jana/0000755000175000017500000000000011327631152011700 5ustar paulliupaulliujana/libjana-gtk/0000755000175000017500000000000011327631152014063 5ustar paulliupaulliujana/libjana-gtk/jana-gtk-event-store.c0000644000175000017500000004264411327631152020206 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include "jana-gtk-event-store.h" G_DEFINE_TYPE (JanaGtkEventStore, jana_gtk_event_store, GTK_TYPE_LIST_STORE) #define EVENT_STORE_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_EVENT_STORE, JanaGtkEventStorePrivate)) typedef struct _JanaGtkEventStorePrivate JanaGtkEventStorePrivate; struct _JanaGtkEventStorePrivate { GHashTable *events_hash; gboolean split; JanaStoreView *view; glong offset; }; enum { PROP_VIEW = 1, PROP_OFFSET, }; static void event_store_added_cb (JanaStoreView *view, GList *components, JanaGtkEventStore *store) { JanaTime *range_start, *range_end; JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (store); jana_store_view_get_range (priv->view, &range_start, &range_end); for (; components; components = components->next) { gchar *uid, *summary, *description, *location, **categories; JanaTime *start, *end; JanaRecurrence *recur; JanaEvent *event; GList *instance, *instances, *iter_list = NULL; gint days, inst_days; glong seconds; if (jana_component_get_component_type (JANA_COMPONENT ( components->data)) != JANA_COMPONENT_EVENT) continue; event = JANA_EVENT (components->data); uid = jana_component_get_uid (JANA_COMPONENT (event)); summary = jana_event_get_summary (event); description = jana_event_get_description (event); location = jana_event_get_location (event); categories = jana_event_get_categories (event); start = jana_event_get_start (event); end = jana_event_get_end (event); recur = jana_event_get_recurrence (event); /* See how many days are between the start and the end so we * can set the first_instance and last_instance parameters * correctly. */ jana_utils_time_diff (start, end, NULL, NULL, &days, NULL, NULL, &seconds); if (days && (seconds == 0)) days--; inst_days = 0; instances = jana_utils_event_get_instances (event, range_start, range_end, priv->offset); for (instance = instances; instance; instance = instance->next){ JanaDuration *duration = (JanaDuration *)instance->data; GtkTreeIter *iter = g_slice_new (GtkTreeIter); iter_list = g_list_append (iter_list, iter); gboolean first, last; if (inst_days == 0) first = TRUE; else first = FALSE; if (inst_days == days) { last = TRUE; inst_days -= (days + 1); } else last = FALSE; gtk_list_store_insert_with_values ( GTK_LIST_STORE (store), iter, 0, JANA_GTK_EVENT_STORE_COL_UID, uid, JANA_GTK_EVENT_STORE_COL_SUMMARY, summary, JANA_GTK_EVENT_STORE_COL_DESCRIPTION, description, JANA_GTK_EVENT_STORE_COL_LOCATION, location, JANA_GTK_EVENT_STORE_COL_CATEGORIES, categories, JANA_GTK_EVENT_STORE_COL_START, duration->start, JANA_GTK_EVENT_STORE_COL_END, duration->end, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, first, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, last, JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, jana_event_has_recurrence (event), JANA_GTK_EVENT_STORE_COL_HAS_ALARM, jana_event_has_alarm (event), JANA_GTK_EVENT_STORE_COL_RECUR_TYPE, recur, -1); inst_days ++; } g_hash_table_insert (priv->events_hash, (gpointer)uid, iter_list); jana_utils_instance_list_free (instances); /* Don't free uid, it'll be freed by the hash table */ /*g_free (uid);*/ g_free (summary); g_free (description); g_free (location); g_strfreev (categories); g_object_unref (start); g_object_unref (end); jana_recurrence_free (recur); } if (range_start) g_object_unref (range_start); if (range_end) g_object_unref (range_end); } static void event_store_modified_cb (JanaStoreView *view, GList *components, JanaGtkEventStore *store) { JanaTime *range_start, *range_end; JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (store); jana_store_view_get_range (priv->view, &range_start, &range_end); for (; components; components = components->next) { GList *instance, *instances, *iter_list; gchar *uid, *summary, *description, *location, **categories; gpointer orig_uid, orig_list; JanaTime *start, *end; JanaRecurrence *recur; gint days, inst_days; gint iter_count = 0; GtkTreeIter *iter; JanaEvent *event; glong seconds; if (jana_component_get_component_type (components->data) != JANA_COMPONENT_EVENT) continue; event = JANA_EVENT (components->data); uid = jana_component_get_uid (JANA_COMPONENT (event)); if (!g_hash_table_lookup_extended ( priv->events_hash, uid, &orig_uid, &orig_list)) { g_free (uid); continue; } iter_list = (GList *)orig_list; summary = jana_event_get_summary (event); description = jana_event_get_description (event); location = jana_event_get_location (event); categories = jana_event_get_categories (event); start = jana_event_get_start (event); end = jana_event_get_end (event); recur = jana_event_get_recurrence (event); jana_utils_time_diff (start, end, NULL, NULL, &days, NULL, NULL, &seconds); if (days && (seconds == 0)) days--; inst_days = 0; /* Go through instances, naively changing ones that already * exist, trimming if there are too many and adding if there * aren't enough. As we can't know the nature of the change, * there's nothing better we can do here. */ instances = jana_utils_event_get_instances (event, range_start, range_end, priv->offset); for (instance = instances; instance; instance = instance->next){ JanaDuration *duration = (JanaDuration *)instance->data; gboolean first, last; if (inst_days == 0) first = TRUE; else first = FALSE; if (inst_days == days) { last = TRUE; inst_days -= (days + 1); } else last = FALSE; iter = (GtkTreeIter *)g_list_nth_data ( iter_list, iter_count); if (iter) { /* Change row */ gtk_list_store_set ( GTK_LIST_STORE (store), iter, JANA_GTK_EVENT_STORE_COL_UID, uid, JANA_GTK_EVENT_STORE_COL_SUMMARY, summary, JANA_GTK_EVENT_STORE_COL_DESCRIPTION, description, JANA_GTK_EVENT_STORE_COL_LOCATION, location, JANA_GTK_EVENT_STORE_COL_CATEGORIES, categories, JANA_GTK_EVENT_STORE_COL_START, duration->start, JANA_GTK_EVENT_STORE_COL_END, duration->end, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, first, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, last, JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, jana_event_has_recurrence (event), JANA_GTK_EVENT_STORE_COL_HAS_ALARM, jana_event_has_alarm (event), JANA_GTK_EVENT_STORE_COL_RECUR_TYPE, recur, -1); } else { /* Add new row */ iter = g_slice_new (GtkTreeIter); gtk_list_store_insert_with_values ( GTK_LIST_STORE (store), iter, 0, JANA_GTK_EVENT_STORE_COL_UID, uid, JANA_GTK_EVENT_STORE_COL_SUMMARY, summary, JANA_GTK_EVENT_STORE_COL_DESCRIPTION, description, JANA_GTK_EVENT_STORE_COL_LOCATION, location, JANA_GTK_EVENT_STORE_COL_CATEGORIES, categories, JANA_GTK_EVENT_STORE_COL_START, duration->start, JANA_GTK_EVENT_STORE_COL_END, duration->end, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, first, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, last, JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, jana_event_has_recurrence (event), JANA_GTK_EVENT_STORE_COL_HAS_ALARM, jana_event_has_alarm (event), JANA_GTK_EVENT_STORE_COL_RECUR_TYPE, recur, -1); iter_list = g_list_append (iter_list, iter); } iter_count ++; inst_days ++; } /* Trim off instances if there are too many */ while ((instance = g_list_nth (iter_list, iter_count))) { iter = (GtkTreeIter *)instance->data; gtk_list_store_remove ( GTK_LIST_STORE (store), iter); g_slice_free (GtkTreeIter, iter); iter_list = g_list_delete_link (iter_list, instance); } jana_utils_instance_list_free (instances); g_hash_table_steal (priv->events_hash, orig_uid); g_free (orig_uid); g_hash_table_insert (priv->events_hash, uid, iter_list); g_free (summary); g_free (description); g_free (location); g_strfreev (categories); g_object_unref (start); g_object_unref (end); jana_recurrence_free (recur); } if (range_start) g_object_unref (range_start); if (range_end) g_object_unref (range_end); } static void event_store_removed_cb (JanaStoreView *view, GList *uids, JanaGtkEventStore *store) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (store); for (; uids; uids = uids->next) { const gchar *uid = (const gchar *)uids->data; GList *iter_list; iter_list = (GList *)g_hash_table_lookup ( priv->events_hash, uid); if (!iter_list) continue; for (; iter_list; iter_list = iter_list->next) { GtkTreeIter *iter = (GtkTreeIter *)iter_list->data; gtk_list_store_remove (GTK_LIST_STORE (store), iter); } g_hash_table_remove (priv->events_hash, uid); } } static void jana_gtk_event_store_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (object); switch (property_id) { case PROP_VIEW : g_value_set_object (value, priv->view); break; case PROP_OFFSET : g_value_set_long (value, priv->offset); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_event_store_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_VIEW : jana_gtk_event_store_set_view (JANA_GTK_EVENT_STORE (object), g_value_get_object (value)); break; case PROP_OFFSET : jana_gtk_event_store_set_offset (JANA_GTK_EVENT_STORE (object), g_value_get_long (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_event_store_dispose (GObject *object) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (object); if (priv->view) { g_object_unref (priv->view); priv->view = NULL; } if (G_OBJECT_CLASS (jana_gtk_event_store_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_event_store_parent_class)->dispose ( object); } static void jana_gtk_event_store_finalize (GObject *object) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (object); g_hash_table_destroy (priv->events_hash); G_OBJECT_CLASS (jana_gtk_event_store_parent_class)->finalize (object); } static void jana_gtk_event_store_class_init (JanaGtkEventStoreClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkEventStorePrivate)); object_class->get_property = jana_gtk_event_store_get_property; object_class->set_property = jana_gtk_event_store_set_property; object_class->dispose = jana_gtk_event_store_dispose; object_class->finalize = jana_gtk_event_store_finalize; g_object_class_install_property ( object_class, PROP_VIEW, g_param_spec_object ( "view", "JanaStoreView *", "The JanaStoreView monitored.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_OFFSET, g_param_spec_long ( "offset", "glong", "The time offset to use when instancing events.", -G_MAXLONG, G_MAXLONG, 0, G_PARAM_READWRITE)); } static gint jana_gtk_event_store_compare (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { JanaTime *start1, *end1, *start2, *end2; gchar *summary1, *summary2; gint result = 0; JanaGtkEventStore *store = JANA_GTK_EVENT_STORE (user_data); gtk_tree_model_get (GTK_TREE_MODEL (store), a, JANA_GTK_EVENT_STORE_COL_START, &start1, JANA_GTK_EVENT_STORE_COL_END, &end1, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary1, -1); gtk_tree_model_get (GTK_TREE_MODEL (store), b, JANA_GTK_EVENT_STORE_COL_START, &start2, JANA_GTK_EVENT_STORE_COL_END, &end2, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary2, -1); if (start1 && start2) { result = jana_utils_time_compare (start1, start2, FALSE); if (result == 0) result = jana_utils_time_compare ( end2, end1, FALSE); } if (summary1 && summary2) if (result == 0) result = strcmp (summary1, summary2); g_free (summary1); g_free (summary2); g_object_unref (start1); g_object_unref (start2); g_object_unref (end1); g_object_unref (end2); return result; } void event_store_free_iter_list (gpointer data) { GList *iter_list = (GList *)data; while (iter_list) { g_slice_free (GtkTreeIter, iter_list->data); iter_list = g_list_delete_link (iter_list, iter_list); } } static void jana_gtk_event_store_init (JanaGtkEventStore *self) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (self); priv->view = NULL; priv->events_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, event_store_free_iter_list); gtk_list_store_set_column_types (GTK_LIST_STORE (self), JANA_GTK_EVENT_STORE_COL_LAST, (GType []){G_TYPE_STRING, /* UID */ G_TYPE_STRING, /* SUMMARY */ G_TYPE_STRING, /* DESCRIPTION */ G_TYPE_STRING, /* LOCATION */ G_TYPE_STRV, /* CATEGORIES */ G_TYPE_OBJECT, /* START */ G_TYPE_OBJECT, /* END */ G_TYPE_BOOLEAN, /* FIRST_INSTANCE */ G_TYPE_BOOLEAN, /* LAST_INSTANCE */ G_TYPE_BOOLEAN, /* HAS_RECURRENCES */ G_TYPE_BOOLEAN, /* HAS_ALARM */ JANA_TYPE_RECURRENCE,/* RECUR_TYPE */ }); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (self), JANA_GTK_EVENT_STORE_COL_START, jana_gtk_event_store_compare, self, NULL); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self), JANA_GTK_EVENT_STORE_COL_START, GTK_SORT_ASCENDING); } GtkTreeModel * jana_gtk_event_store_new (void) { return (GtkTreeModel *)g_object_new (JANA_GTK_TYPE_EVENT_STORE, NULL); } GtkTreeModel * jana_gtk_event_store_new_full (JanaStoreView *view, glong offset) { return (GtkTreeModel *)g_object_new (JANA_GTK_TYPE_EVENT_STORE, "view", view, "offset", offset, NULL); } void jana_gtk_event_store_set_view (JanaGtkEventStore *store, JanaStoreView *view) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (store); if (priv->view) { g_signal_handlers_disconnect_by_func ( priv->view, event_store_added_cb, store); g_signal_handlers_disconnect_by_func ( priv->view, event_store_modified_cb, store); g_signal_handlers_disconnect_by_func ( priv->view, event_store_removed_cb, store); g_object_unref (priv->view); priv->view = NULL; g_hash_table_remove_all (priv->events_hash); gtk_list_store_clear (GTK_LIST_STORE (store)); } if (view) { priv->view = g_object_ref (view); g_signal_connect (priv->view, "added", G_CALLBACK (event_store_added_cb), store); g_signal_connect (priv->view, "modified", G_CALLBACK (event_store_modified_cb), store); g_signal_connect (priv->view, "removed", G_CALLBACK (event_store_removed_cb), store); } } JanaStoreView * jana_gtk_event_store_get_view (JanaGtkEventStore *store) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (store); return priv->view ? g_object_ref (priv->view) : NULL; } JanaStore * jana_gtk_event_store_get_store (JanaGtkEventStore *self) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (self); if (priv->view) { return jana_store_view_get_store (priv->view); } else return NULL; } typedef struct { JanaStore *store; GList *components; } ChangeEventsData; static void change_events_cb (gpointer key, gpointer value, gpointer user_data) { ChangeEventsData *data = (ChangeEventsData *)user_data; const gchar *uid = (const gchar *)key; JanaComponent *comp = jana_store_get_component (data->store, uid); data->components = g_list_prepend (data->components, comp); } /** * jana_gtk_event_store_set_offset: * @self: A #JanaGtkEventStore * @offset: Time offset, in seconds * * Sets the time offset that should be used when splitting events into day * instances. */ void jana_gtk_event_store_set_offset (JanaGtkEventStore *self, glong offset) { JanaGtkEventStorePrivate *priv = EVENT_STORE_PRIVATE (self); ChangeEventsData data; if (priv->offset == offset) return; priv->offset = offset; /* Re-instance all events by firing the modified signal on them */ data.store = jana_store_view_get_store (priv->view); data.components = NULL; /* Create a list of all the components */ g_hash_table_foreach (priv->events_hash, change_events_cb, &data); /* Send them to the modified callback */ event_store_modified_cb (priv->view, data.components, self); /* Free components */ while (data.components) { g_object_unref ((GObject *)data.components->data); data.components = g_list_delete_link ( data.components, data.components); } g_object_unref (data.store); } jana/libjana-gtk/jana-gtk-year-view.h0000644000175000017500000000532511327631152017643 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_YEAR_VIEW_H #define _JANA_GTK_YEAR_VIEW_H #include #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_YEAR_VIEW jana_gtk_year_view_get_type() #define JANA_GTK_YEAR_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_YEAR_VIEW, JanaGtkYearView)) #define JANA_GTK_YEAR_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_YEAR_VIEW, JanaGtkYearViewClass)) #define JANA_GTK_IS_YEAR_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_YEAR_VIEW)) #define JANA_GTK_IS_YEAR_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_YEAR_VIEW)) #define JANA_GTK_YEAR_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_YEAR_VIEW, JanaGtkYearViewClass)) typedef struct { GtkTable parent; } JanaGtkYearView; typedef struct { GtkTableClass parent_class; /* Signals */ void (*selection_changed) (JanaGtkYearView *self, gint month); } JanaGtkYearViewClass; GType jana_gtk_year_view_get_type (void); GtkWidget * jana_gtk_year_view_new (guint months_per_row, JanaTime *year); void jana_gtk_year_view_add_store (JanaGtkYearView *self, JanaGtkEventStore *store); void jana_gtk_year_view_remove_store (JanaGtkYearView *self, JanaGtkEventStore *store); void jana_gtk_year_view_set_year (JanaGtkYearView *self, JanaTime *year); JanaTime * jana_gtk_year_view_get_year (JanaGtkYearView *self); void jana_gtk_year_view_set_months_per_row (JanaGtkYearView *self, guint months_per_row); gint jana_gtk_year_view_get_selected_month (JanaGtkYearView *self); void jana_gtk_year_view_set_selected_month (JanaGtkYearView *self, gint month); void jana_gtk_year_view_set_highlighted_time (JanaGtkYearView *self, JanaTime *time); G_END_DECLS #endif /* _JANA_GTK_YEAR_VIEW_H */ jana/libjana-gtk/jana-gtk-year-view.c0000644000175000017500000003762611327631152017647 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include "jana-gtk-year-view.h" G_DEFINE_TYPE (JanaGtkYearView, jana_gtk_year_view, GTK_TYPE_TABLE) #define YEAR_VIEW_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_YEAR_VIEW, \ JanaGtkYearViewPrivate)) typedef struct _JanaGtkYearViewPrivate JanaGtkYearViewPrivate; struct _JanaGtkYearViewPrivate { /* The event box containing the month labels and such */ GtkWidget *boxes[12]; /* The month labels */ GtkWidget *month_labels[12]; /* The labels showing how many events in the month there are */ GtkWidget *events_labels[12]; /* Amount of events in a particular month */ guint events[12]; JanaTime *year; gint selected_month; /* List of JanaGtkEventStore's */ GList *stores; JanaTime *highlighted_time; }; enum { PROP_MONTHS_PER_ROW = 1, PROP_YEAR, PROP_HIGHLIGHTED_TIME, }; enum { SELECTION_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void recount_events (JanaGtkYearView *self) { gint month, year; GList *stores; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); /* Reset event count */ for (month = 0; month < 12; month++) priv->events[month] = 0; year = priv->year ? jana_time_get_year (priv->year) : 0; /* Iterate through all stores and count events per month */ for (stores = priv->stores; stores; stores = stores->next) { GtkTreeIter iter; JanaGtkEventStore *store = (JanaGtkEventStore *)stores->data; if (gtk_tree_model_get_iter_first ( (GtkTreeModel *)store, &iter)) do { JanaTime *start, *old_start; gtk_tree_model_get ((GtkTreeModel *)store, &iter, JANA_GTK_EVENT_STORE_COL_START, &old_start, -1); if (!old_start) continue; /* Adjust for timezones */ start = jana_time_duplicate (old_start); jana_time_set_offset (start, jana_time_get_offset (priv->year)); if (jana_time_get_year (start) == year) priv->events[jana_time_get_month (start)-1] ++; g_object_unref (start); g_object_unref (old_start); } while (gtk_tree_model_iter_next ( (GtkTreeModel *)store, &iter)); } /* Set labels */ for (month = 0; month < 12; month++) { if (priv->events[month]) { gchar *number = g_strdup_printf ( "%d", priv->events[month]); gtk_label_set_text (GTK_LABEL ( priv->events_labels[month]), number); g_free (number); } else { gtk_label_set_text (GTK_LABEL ( priv->events_labels[month]), "-"); } } } static void jana_gtk_year_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (object); switch (property_id) { case PROP_YEAR : if (priv->year) g_value_take_object ( value, jana_time_duplicate (priv->year)); break; case PROP_HIGHLIGHTED_TIME : if (priv->highlighted_time) g_value_take_object (value, jana_time_duplicate (priv->highlighted_time)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_year_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkYearView *year_view = JANA_GTK_YEAR_VIEW (object); switch (property_id) { case PROP_YEAR : jana_gtk_year_view_set_year (year_view, g_value_get_object (value)); break; case PROP_MONTHS_PER_ROW : jana_gtk_year_view_set_months_per_row ( JANA_GTK_YEAR_VIEW (object), g_value_get_uint (value)); break; case PROP_HIGHLIGHTED_TIME : jana_gtk_year_view_set_highlighted_time ( JANA_GTK_YEAR_VIEW (object), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void row_deleted_cb (GtkTreeModel *tree_model, GtkTreePath *path, JanaGtkYearView *self) { recount_events (self); } static void row_changed_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkYearView *self) { recount_events (self); } static void row_inserted_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkYearView *self) { /* TODO: Just consider this one row rather than recounting all the * events. */ recount_events (self); } static void jana_gtk_year_view_dispose (GObject *object) { gint i; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (object); for (i = 0; i < 12; i++) { if (priv->boxes[i]) { g_object_unref (priv->boxes[i]); priv->boxes[i] = NULL; } } while (priv->stores) { GObject *store = (GObject *)priv->stores->data; g_signal_handlers_disconnect_by_func ( store, row_inserted_cb, object); g_signal_handlers_disconnect_by_func ( store, row_changed_cb, object); g_signal_handlers_disconnect_by_func ( store, row_deleted_cb, object); g_object_unref (store); priv->stores = g_list_delete_link (priv->stores, priv->stores); } if (G_OBJECT_CLASS (jana_gtk_year_view_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_year_view_parent_class)-> dispose (object); } static void jana_gtk_year_view_finalize (GObject *object) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (object); if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } G_OBJECT_CLASS (jana_gtk_year_view_parent_class)->finalize (object); } static void jana_gtk_year_view_class_init (JanaGtkYearViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkYearViewPrivate)); object_class->get_property = jana_gtk_year_view_get_property; object_class->set_property = jana_gtk_year_view_set_property; object_class->dispose = jana_gtk_year_view_dispose; object_class->finalize = jana_gtk_year_view_finalize; g_object_class_install_property ( object_class, PROP_MONTHS_PER_ROW, g_param_spec_uint ( "months_per_row", "Months per row", "Months to display per row.", 1, 12, 3, G_PARAM_WRITABLE)); g_object_class_install_property ( object_class, PROP_YEAR, g_param_spec_object ( "year", "Year", "Year to count events in.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_TIME, g_param_spec_object ( "highlighted_time", "Highlighted time", "A time that should be highlighted, " "for example, the current time.", G_TYPE_OBJECT, G_PARAM_READWRITE)); signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkYearViewClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_INT); } static gboolean button_press_event_cb (GtkWidget *widget, GdkEventButton *event, JanaGtkYearView *self) { gint month; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); month = GPOINTER_TO_INT (g_object_get_data ( G_OBJECT (widget), "month")); if ((month) && (month != priv->selected_month)) { if (priv->selected_month) { priv->selected_month --; gtk_widget_set_state (priv->boxes[ priv->selected_month], GTK_STATE_NORMAL); gtk_widget_set_state (priv->month_labels[ priv->selected_month], GTK_STATE_NORMAL); gtk_widget_set_state (priv->events_labels[ priv->selected_month], GTK_STATE_NORMAL); } priv->selected_month = month; month --; gtk_widget_set_state (priv->boxes[month], GTK_STATE_SELECTED); gtk_widget_set_state (priv->month_labels[month], GTK_STATE_SELECTED); gtk_widget_set_state (priv->events_labels[month], GTK_STATE_SELECTED); g_signal_emit (self, signals[SELECTION_CHANGED], 0, priv->selected_month); } return FALSE; } static void regenerate_labels (JanaGtkYearView *self) { gint month; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); for (month = 0; month < 12; month++) { GtkLabel *label = GTK_LABEL (priv->month_labels[month]); if (priv->highlighted_time && priv->year && (jana_time_get_month ( priv->highlighted_time) == (month + 1)) && (jana_time_get_year (priv->year) == jana_time_get_year (priv->highlighted_time))) { gchar *markup; gtk_label_set_use_markup (label, TRUE); markup = g_strdup_printf ("%s", nl_langinfo (ABMON_1+month)); gtk_label_set_markup (label, markup); g_free (markup); } else { gtk_label_set_use_markup (label, FALSE); gtk_label_set_text (label, nl_langinfo (ABMON_1+month)); } } } static void jana_gtk_year_view_init (JanaGtkYearView *self) { gint month; static gboolean locale_set = FALSE; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); if (!locale_set) { setlocale (LC_TIME, ""); locale_set = TRUE; } for (month = 0; month < 12; month++) { GtkWidget *vbox; priv->boxes[month] = g_object_ref (gtk_event_box_new ()); priv->month_labels[month] = gtk_label_new (NULL); priv->events_labels[month] = gtk_label_new ("-"); priv->events[month] = 0; g_object_set_data (G_OBJECT (priv->boxes[month]), "month", GINT_TO_POINTER (month + 1)); vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), priv->month_labels[month], TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (vbox), priv->events_labels[month], TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (priv->boxes[month]), vbox); gtk_widget_show_all (priv->boxes[month]); g_signal_connect (priv->boxes[month], "button-press-event", G_CALLBACK (button_press_event_cb), self); } regenerate_labels (self); } /** * jana_gtk_year_view_new: * @months_per_row: Number of months to pack into a row * @year: The year to count events in * * Create a new widget that provides a summary of events over @year. * * Returns: A new #JanaGtkYearView widget. */ GtkWidget * jana_gtk_year_view_new (guint months_per_row, JanaTime *year) { return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_YEAR_VIEW, "months_per_row", months_per_row, "year", year, NULL)); } /** * jana_gtk_year_view_add_store: * @self: A #JanaGtkYearView * @store: A #JanaGtkEventStore * * Adds @store to the list of #JanaGtkEventStore objects used in visualising * the year. */ void jana_gtk_year_view_add_store (JanaGtkYearView *self, JanaGtkEventStore *store) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); priv->stores = g_list_prepend (priv->stores, g_object_ref (store)); recount_events (self); g_signal_connect (store, "row-inserted", G_CALLBACK (row_inserted_cb), self); g_signal_connect (store, "row-changed", G_CALLBACK (row_changed_cb), self); g_signal_connect (store, "row-deleted", G_CALLBACK (row_deleted_cb), self); } /** * jana_gtk_year_view_remove_store: * @self: A #JanaGtkYearView * @store: A #JanaGtkEventStore * * Removes @store from the list of #JanaGtkEventStore objects used in * visualising the year. If @store has not previously been added with * jana_gtk_year_view_add_store(), nothing happens. */ void jana_gtk_year_view_remove_store (JanaGtkYearView *self, JanaGtkEventStore *store) { GList *link; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); if (!(link = g_list_find (priv->stores, store))) return; g_signal_handlers_disconnect_by_func (store, row_inserted_cb, self); g_signal_handlers_disconnect_by_func (store, row_changed_cb, self); g_signal_handlers_disconnect_by_func (store, row_deleted_cb, self); g_object_unref (store); priv->stores = g_list_delete_link (priv->stores, link); recount_events (self); } /** * jana_gtk_year_view_set_year: * @self: A #JanaGtkYearView * @year: The year to count events in * * Set the year for @self to count events in. */ void jana_gtk_year_view_set_year (JanaGtkYearView *self, JanaTime *year) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); if (priv->year) { g_object_unref (priv->year); priv->year = NULL; } if (year) { priv->year = jana_time_duplicate (year); jana_time_set_isdate (priv->year, TRUE); jana_time_set_day (priv->year, 1); jana_time_set_month (priv->year, 1); regenerate_labels (self); recount_events (self); } } /** * jana_gtk_year_view_get_year: * @self: A #JanaGtkYearView * * Gets the year @self is counting events in. * * Returns: The year @self is counting events in. */ JanaTime * jana_gtk_year_view_get_year (JanaGtkYearView *self) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); return jana_time_duplicate (priv->year); } static void container_remove_swapped (GtkWidget *widget, gpointer container) { gtk_container_remove (GTK_CONTAINER (container), widget); } /** * jana_gtk_year_view_set_months_per_row: * @self: A #JanaGtkYearView * @months_per_row: Months to pack per row, between 1 and 12, inclusive * * Set the number of months for @self to pack into a row. */ void jana_gtk_year_view_set_months_per_row (JanaGtkYearView *self, guint months_per_row) { gint month, cols; JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); g_assert ((months_per_row > 0) && (months_per_row <= 12)); /* Empty container */ gtk_container_foreach (GTK_CONTAINER (self), container_remove_swapped, self); /* Pack month boxes */ cols = months_per_row; for (month = 0; month < 12; month++) { gtk_table_attach (GTK_TABLE (self), priv->boxes[month], month % cols, (month % cols) + 1, month / cols, (month / cols) + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); } } /** * jana_gtk_year_view_get_selected_month: * @self: A #JanaGtkYearView * * Gets the currently selected month, between 0 and 12 inclusive. 0 * corresponds to there being no event selected. * * Returns: The selected month, 1 - 12, or 0 if there is no selected month. */ gint jana_gtk_year_view_get_selected_month (JanaGtkYearView *self) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); return priv->selected_month; } /** * jana_gtk_year_view_set_selected_month: * @self: A #JanaGtkYearView * @month: A month (1 - 12), or 0 to clear the selection * * Sets or clears the selected month. */ void jana_gtk_year_view_set_selected_month (JanaGtkYearView *self, gint month) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); g_assert ((month >= 0) && (month <= 12)); if (priv->selected_month == month) return; if (month) { button_press_event_cb (priv->boxes[month-1], NULL, self); } else { priv->selected_month --; gtk_widget_set_state (priv->boxes[ priv->selected_month], GTK_STATE_NORMAL); gtk_widget_set_state (priv->month_labels[ priv->selected_month], GTK_STATE_NORMAL); gtk_widget_set_state (priv->events_labels[ priv->selected_month], GTK_STATE_NORMAL); priv->selected_month = 0; g_signal_emit (self, signals[SELECTION_CHANGED], 0, 0); } } /** * jana_gtk_year_view_set_highlighted_time: * @self: A #JanaGtkYearView * @time: A #JanaTime * * Sets a time to be highlighted. This can be used to highlight the current * time, for example. */ void jana_gtk_year_view_set_highlighted_time (JanaGtkYearView *self, JanaTime *time) { JanaGtkYearViewPrivate *priv = YEAR_VIEW_PRIVATE (self); if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } if (time) { priv->highlighted_time = jana_time_duplicate (time); jana_time_set_offset (priv->highlighted_time, jana_time_get_offset (priv->year)); } regenerate_labels (self); } jana/libjana-gtk/jana-gtk-event-store.h0000644000175000017500000000545111327631152020206 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_EVENT_STORE #define _JANA_GTK_EVENT_STORE #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_EVENT_STORE jana_gtk_event_store_get_type() #define JANA_GTK_EVENT_STORE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_EVENT_STORE, JanaGtkEventStore)) #define JANA_GTK_EVENT_STORE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_EVENT_STORE, JanaGtkEventStoreClass)) #define JANA_GTK_IS_EVENT_STORE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_EVENT_STORE)) #define JANA_GTK_IS_EVENT_STORE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_EVENT_STORE)) #define JANA_GTK_EVENT_STORE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_EVENT_STORE, JanaGtkEventStoreClass)) typedef struct { GtkListStore parent; } JanaGtkEventStore; typedef struct { GtkListStoreClass parent_class; } JanaGtkEventStoreClass; enum { JANA_GTK_EVENT_STORE_COL_UID, JANA_GTK_EVENT_STORE_COL_SUMMARY, JANA_GTK_EVENT_STORE_COL_DESCRIPTION, JANA_GTK_EVENT_STORE_COL_LOCATION, JANA_GTK_EVENT_STORE_COL_CATEGORIES, JANA_GTK_EVENT_STORE_COL_START, JANA_GTK_EVENT_STORE_COL_END, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, JANA_GTK_EVENT_STORE_COL_HAS_ALARM, JANA_GTK_EVENT_STORE_COL_RECUR_TYPE, JANA_GTK_EVENT_STORE_COL_LAST }; GType jana_gtk_event_store_get_type (void); GtkTreeModel * jana_gtk_event_store_new (void); GtkTreeModel * jana_gtk_event_store_new_full (JanaStoreView *view, glong offset); void jana_gtk_event_store_set_view (JanaGtkEventStore *store, JanaStoreView *view); JanaStoreView * jana_gtk_event_store_get_view (JanaGtkEventStore *store); JanaStore * jana_gtk_event_store_get_store (JanaGtkEventStore *store); void jana_gtk_event_store_set_offset (JanaGtkEventStore *self, glong offset); G_END_DECLS #endif /* _JANA_GTK_EVENT_STORE */ jana/libjana-gtk/jana-gtk-recurrence.h0000644000175000017500000000455011327631152020067 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_RECURRENCE_H #define _JANA_GTK_RECURRENCE_H #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_RECURRENCE jana_gtk_recurrence_get_type() #define JANA_GTK_RECURRENCE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_RECURRENCE, JanaGtkRecurrence)) #define JANA_GTK_RECURRENCE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_RECURRENCE, JanaGtkRecurrenceClass)) #define JANA_GTK_IS_RECURRENCE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_RECURRENCE)) #define JANA_GTK_IS_RECURRENCE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_RECURRENCE)) #define JANA_GTK_RECURRENCE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_RECURRENCE, JanaGtkRecurrenceClass)) typedef struct { GtkVBox parent; } JanaGtkRecurrence; typedef struct { GtkVBoxClass parent_class; } JanaGtkRecurrenceClass; GType jana_gtk_recurrence_get_type (void); GtkWidget * jana_gtk_recurrence_new (void); void jana_gtk_recurrence_set_recur (JanaGtkRecurrence *self, JanaRecurrence *recur); void jana_gtk_recurrence_set_editable (JanaGtkRecurrence *self, gboolean editable); void jana_gtk_recurrence_set_time (JanaGtkRecurrence *self, JanaTime *time); JanaRecurrence * jana_gtk_recurrence_get_recur (JanaGtkRecurrence *self); gboolean jana_gtk_recurrence_get_editable (JanaGtkRecurrence *self); JanaTime * jana_gtk_recurrence_get_time (JanaGtkRecurrence *self); G_END_DECLS #endif /* _JANA_GTK_RECURRENCE_H */ jana/libjana-gtk/jana-gtk-tree-layout.c0000644000175000017500000010207011327631152020173 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include "jana-gtk-tree-layout.h" G_DEFINE_TYPE (JanaGtkTreeLayout, jana_gtk_tree_layout, GTK_TYPE_EVENT_BOX) #define TREE_LAYOUT_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_TREE_LAYOUT, \ JanaGtkTreeLayoutPrivate)) typedef struct _JanaGtkTreeLayoutPrivate JanaGtkTreeLayoutPrivate; struct _JanaGtkTreeLayoutPrivate { GCompareDataFunc sort_cb; gpointer sort_data; gboolean single_click; GtkSelectionMode select_mode; gboolean fill_width; gboolean fill_height; GtkTreeModelFilterVisibleFunc visible_cb; gpointer visible_data; GList *cells; GList *visible_cells; GList **cells_ptr; GHashTable *models; JanaGtkTreeLayoutCellInfo *hover; GList *select; guint select_idle; }; enum { PROP_SORT_CB = 1, PROP_SORT_DATA, PROP_SINGLE_CLICK, PROP_SELECT_MODE, PROP_FILL_WIDTH, PROP_FILL_HEIGHT, PROP_VISIBLE_CB, PROP_VISIBLE_DATA, }; enum { SELECTION_CHANGED, CELL_ACTIVATED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void tree_layout_add_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height, GtkCellRenderer *renderer, va_list args); static void tree_layout_move_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height); static void tree_layout_remove_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row); static void tree_layout_clear (JanaGtkTreeLayout *self); static void tree_layout_remove_cell_with_list (JanaGtkTreeLayout *self, GList *info_list); static gint find_point_cb (gconstpointer a, gconstpointer b) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)a; GdkPoint *point = (GdkPoint *)b; if ((point->x < info->real_x) || (point->y < info->real_y)) return 1; else if ((point->x > info->real_x + info->real_width) || (point->y > info->real_y + info->real_height)) return -1; else return 0; } static gint find_row_cb (gconstpointer a, gconstpointer b) { gint result; GtkTreePath *path_a, *path_b; path_a = gtk_tree_row_reference_get_path ( ((JanaGtkTreeLayoutCellInfo *)a)->row); path_b = gtk_tree_row_reference_get_path ((GtkTreeRowReference *)b); result = gtk_tree_path_compare (path_a, path_b); gtk_tree_path_free (path_a); gtk_tree_path_free (path_b); return result; } static void free_info (JanaGtkTreeLayoutCellInfo *info) { g_object_unref (info->renderer); while (info->attributes) { /* Column ID */ info->attributes = g_list_delete_link (info->attributes, info->attributes); /* Property name */ g_free (info->attributes->data); info->attributes = g_list_delete_link (info->attributes, info->attributes); } g_slice_free (JanaGtkTreeLayoutCellInfo, info); } static void tree_layout_row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GtkTreeRowReference *row; GList *info_list; row = gtk_tree_row_reference_new (model, path); info_list = g_list_find_custom ( priv->cells, row, find_row_cb); gtk_tree_row_reference_free (row); if (info_list) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if (priv->sort_cb) { priv->cells = g_list_sort_with_data (priv->cells, priv->sort_cb, priv->sort_data); } gtk_widget_queue_draw_area (GTK_WIDGET (self), info->real_x + GTK_WIDGET (self)->allocation.x, info->real_y + GTK_WIDGET (self)->allocation.y, info->real_width, info->real_height); if (priv->visible_cb) { info_list = g_list_find (priv->visible_cells, info); if (priv->visible_cb (model, iter, priv->visible_data)){ if (info_list) { if (priv->sort_cb) { priv->visible_cells = g_list_sort_with_data ( priv->visible_cells, priv->sort_cb, priv->sort_data); } } else { priv->visible_cells = g_list_insert_sorted_with_data ( priv->visible_cells, info, priv->sort_cb, priv->sort_data); } } else if (info_list) { priv->visible_cells = g_list_delete_link ( priv->visible_cells, info_list); } } } } static void tree_layout_row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GList *info_list = priv->cells; /* Iterate through cells and remove invalid - we can't search for * a particular row as the row reference is now invalid :( */ while (info_list) { GList *prev_info = info_list; JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)info_list->data; info_list = info_list->next; if (!gtk_tree_row_reference_valid (info->row)) { /* No need to queue a redraw, the widget will be * redrawn due to a possible new size request */ tree_layout_remove_cell_with_list ( self, prev_info); } } } static GList * get_visible_cells (JanaGtkTreeLayout *self) { GList *cell, *cells = NULL; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); for (cell = priv->cells; cell; cell = cell->next) { JanaGtkTreeLayoutCellInfo *info; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; info = (JanaGtkTreeLayoutCellInfo *)cell->data; model = gtk_tree_row_reference_get_model (info->row); path = gtk_tree_row_reference_get_path (info->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); if (priv->visible_cb (model, &iter, priv->visible_data)) cells = g_list_append (cells, info); } return cells; } static void jana_gtk_tree_layout_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (object); switch (property_id) { case PROP_SORT_CB : g_value_set_pointer (value, priv->sort_cb); break; case PROP_SORT_DATA : g_value_set_pointer (value, priv->sort_data); break; case PROP_SINGLE_CLICK : g_value_set_boolean (value, priv->single_click); break; case PROP_SELECT_MODE : g_value_set_enum (value, priv->select_mode); break; case PROP_FILL_WIDTH : g_value_set_boolean (value, priv->fill_width); break; case PROP_FILL_HEIGHT : g_value_set_boolean (value, priv->fill_height); break; case PROP_VISIBLE_CB : g_value_set_pointer (value, priv->visible_cb); break; case PROP_VISIBLE_DATA : g_value_set_pointer (value, priv->visible_data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_tree_layout_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (object); switch (property_id) { case PROP_SORT_CB : priv->sort_cb = g_value_get_pointer (value); if (priv->sort_cb) { priv->cells = g_list_sort_with_data (priv->cells, priv->sort_cb, priv->sort_data); if (priv->visible_cb) priv->visible_cells = g_list_sort_with_data ( priv->visible_cells, priv->sort_cb, priv->sort_data); } break; case PROP_SORT_DATA : priv->sort_data = g_value_get_pointer (value); break; case PROP_SINGLE_CLICK : priv->single_click = g_value_get_boolean (value); break; case PROP_SELECT_MODE : priv->select_mode = g_value_get_enum (value); break; case PROP_FILL_WIDTH : priv->fill_width = g_value_get_boolean (value); break; case PROP_FILL_HEIGHT : priv->fill_height = g_value_get_boolean (value); break; case PROP_VISIBLE_CB : jana_gtk_tree_layout_set_visible_func ( JANA_GTK_TREE_LAYOUT (object), g_value_get_pointer (value), priv->visible_data); break; case PROP_VISIBLE_DATA : priv->visible_data = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_tree_layout_dispose (GObject *object) { jana_gtk_tree_layout_clear (JANA_GTK_TREE_LAYOUT (object)); if (G_OBJECT_CLASS (jana_gtk_tree_layout_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_tree_layout_parent_class)-> dispose (object); } static void jana_gtk_tree_layout_finalize (GObject *object) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (object); g_hash_table_destroy (priv->models); G_OBJECT_CLASS (jana_gtk_tree_layout_parent_class)->finalize (object); } static void tree_layout_set_properties (JanaGtkTreeLayoutCellInfo *info) { GList *attr; GtkTreeModel *model; GtkTreeIter iter; GtkTreePath *path; GValue value = { 0, }; model = gtk_tree_row_reference_get_model (info->row); path = gtk_tree_row_reference_get_path (info->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); /* Set properties */ for (attr = info->attributes; attr && attr->next; attr = attr->next->next) { gtk_tree_model_get_value (model, &iter, GPOINTER_TO_INT (attr->data), &value); g_object_set_property (G_OBJECT (info->renderer), (gchar *)attr->next->data, &value); g_value_unset (&value); } } static gboolean jana_gtk_tree_layout_expose_event (GtkWidget *widget, GdkEventExpose *event) { GList *c; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (widget); /* Draw these in the reverse order to how we handle mouse operations, * that way cells that obscure other cells appear to have priority. */ for (c = g_list_last (*priv->cells_ptr); c; c = c->prev) { GdkRectangle cell_area; GtkCellRendererState state = 0; JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)c->data; if ((info->real_width < 0) || (info->real_height < 0)) continue; tree_layout_set_properties (info); cell_area.x = info->real_x + widget->allocation.x; cell_area.y = info->real_y + widget->allocation.y; cell_area.width = info->real_width; cell_area.height = info->real_height; if (info == priv->hover) state |= GTK_CELL_RENDERER_PRELIT; if (g_list_find (priv->select, info)) state |= GTK_CELL_RENDERER_SELECTED; if (!info->sensitive) state |= GTK_CELL_RENDERER_INSENSITIVE; gtk_cell_renderer_render (info->renderer, widget->window, widget, &cell_area, &cell_area, &event->area, state); } return FALSE; } static void tree_layout_get_size (JanaGtkTreeLayout *self, gint *width, gint *height) { GList *c; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); if (width) *width = 0; if (height) *height = 0; for (c = *priv->cells_ptr; c; c = c->next) { gint size; JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)c->data; if (width) { size = info->real_x + info->real_width; if (size > *width) *width = size; } if (height) { size = info->real_y + info->real_height; if (size > *height) *height = size; } } } static void jana_gtk_tree_layout_size_request (GtkWidget *widget, GtkRequisition *requisition) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (widget); requisition->width = 0; requisition->height = 0; if (priv->fill_width && priv->fill_height) return; tree_layout_get_size (JANA_GTK_TREE_LAYOUT (widget), priv->fill_width ? NULL : &requisition->width, priv->fill_height ? NULL : &requisition->height); } static void jana_gtk_tree_layout_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GList *c; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (widget); GTK_WIDGET_CLASS (jana_gtk_tree_layout_parent_class)->size_allocate ( widget, allocation); /* Work out real size of cells (necessary for width|height == -1) */ for (c = *priv->cells_ptr; c; c = c->next) { gint x_offset, y_offset, old_width, old_height, width, height; GdkRectangle cell_area; JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)c->data; if ((info->width >= 0) && (info->height >= 0)) continue; if ((allocation->width == 0) || (allocation->height == 0)) continue; /* Find real width/height */ cell_area.x = info->real_x; cell_area.y = info->real_y; cell_area.width = (info->width < 0) ? (allocation->width - info->real_x) : info->real_width; cell_area.height = (info->height < 0) ? (allocation->height - info->real_y) : info->real_height; old_width = info->real_width; old_height = info->real_height; tree_layout_set_properties (info); gtk_cell_renderer_set_fixed_size (info->renderer, info->width, info->height); width = 0; height = 0; x_offset = 0; y_offset = 0; gtk_cell_renderer_get_size (info->renderer, widget, &cell_area, (info->width < 0) ? &x_offset : NULL, (info->height < 0) ? &y_offset : NULL, (info->width < 0) ? &width : NULL, (info->height < 0) ? &height : NULL); if (info->width < 0) { info->real_x += x_offset; info->real_width = width; } if (info->height < 0) { info->real_y += y_offset; info->real_height = height; } /* If we've changed since last size, resize the widget */ if (((!priv->fill_width) && (info->real_width != old_width)) || ((!priv->fill_height) && (info->real_height != old_height))) gtk_widget_queue_resize (widget); } /* Work out scaled position (for fill-width|fill-height) */ if (priv->fill_width || priv->fill_height) { gint width, height; gfloat scale_x = 1.f, scale_y = 1.f; tree_layout_get_size (JANA_GTK_TREE_LAYOUT (widget), &width, &height); scale_x = (gfloat)allocation->width / (gfloat)width; scale_y = (gfloat)allocation->height / (gfloat)height; for (c = *priv->cells_ptr; c; c = c->next) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)c->data; if (priv->fill_width) { info->real_x = (gint) ((gfloat)info->real_x*scale_x); info->real_width = (gint)((gfloat) info->real_width * scale_x); } if (priv->fill_height) { info->real_y = (gint) ((gfloat)info->real_y * scale_y); info->real_height = (gint)((gfloat) info->real_height * scale_y); } } } } static gboolean select_idle_cb (gpointer data) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (data); g_signal_emit (data, signals[SELECTION_CHANGED], 0); priv->select_idle = 0; return FALSE; } static gboolean jana_gtk_tree_layout_button_press_event (GtkWidget *widget, GdkEventButton *event) { GdkPoint point; GList *info_list; JanaGtkTreeLayoutCellInfo *info; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (widget); if (priv->select_mode == GTK_SELECTION_NONE) { GdkPoint point; /* Activate the event if there is one, and we're in single * click mode or this was a double-click. */ point.x = event->x; point.y = event->y; if ((priv->single_click || (event->type == GDK_2BUTTON_PRESS)) && (info_list = g_list_find_custom ( *priv->cells_ptr, &point, find_point_cb))) { gchar *path_string; GdkRectangle cell_area; info = (JanaGtkTreeLayoutCellInfo *)info_list->data; GtkTreePath *path; if (!info->sensitive) return FALSE; path = gtk_tree_row_reference_get_path (info->row); path_string = gtk_tree_path_to_string (path); gtk_tree_path_free (path); cell_area.x = info->real_x; cell_area.y = info->real_y; cell_area.width = info->real_width; cell_area.height = info->real_height; gtk_cell_renderer_activate (info->renderer, (GdkEvent *)event, widget, path_string, &cell_area, &cell_area, GTK_CELL_RENDERER_PRELIT); g_free (path_string); g_signal_emit (widget, signals[CELL_ACTIVATED], 0, info); } return FALSE; } /* Find and select new cell(s), redraw */ point.x = event->x; point.y = event->y; info_list = g_list_find_custom (*priv->cells_ptr, &point, find_point_cb); info = info_list ? (JanaGtkTreeLayoutCellInfo *)info_list->data : NULL; /* Deselect old cell(s) if necessary and queue a redraw */ if (((priv->select_mode != GTK_SELECTION_BROWSE) && (!(event->state & GDK_CONTROL_MASK))) || ((priv->select_mode != GTK_SELECTION_MULTIPLE) && priv->select && info && (priv->select->data != info))) { for (info_list = priv->select; info_list; info_list = info_list->next) { JanaGtkTreeLayoutCellInfo *old_info = (JanaGtkTreeLayoutCellInfo *) info_list->data; gtk_widget_queue_draw_area (widget, old_info->real_x + widget->allocation.x, old_info->real_y + widget->allocation.y, old_info->real_width, old_info->real_height); } g_list_free (priv->select); priv->select = NULL; if (!priv->select_idle) priv->select_idle = g_idle_add ( select_idle_cb, widget); } /* Select new cell, activate if necessary and redraw */ if (info) { if ((priv->select_mode != GTK_SELECTION_BROWSE) && (event->state & GDK_CONTROL_MASK)) { /* Deselect row if it's already selected */ GList *selected = g_list_find (priv->select, info); if (selected) { priv->select = g_list_remove ( priv->select, info); gtk_widget_queue_draw_area (widget, info->real_x + widget->allocation.x, info->real_y + widget->allocation.y, info->real_width, info->real_height); if (!priv->select_idle) priv->select_idle = g_idle_add (select_idle_cb, widget); return FALSE; } } /* Activate cell(s) */ /* Activates on double-click, or if in single-click mode, * only when there's a single event selected (otherwise * selecting multiple events would become near-impossible) */ if ((event->type == GDK_2BUTTON_PRESS) || (priv->single_click && (!priv->select))) { for (info_list = priv->select; info_list; info_list = info_list->next) { gchar *path_string; GdkRectangle cell_area; GtkCellRendererState state = GTK_CELL_RENDERER_SELECTED; JanaGtkTreeLayoutCellInfo *old_info = (JanaGtkTreeLayoutCellInfo *) info_list->data; GtkTreePath *path; if (!info->sensitive) continue; path = gtk_tree_row_reference_get_path ( info->row); path_string = gtk_tree_path_to_string (path); gtk_tree_path_free (path); cell_area.x = info->real_x; cell_area.y = info->real_y; cell_area.width = info->real_width; cell_area.height = info->real_height; if (old_info == info) state |= GTK_CELL_RENDERER_PRELIT; gtk_cell_renderer_activate (old_info->renderer, (GdkEvent *)event, widget, path_string, &cell_area, &cell_area, state); g_free (path_string); g_signal_emit (widget, signals[CELL_ACTIVATED], 0, old_info); } } /* Add new cell to selection */ if (info->sensitive) { priv->select = g_list_prepend (priv->select, info); gtk_widget_queue_draw_area (widget, info->real_x + widget->allocation.x, info->real_y + widget->allocation.y, info->real_width, info->real_height); if (!priv->select_idle) priv->select_idle = g_idle_add (select_idle_cb, widget); } } return FALSE; } static gboolean jana_gtk_tree_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { GdkPoint point; GList *info_list; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (widget); /* Find the cell we're hovered over and redraw it if necessary */ point.x = event->x; point.y = event->y; if ((info_list = g_list_find_custom ( *priv->cells_ptr, &point, find_point_cb))) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if (priv->hover != info) { if (priv->hover) gtk_widget_queue_draw_area ( widget, priv->hover->real_x + widget->allocation.x, priv->hover->real_y + widget->allocation.y, priv->hover->real_width, priv->hover->real_height); priv->hover = info; gtk_widget_queue_draw_area (widget, priv->hover->real_x + widget->allocation.x, priv->hover->real_y + widget->allocation.y, priv->hover->real_width, priv->hover->real_height); } } else if (priv->hover) { gtk_widget_queue_draw_area (widget, priv->hover->real_x + widget->allocation.x, priv->hover->real_y + widget->allocation.y, priv->hover->real_width, priv->hover->real_height); priv->hover = NULL; return FALSE; } return FALSE; } static void jana_gtk_tree_layout_class_init (JanaGtkTreeLayoutClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkTreeLayoutPrivate)); object_class->get_property = jana_gtk_tree_layout_get_property; object_class->set_property = jana_gtk_tree_layout_set_property; object_class->dispose = jana_gtk_tree_layout_dispose; object_class->finalize = jana_gtk_tree_layout_finalize; widget_class->expose_event = jana_gtk_tree_layout_expose_event; widget_class->size_request = jana_gtk_tree_layout_size_request; widget_class->size_allocate = jana_gtk_tree_layout_size_allocate; widget_class->button_press_event = jana_gtk_tree_layout_button_press_event; widget_class->motion_notify_event = jana_gtk_tree_layout_motion_notify_event; klass->add_cell = tree_layout_add_cell; klass->move_cell = tree_layout_move_cell; klass->remove_cell = tree_layout_remove_cell; klass->clear = tree_layout_clear; g_object_class_install_property ( object_class, PROP_SORT_CB, g_param_spec_pointer ( "sort_cb", "Sort callback", "A comparison function to sort the cells into drawing " "order.", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SORT_DATA, g_param_spec_pointer ( "sort_data", "Sort data", "User data for cell sorting function.", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SINGLE_CLICK, g_param_spec_boolean ( "single_click", "Single click", "Whether to activate cells on a single click.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SELECT_MODE, g_param_spec_enum ( "select_mode", "Selection mode", "Selection mode.", GTK_TYPE_SELECTION_MODE, GTK_SELECTION_SINGLE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_FILL_WIDTH, g_param_spec_boolean ( "fill_width", "Fill width", "Scale to fit available width.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_FILL_HEIGHT, g_param_spec_boolean ( "fill_height", "Fill height", "Scale to fit available height.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_VISIBLE_CB, g_param_spec_pointer ( "visible_cb", "Visible callback", "A filter function to determine which cells are " "visible.", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_VISIBLE_DATA, g_param_spec_pointer ( "visible_data", "gpointer", "User data for cell visibility filter function.", G_PARAM_READWRITE)); signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkTreeLayoutClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CELL_ACTIVATED] = g_signal_new ("cell_activated", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkTreeLayoutClass, cell_activated), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void tree_layout_style_set_cb (GtkWidget *widget, GtkStyle *previous_style, gpointer user_data) { gtk_widget_queue_resize (widget); gtk_widget_queue_draw (widget); } static void jana_gtk_tree_layout_init (JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); priv->models = g_hash_table_new (g_direct_hash, g_int_equal); priv->select_mode = GTK_SELECTION_SINGLE; priv->cells_ptr = &priv->cells; gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); gtk_event_box_set_visible_window (GTK_EVENT_BOX (self), FALSE); gtk_widget_add_events (GTK_WIDGET (self), GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_SCROLL_MASK); g_signal_connect (G_OBJECT (self), "style-set", G_CALLBACK (tree_layout_style_set_cb), NULL); } static void tree_layout_add_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height, GtkCellRenderer *renderer, va_list args) { gint refs; const gchar *prop; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaGtkTreeLayoutCellInfo *info; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); info = g_slice_new (JanaGtkTreeLayoutCellInfo); info->row = gtk_tree_row_reference_copy (row); info->x = x; info->y = y; info->width = width; info->height = height; info->real_x = x; info->real_y = y; info->real_width = width; info->real_height = height; info->sensitive = TRUE; info->renderer = g_object_ref (renderer); info->attributes = NULL; for (prop = va_arg (args, const gchar *); prop; prop = va_arg (args, const gchar *)) { gint col_id = va_arg (args, gint); info->attributes = g_list_prepend (info->attributes, g_strdup (prop)); info->attributes = g_list_prepend (info->attributes, GINT_TO_POINTER (col_id)); } model = gtk_tree_row_reference_get_model (info->row); if ((refs = GPOINTER_TO_INT (g_hash_table_lookup ( priv->models, model)))) { /* Increment local ref-count */ g_hash_table_replace (priv->models, model, GINT_TO_POINTER (refs + 1)); } else { /* Attach to signals for row updates */ g_signal_connect (G_OBJECT (model), "row-changed", G_CALLBACK (tree_layout_row_changed_cb), self); g_signal_connect (G_OBJECT (model), "row-deleted", G_CALLBACK (tree_layout_row_deleted_cb), self); g_hash_table_insert (priv->models, g_object_ref (model), GINT_TO_POINTER (1)); } if (priv->sort_cb) priv->cells = g_list_insert_sorted_with_data (priv->cells, info, priv->sort_cb, priv->sort_data); else priv->cells = g_list_prepend (priv->cells, info); path = gtk_tree_row_reference_get_path (row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); if (priv->visible_cb && priv->visible_cb (model, &iter, priv->visible_data)) { if (priv->sort_cb) priv->visible_cells = g_list_insert_sorted_with_data ( priv->visible_cells, info, priv->sort_cb, priv->sort_data); else priv->visible_cells = g_list_prepend ( priv->visible_cells, info); } gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void tree_layout_move_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height) { JanaGtkTreeLayoutCellInfo *info; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GList *info_list = g_list_find_custom (priv->cells, row, find_row_cb); if (!info_list) return; info = (JanaGtkTreeLayoutCellInfo *)info_list->data; info->x = x; info->y = y; info->width = width; info->height = height; info->real_x = x; info->real_y = y; info->real_width = width; info->real_height = height; if (priv->hover == info) priv->hover = NULL; if (priv->sort_cb) priv->cells = g_list_sort_with_data (priv->cells, priv->sort_cb, priv->sort_data); gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void tree_layout_remove_cell_with_list (JanaGtkTreeLayout *self, GList *info_list) { gint refs; GList *selected; GtkTreeModel *model; JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if ((selected = g_list_find (priv->select, info))) { priv->select = g_list_delete_link (priv->select, selected); if (!priv->select_idle) priv->select_idle = g_idle_add ( select_idle_cb, self); } if (priv->hover == info) priv->hover = NULL; model = gtk_tree_row_reference_get_model (info->row); if ((refs = GPOINTER_TO_INT (g_hash_table_lookup ( priv->models, model)))) { refs --; if (refs) { /* Decrement local ref-count */ g_hash_table_replace (priv->models, model, GINT_TO_POINTER (refs)); } else { /* Remove signals and unref model */ g_signal_handlers_disconnect_by_func (model, tree_layout_row_changed_cb, self); g_signal_handlers_disconnect_by_func (model, tree_layout_row_deleted_cb, self); g_hash_table_remove (priv->models, model); g_object_unref (model); } } free_info ((JanaGtkTreeLayoutCellInfo *)info_list->data); priv->cells = g_list_delete_link (priv->cells, info_list); if (priv->visible_cb) { GList *link = g_list_find ( priv->visible_cells, info); if (link) priv->visible_cells = g_list_delete_link ( priv->visible_cells, link); } gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void tree_layout_remove_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GList *info_list = g_list_find_custom (priv->cells, row, find_row_cb); if (info_list) tree_layout_remove_cell_with_list (self, info_list); } static void tree_layout_clear (JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); while (priv->cells) tree_layout_remove_cell_with_list ( self, priv->cells); } GtkWidget* jana_gtk_tree_layout_new (void) { return (GtkWidget *)g_object_new (JANA_GTK_TYPE_TREE_LAYOUT, NULL); } GList * jana_gtk_tree_layout_get_selection (JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); return g_list_copy (priv->select); } GList * jana_gtk_tree_layout_get_cells (JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); return g_list_copy (priv->cells); } void jana_gtk_tree_layout_add_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height, GtkCellRenderer *renderer, ...) { va_list args; va_start (args, renderer); JANA_GTK_TREE_LAYOUT_GET_CLASS (self)->add_cell (self, row, x, y, width, height, renderer, args); va_end (args); } void jana_gtk_tree_layout_move_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height) { JANA_GTK_TREE_LAYOUT_GET_CLASS (self)-> move_cell (self, row, x, y, width, height); } void jana_gtk_tree_layout_remove_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row) { JANA_GTK_TREE_LAYOUT_GET_CLASS (self)->remove_cell (self, row); } void jana_gtk_tree_layout_clear (JanaGtkTreeLayout *self) { JANA_GTK_TREE_LAYOUT_GET_CLASS (self)->clear (self); } void jana_gtk_tree_layout_set_selection (JanaGtkTreeLayout *self, GList *selection) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); g_list_free (priv->select); priv->select = g_list_copy (selection); gtk_widget_queue_draw (GTK_WIDGET (self)); } const JanaGtkTreeLayoutCellInfo * jana_gtk_tree_layout_get_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GList *info_list = g_list_find_custom (priv->cells, row, find_row_cb); if (info_list) return (const JanaGtkTreeLayoutCellInfo *)info_list->data; else return NULL; } void jana_gtk_tree_layout_set_cell_sensitive (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gboolean sensitive) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); GList *info_list = g_list_find_custom (priv->cells, row, find_row_cb); if (info_list) { JanaGtkTreeLayoutCellInfo *info; info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if (info->sensitive != sensitive) { info->sensitive = sensitive; gtk_widget_queue_draw_area (GTK_WIDGET (self), info->real_x + GTK_WIDGET (self)->allocation.x, info->real_y + GTK_WIDGET (self)->allocation.y, info->real_width, info->real_height); } } } void jana_gtk_tree_layout_set_visible_func (JanaGtkTreeLayout *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); if (priv->visible_cb) g_list_free (priv->visible_cells); priv->visible_cb = visible_cb; priv->visible_data = data; if (priv->visible_cb) { priv->visible_cells = get_visible_cells (self); priv->cells_ptr = &priv->visible_cells; } else priv->cells_ptr = &priv->cells; gtk_widget_queue_draw (GTK_WIDGET (self)); } void jana_gtk_tree_layout_refilter (JanaGtkTreeLayout *self) { JanaGtkTreeLayoutPrivate *priv = TREE_LAYOUT_PRIVATE (self); if (priv->visible_cb) { g_list_free (priv->visible_cells); priv->visible_cells = get_visible_cells (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } } jana/libjana-gtk/jana-gtk-world-map-marker-pixbuf.c0000644000175000017500000000523711327631152022404 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include "jana-gtk-world-map-marker-pixbuf.h" G_DEFINE_TYPE (JanaGtkWorldMapMarkerPixbuf, jana_gtk_world_map_marker_pixbuf, JANA_GTK_TYPE_WORLD_MAP_MARKER) static void dispose (GObject *object) { JanaGtkWorldMapMarkerPixbuf *marker = (JanaGtkWorldMapMarkerPixbuf *)object; if (marker->pixbuf) { g_object_unref (marker->pixbuf); marker->pixbuf = NULL; } ((GObjectClass *) jana_gtk_world_map_marker_pixbuf_parent_class)-> dispose (object); } static void render (JanaGtkWorldMapMarker *marker, GtkStyle *style, cairo_t *cr, GtkStateType state, gint x, gint y) { gint real_x, real_y, width, height; if (!((JanaGtkWorldMapMarkerPixbuf *)marker)->pixbuf) { JANA_GTK_WORLD_MAP_MARKER_CLASS ( jana_gtk_world_map_marker_pixbuf_parent_class)-> render (marker, style, cr, state, x, y); return; } width = gdk_pixbuf_get_width ( ((JanaGtkWorldMapMarkerPixbuf *)marker)->pixbuf); height = gdk_pixbuf_get_height ( ((JanaGtkWorldMapMarkerPixbuf *)marker)->pixbuf); real_x = x - (width / 2); real_y = y - (height / 2); gdk_cairo_set_source_pixbuf (cr, ((JanaGtkWorldMapMarkerPixbuf *) marker)->pixbuf, real_x, real_y); cairo_paint (cr); } static void jana_gtk_world_map_marker_pixbuf_class_init ( JanaGtkWorldMapMarkerPixbufClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; JanaGtkWorldMapMarkerClass *map_class = (JanaGtkWorldMapMarkerClass *) klass; object_class->dispose = dispose; map_class->render = render; } static void jana_gtk_world_map_marker_pixbuf_init (JanaGtkWorldMapMarkerPixbuf *marker) { } JanaGtkWorldMapMarker * jana_gtk_world_map_marker_pixbuf_new (GdkPixbuf *pixbuf) { JanaGtkWorldMapMarkerPixbuf *marker; marker = g_object_new (JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF, NULL); marker->pixbuf = pixbuf ? g_object_ref (pixbuf) : NULL; return JANA_GTK_WORLD_MAP_MARKER (marker); } jana/libjana-gtk/jana-gtk-tree-layout.h0000644000175000017500000000764111327631152020210 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_TREE_LAYOUT_H #define _JANA_GTK_TREE_LAYOUT_H #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_TREE_LAYOUT jana_gtk_tree_layout_get_type() #define JANA_GTK_TREE_LAYOUT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_TREE_LAYOUT, JanaGtkTreeLayout)) #define JANA_GTK_TREE_LAYOUT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_TREE_LAYOUT, JanaGtkTreeLayoutClass)) #define JANA_GTK_IS_TREE_LAYOUT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_TREE_LAYOUT)) #define JANA_GTK_IS_TREE_LAYOUT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_TREE_LAYOUT)) #define JANA_GTK_TREE_LAYOUT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_TREE_LAYOUT, JanaGtkTreeLayoutClass)) typedef struct { GtkTreeRowReference *row; gint x; gint y; gint width; gint height; gint real_x; gint real_y; gint real_width; gint real_height; gboolean sensitive; GtkCellRenderer *renderer; GList *attributes; } JanaGtkTreeLayoutCellInfo; typedef struct { GtkEventBox parent; } JanaGtkTreeLayout; typedef struct { GtkEventBoxClass parent_class; void (*add_cell) (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height, GtkCellRenderer *renderer, va_list args); void (*move_cell) (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height); void (*remove_cell) (JanaGtkTreeLayout *self, GtkTreeRowReference *row); void (*clear) (JanaGtkTreeLayout *self); /* Signals */ void (*selection_changed) (JanaGtkTreeLayout *self); void (*cell_activated) (JanaGtkTreeLayout *self, const JanaGtkTreeLayoutCellInfo *info); } JanaGtkTreeLayoutClass; GType jana_gtk_tree_layout_get_type (void); GtkWidget* jana_gtk_tree_layout_new (void); void jana_gtk_tree_layout_add_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height, GtkCellRenderer *renderer, ...); void jana_gtk_tree_layout_move_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gint x, gint y, gint width, gint height); void jana_gtk_tree_layout_remove_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row); void jana_gtk_tree_layout_clear (JanaGtkTreeLayout *self); GList * jana_gtk_tree_layout_get_selection (JanaGtkTreeLayout *self); GList * jana_gtk_tree_layout_get_cells (JanaGtkTreeLayout *self); void jana_gtk_tree_layout_set_selection (JanaGtkTreeLayout *self, GList *selection); const JanaGtkTreeLayoutCellInfo * jana_gtk_tree_layout_get_cell (JanaGtkTreeLayout *self, GtkTreeRowReference *row); void jana_gtk_tree_layout_set_cell_sensitive (JanaGtkTreeLayout *self, GtkTreeRowReference *row, gboolean sensitive); void jana_gtk_tree_layout_set_visible_func (JanaGtkTreeLayout *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data); void jana_gtk_tree_layout_refilter (JanaGtkTreeLayout *self); G_END_DECLS #endif /* _JANA_GTK_TREE_LAYOUT_H */ jana/libjana-gtk/jana-gtk-date-time.h0000644000175000017500000000432511327631152017603 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_DATE_TIME_H #define _JANA_GTK_DATE_TIME_H #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_DATE_TIME jana_gtk_date_time_get_type() #define JANA_GTK_DATE_TIME(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_DATE_TIME, JanaGtkDateTime)) #define JANA_GTK_DATE_TIME_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_DATE_TIME, JanaGtkDateTimeClass)) #define JANA_GTK_IS_DATE_TIME(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_DATE_TIME)) #define JANA_GTK_IS_DATE_TIME_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_DATE_TIME)) #define JANA_GTK_DATE_TIME_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_DATE_TIME, JanaGtkDateTimeClass)) typedef struct { GtkVBox parent; } JanaGtkDateTime; typedef struct { GtkVBoxClass parent_class; /* Signals */ void (*changed) (JanaGtkDateTime *self); } JanaGtkDateTimeClass; GType jana_gtk_date_time_get_type (void); GtkWidget* jana_gtk_date_time_new (JanaTime *time); JanaTime *jana_gtk_date_time_get_time (JanaGtkDateTime *self); void jana_gtk_date_time_set_time (JanaGtkDateTime *self, JanaTime *time); void jana_gtk_date_time_set_editable (JanaGtkDateTime *self, gboolean editable); gboolean jana_gtk_date_time_get_editable (JanaGtkDateTime *self); G_END_DECLS #endif /* _JANA_GTK_DATE_TIME_H */ jana/libjana-gtk/jana-gtk-recurrence.c0000644000175000017500000005170611327631152020067 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include "jana-gtk-recurrence.h" #include #include "jana-gtk-date-time.h" G_DEFINE_TYPE (JanaGtkRecurrence, jana_gtk_recurrence, GTK_TYPE_VBOX) #define RECURRENCE_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_RECURRENCE, \ JanaGtkRecurrencePrivate)) typedef struct _JanaGtkRecurrencePrivate JanaGtkRecurrencePrivate; struct _JanaGtkRecurrencePrivate { JanaRecurrence *recur; JanaTime *time; gboolean editable; GtkWidget *edit_vbox; GtkWidget *type_combo; GtkWidget *interval_dec_button; GtkWidget *interval_inc_button; GtkWidget *week_hbox; GtkToggleButton *week_buttons[7]; GtkWidget *month_hbox; GtkToggleButton *byday_button; GtkToggleButton *bydate_button; GtkWidget *end_hbox; GtkWidget *end_button; GtkWidget *end_label; GtkWidget *preview_frame; GtkWidget *preview_textview; }; enum { PROP_RECUR = 1, PROP_TIME, PROP_EDITABLE, }; static void fill_type_combo (JanaGtkRecurrence *self) { gchar *recur_string; JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); JanaRecurrence *recur = jana_recurrence_new (); if (priv->recur) recur->interval = priv->recur->interval; /* Daily */ recur_string = jana_utils_recurrence_to_string (recur, NULL); gtk_combo_box_insert_text (GTK_COMBO_BOX (priv->type_combo), 1, recur_string); gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->type_combo), 2); g_free (recur_string); /* Weekly */ recur->type = JANA_RECURRENCE_WEEKLY; recur_string = jana_utils_recurrence_to_string (recur, NULL); gtk_combo_box_insert_text (GTK_COMBO_BOX (priv->type_combo), 2, recur_string); gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->type_combo), 3); g_free (recur_string); /* Monthly */ recur->type = JANA_RECURRENCE_MONTHLY; recur_string = jana_utils_recurrence_to_string (recur, NULL); gtk_combo_box_insert_text (GTK_COMBO_BOX (priv->type_combo), 3, recur_string); gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->type_combo), 4); g_free (recur_string); /* Yearly */ recur->type = JANA_RECURRENCE_YEARLY; recur_string = jana_utils_recurrence_to_string (recur, NULL); gtk_combo_box_insert_text (GTK_COMBO_BOX (priv->type_combo), 4, recur_string); gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->type_combo), 5); g_free (recur_string); jana_recurrence_free (recur); } static void refresh (JanaGtkRecurrence *self) { gint i; gchar *recur_text; GtkTextBuffer *buffer; JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if ((!priv->recur) || (!priv->time)) gtk_widget_hide (priv->end_hbox); else gtk_widget_show (priv->end_hbox); /* Update type selector combo box */ fill_type_combo (self); /* Update preview */ recur_text = jana_utils_recurrence_to_string (priv->recur, priv->time); buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW (priv->preview_textview)); gtk_text_buffer_set_text (buffer, recur_text, -1); /* Show/hide the appropriate editing widgets and set type combo */ gtk_widget_hide (priv->week_hbox); gtk_widget_hide (priv->month_hbox); if (priv->recur) { if (priv->recur->end) { gchar *time_string = jana_utils_strftime ( priv->recur->end, "%d/%m/%Y"); gtk_label_set_text (GTK_LABEL (priv->end_label), time_string); g_free (time_string); } else { gtk_label_set_text (GTK_LABEL (priv->end_label), "Forever"); } if (priv->recur->interval <= 1) gtk_widget_set_sensitive ( priv->interval_dec_button, FALSE); else gtk_widget_set_sensitive ( priv->interval_dec_button, TRUE); gtk_widget_set_sensitive (priv->interval_inc_button, TRUE); switch (priv->recur->type) { case JANA_RECURRENCE_DAILY : gtk_combo_box_set_active ( GTK_COMBO_BOX (priv->type_combo), 1); break; case JANA_RECURRENCE_WEEKLY : for (i = 0; i < 7; i++) { gtk_toggle_button_set_active ( priv->week_buttons[i], priv->recur->week_days[i]); } gtk_widget_show (priv->week_hbox); gtk_combo_box_set_active ( GTK_COMBO_BOX (priv->type_combo), 2); break; case JANA_RECURRENCE_MONTHLY : if (priv->recur->by_date) gtk_toggle_button_set_active ( priv->bydate_button, TRUE); else gtk_toggle_button_set_active ( priv->byday_button, TRUE); gtk_widget_show (priv->month_hbox); gtk_combo_box_set_active ( GTK_COMBO_BOX (priv->type_combo), 3); break; case JANA_RECURRENCE_YEARLY : gtk_combo_box_set_active ( GTK_COMBO_BOX (priv->type_combo), 4); break; } } else { gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo), 0); gtk_widget_set_sensitive (priv->interval_dec_button, FALSE); gtk_widget_set_sensitive (priv->interval_inc_button, FALSE); } } static void jana_gtk_recurrence_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (object); switch (property_id) { case PROP_RECUR : g_value_set_boxed (value, priv->recur); break; case PROP_TIME : g_value_set_object (value, priv->time); break; case PROP_EDITABLE : g_value_set_boolean (value, priv->editable); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_recurrence_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_RECUR : jana_gtk_recurrence_set_recur (JANA_GTK_RECURRENCE (object), g_value_get_boxed (value)); break; case PROP_TIME : jana_gtk_recurrence_set_time (JANA_GTK_RECURRENCE (object), JANA_TIME (g_value_get_object (value))); break; case PROP_EDITABLE : jana_gtk_recurrence_set_editable (JANA_GTK_RECURRENCE (object), g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_recurrence_dispose (GObject *object) { if (G_OBJECT_CLASS (jana_gtk_recurrence_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_recurrence_parent_class)-> dispose (object); } static void jana_gtk_recurrence_finalize (GObject *object) { G_OBJECT_CLASS (jana_gtk_recurrence_parent_class)->finalize (object); } static void jana_gtk_recurrence_style_set (GtkWidget *widget, GtkStyle *previous_style) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (widget); gtk_widget_modify_base (priv->preview_textview, GTK_STATE_NORMAL, &widget->style->bg[GTK_STATE_NORMAL]); GTK_WIDGET_CLASS (jana_gtk_recurrence_parent_class)-> style_set (widget, previous_style); } static void jana_gtk_recurrence_class_init (JanaGtkRecurrenceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkRecurrencePrivate)); object_class->get_property = jana_gtk_recurrence_get_property; object_class->set_property = jana_gtk_recurrence_set_property; object_class->dispose = jana_gtk_recurrence_dispose; object_class->finalize = jana_gtk_recurrence_finalize; widget_class->style_set = jana_gtk_recurrence_style_set; g_object_class_install_property ( object_class, PROP_RECUR, g_param_spec_boxed ( "recur", "Recurrence", "The JanaRecurrence represented by this widget.", JANA_TYPE_RECURRENCE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_TIME, g_param_spec_object ( "time", "Time", "The JanaTime the recurrence starts on.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_EDITABLE, g_param_spec_boolean ( "editable", "Editable", "Whether the recurrence can be edited or not.", FALSE, G_PARAM_READWRITE)); } static void interval_inc_clicked_cb (GtkButton *button, JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (priv->recur) priv->recur->interval++; refresh (self); } static void interval_dec_clicked_cb (GtkButton *button, JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (priv->recur && (priv->recur->interval > 1)) priv->recur->interval--; refresh (self); } static void type_combo_changed_cb (GtkComboBox *combo, JanaGtkRecurrence *self) { gint active; JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); active = gtk_combo_box_get_active (combo); if (active > 0) { JanaRecurrenceType type; switch (active) { case 1 : type = JANA_RECURRENCE_DAILY; break; case 2 : type = JANA_RECURRENCE_WEEKLY; break; case 3 : type = JANA_RECURRENCE_MONTHLY; break; case 4 : type = JANA_RECURRENCE_YEARLY; break; default : return; } if (!priv->recur) { priv->recur = jana_recurrence_new (); priv->recur->type = type; refresh (self); } else if (priv->recur->type != type) { priv->recur->type = type; refresh (self); } } else if (active == 0) { if (priv->recur) { jana_recurrence_free (priv->recur); priv->recur = NULL; refresh (self); } } } #define day_toggle_cb(x) \ static void \ day##x##_toggled_cb (GtkToggleButton *toggle, JanaGtkRecurrence *self) \ { \ gboolean active; \ JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); \ if ((active = gtk_toggle_button_get_active (toggle)) != \ priv->recur->week_days[x]) { \ priv->recur->week_days[x] = active; \ refresh (self); \ } \ } day_toggle_cb(0) day_toggle_cb(1) day_toggle_cb(2) day_toggle_cb(3) day_toggle_cb(4) day_toggle_cb(5) day_toggle_cb(6) static void bydate_toggled_cb (GtkToggleButton *toggle, JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (priv->recur->by_date != gtk_toggle_button_get_active (toggle)) { priv->recur->by_date = !priv->recur->by_date; refresh (self); } } static void forever_toggled_cb (GtkToggleButton *toggle, JanaGtkDateTime *datetime) { gtk_widget_set_sensitive (GTK_WIDGET (datetime), !gtk_toggle_button_get_active (toggle)); } static void close_clicked_cb (GtkButton *button, JanaGtkDateTime *datetime) { GtkWidget *window; JanaGtkRecurrence *self; JanaGtkRecurrencePrivate *priv; window = gtk_widget_get_toplevel (GTK_WIDGET (button)); self = (JanaGtkRecurrence *) g_object_get_data (G_OBJECT (window), "self"); priv = RECURRENCE_PRIVATE (self); if (GTK_WIDGET_SENSITIVE (datetime)) { JanaTime *time = jana_gtk_date_time_get_time (datetime); if (jana_utils_time_compare (time, priv->time, TRUE) > 0) { if (priv->recur->end) g_object_unref (priv->recur->end); priv->recur->end = time; } else { g_object_unref (time); } } else if (priv->recur->end) { g_object_unref (priv->recur->end); priv->recur->end = NULL; } refresh (self); gtk_widget_destroy (window); } static void end_clicked_cb (GtkButton *button, JanaGtkRecurrence *self) { GtkWidget *window, *datetime, *check, *toplevel, *vbox, *close, *align; JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); JanaTime *time; /* Time-editing dialog */ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button)); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); if (GTK_WIDGET_TOPLEVEL (toplevel)) gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (toplevel)); gtk_window_set_modal (GTK_WINDOW (window), TRUE); gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); vbox = gtk_vbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); check = gtk_check_button_new_with_mnemonic ("Repeats _forever"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), priv->recur->end ? FALSE : TRUE); time = priv->recur->end ? jana_time_duplicate (priv->recur->end) : jana_time_duplicate (priv->time); jana_time_set_isdate (time, TRUE); datetime = jana_gtk_date_time_new (time); jana_gtk_date_time_set_editable (JANA_GTK_DATE_TIME (datetime), TRUE); gtk_widget_set_sensitive (datetime, priv->recur->end ? TRUE : FALSE); align = gtk_alignment_new (1.0, 0.5, 0.0, 1.0); gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 0, 0); close = gtk_button_new_from_stock (GTK_STOCK_CLOSE); gtk_container_add (GTK_CONTAINER (align), close); gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), datetime, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, TRUE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); g_object_set_data (G_OBJECT (window), "self", self); g_signal_connect (check, "toggled", G_CALLBACK (forever_toggled_cb), datetime); g_signal_connect (close, "clicked", G_CALLBACK (close_clicked_cb), datetime); gtk_widget_show_all (window); } static void jana_gtk_recurrence_init (JanaGtkRecurrence *self) { GtkWidget *label, *hbox, *sub_hbox, *arrow, *button; GtkSizeGroup *size_group; JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); gtk_box_set_spacing (GTK_BOX (self), 6); /* Create preview text-view */ priv->preview_frame = gtk_frame_new (NULL); priv->preview_textview = gtk_text_view_new (); gtk_text_view_set_editable (GTK_TEXT_VIEW ( priv->preview_textview), FALSE); gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW (priv->preview_textview), FALSE); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->preview_textview), GTK_WRAP_WORD_CHAR); gtk_container_add (GTK_CONTAINER (priv->preview_frame), priv->preview_textview); gtk_box_pack_end (GTK_BOX (self), priv->preview_frame, TRUE, TRUE, 0); gtk_frame_set_shadow_type ( GTK_FRAME (priv->preview_frame), GTK_SHADOW_NONE); gtk_widget_show_all (priv->preview_frame); priv->edit_vbox = gtk_vbox_new (FALSE, 6); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* 'Repeats' (recurrence type) combo box */ hbox = gtk_hbox_new (FALSE, 6); label = gtk_label_new ("Repeats:"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_size_group_add_widget (size_group, label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); priv->type_combo = gtk_combo_box_new_text (); gtk_combo_box_append_text (GTK_COMBO_BOX (priv->type_combo), "None"); gtk_combo_box_append_text (GTK_COMBO_BOX (priv->type_combo), "Every day"); gtk_combo_box_append_text (GTK_COMBO_BOX (priv->type_combo), "Every week"); gtk_combo_box_append_text (GTK_COMBO_BOX (priv->type_combo), "Every year"); gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo), 0); gtk_box_pack_start (GTK_BOX (hbox), priv->type_combo, TRUE, TRUE, 0); g_signal_connect (priv->type_combo, "changed", G_CALLBACK (type_combo_changed_cb), self); /* Interval buttons */ sub_hbox = gtk_hbox_new (TRUE, 0); priv->interval_dec_button = gtk_button_new (); arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (priv->interval_dec_button), arrow); gtk_box_pack_start (GTK_BOX (sub_hbox), priv->interval_dec_button, FALSE, TRUE, 0); priv->interval_inc_button = gtk_button_new (); arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (priv->interval_inc_button), arrow); gtk_box_pack_start (GTK_BOX (sub_hbox), priv->interval_inc_button, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), sub_hbox, FALSE, TRUE, 0); g_signal_connect (priv->interval_inc_button, "clicked", G_CALLBACK (interval_inc_clicked_cb), self); g_signal_connect (priv->interval_dec_button, "clicked", G_CALLBACK (interval_dec_clicked_cb), self); gtk_widget_show_all (hbox); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), hbox, FALSE, TRUE, 0); /* Weekly recurrence day-chooser */ priv->week_hbox = gtk_hbox_new (FALSE, 6); label = gtk_label_new ("On:"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_size_group_add_widget (size_group, label); gtk_box_pack_start (GTK_BOX (priv->week_hbox), label, FALSE, TRUE, 0); sub_hbox = gtk_hbox_new (TRUE, 0); /* Weekday toggle widgets */ #define day_toggle_widget(x) \ button = gtk_toggle_button_new_with_label (jana_utils_ab_day (x)); \ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); \ gtk_box_pack_start (GTK_BOX (sub_hbox), button, TRUE, TRUE, 0); \ priv->week_buttons[x] = GTK_TOGGLE_BUTTON (button); \ g_signal_connect (button, "toggled", \ G_CALLBACK (day##x##_toggled_cb), self) day_toggle_widget(0); day_toggle_widget(1); day_toggle_widget(2); day_toggle_widget(3); day_toggle_widget(4); day_toggle_widget(5); day_toggle_widget(6); gtk_box_pack_start (GTK_BOX (priv->week_hbox), sub_hbox, TRUE, TRUE, 0); gtk_widget_show_all (priv->week_hbox); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), priv->week_hbox, FALSE, TRUE, 0); /* Monthly recurrence by date/day chooser */ priv->month_hbox = gtk_hbox_new (FALSE, 6); label = gtk_label_new ("By:"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_size_group_add_widget (size_group, label); gtk_box_pack_start (GTK_BOX (priv->month_hbox), label, FALSE, TRUE, 0); sub_hbox = gtk_hbox_new (TRUE, 0); /* By day */ priv->byday_button = GTK_TOGGLE_BUTTON ( gtk_radio_button_new_with_label (NULL, "Day")); gtk_toggle_button_set_mode (priv->byday_button, FALSE); gtk_box_pack_start (GTK_BOX (sub_hbox), GTK_WIDGET ( priv->byday_button), FALSE, TRUE, 0); /* By date */ priv->bydate_button = GTK_TOGGLE_BUTTON ( gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (priv->byday_button), "Date")); gtk_toggle_button_set_mode (priv->bydate_button, FALSE); g_signal_connect (priv->bydate_button, "toggled", G_CALLBACK (bydate_toggled_cb), self); gtk_box_pack_start (GTK_BOX (sub_hbox), GTK_WIDGET ( priv->bydate_button), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (priv->month_hbox), sub_hbox, FALSE, TRUE, 0); gtk_widget_show_all (priv->month_hbox); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), priv->month_hbox, FALSE, TRUE, 0); /* Until time editor */ priv->end_hbox = gtk_hbox_new (FALSE, 6); label = gtk_label_new ("Until:"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_size_group_add_widget (size_group, label); gtk_box_pack_start (GTK_BOX (priv->end_hbox), label, FALSE, TRUE, 0); priv->end_button = gtk_button_new (); hbox = gtk_hbox_new (FALSE, 6); priv->end_label = gtk_label_new (NULL); arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (hbox), priv->end_label, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, TRUE, 0); gtk_container_add (GTK_CONTAINER (priv->end_button), hbox); g_signal_connect (priv->end_button, "clicked", G_CALLBACK (end_clicked_cb), self); gtk_box_pack_start (GTK_BOX (priv->end_hbox), priv->end_button, FALSE, TRUE, 0); gtk_widget_show_all (priv->end_hbox); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), priv->end_hbox, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (self), priv->edit_vbox, FALSE, TRUE, 0); gtk_widget_set_no_show_all (priv->edit_vbox, TRUE); gtk_widget_set_no_show_all (priv->preview_frame, TRUE); refresh (self); } GtkWidget * jana_gtk_recurrence_new (void) { return g_object_new (JANA_GTK_TYPE_RECURRENCE, NULL); } void jana_gtk_recurrence_set_recur (JanaGtkRecurrence *self, JanaRecurrence *recur) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (priv->recur) { jana_recurrence_free (priv->recur); priv->recur = NULL; } if (recur) priv->recur = jana_recurrence_copy (recur); refresh (self); } JanaRecurrence * jana_gtk_recurrence_get_recur (JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); return priv->recur ? jana_recurrence_copy (priv->recur) : NULL; } void jana_gtk_recurrence_set_editable (JanaGtkRecurrence *self, gboolean editable) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (editable == priv->editable) return; priv->editable = editable; g_object_set (G_OBJECT (priv->edit_vbox), "visible", editable, NULL); gtk_frame_set_shadow_type (GTK_FRAME (priv->preview_frame), editable ? GTK_SHADOW_IN : GTK_SHADOW_NONE); } gboolean jana_gtk_recurrence_get_editable (JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); return priv->editable; } void jana_gtk_recurrence_set_time (JanaGtkRecurrence *self, JanaTime *time) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (time) priv->time = jana_time_duplicate (time); refresh (self); } JanaTime * jana_gtk_recurrence_get_time (JanaGtkRecurrence *self) { JanaGtkRecurrencePrivate *priv = RECURRENCE_PRIVATE (self); return priv->time ? jana_time_duplicate (priv->time) : NULL; } jana/libjana-gtk/Makefile.am0000644000175000017500000000264511327631152016126 0ustar paulliupaulliuSUBDIRS = . data doc localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" $(GOBJECT_CFLAGS) $(GTK_CFLAGS) $(GTHREAD_CFLAGS) $(GLADE_CFLAGS) -Wall AM_LDFLAGS = $(GOBJECT_LIBS) $(GTK_LIBS) $(GTHREAD_LIBS) $(GLADE_LIBS) source_h = jana-gtk.h \ jana-gtk-event-store.h \ jana-gtk-cell-renderer-event.h \ jana-gtk-tree-layout.h \ jana-gtk-event-list.h \ jana-gtk-date-time.h \ jana-gtk-month-view.h \ jana-gtk-day-view.h \ jana-gtk-year-view.h \ jana-gtk-recurrence.h \ jana-gtk-clock.h \ jana-gtk-world-map.h \ jana-gtk-world-map-marker.h \ jana-gtk-world-map-marker-pixbuf.h \ jana-gtk-note-store.h \ jana-gtk-cell-renderer-note.h \ jana-gtk-utils.h source_c = jana-gtk-event-store.c \ jana-gtk-cell-renderer-event.c \ jana-gtk-tree-layout.c \ jana-gtk-event-list.c \ jana-gtk-date-time.c \ jana-gtk-month-view.c \ jana-gtk-day-view.c \ jana-gtk-year-view.c \ jana-gtk-recurrence.c \ jana-gtk-clock.c \ jana-gtk-world-map.c \ jana-gtk-world-map-marker.c \ jana-gtk-world-map-marker-pixbuf.c \ jana-gtk-note-store.c \ jana-gtk-cell-renderer-note.c \ jana-gtk-utils.c lib_LTLIBRARIES = libjana-gtk.la libjana_gtk_la_LIBADD = $(top_srcdir)/libjana/libjana.la libjana_gtk_la_SOURCES = $(source_c) $(source_h) library_includedir=$(includedir)/jana/libjana-gtk library_include_HEADERS = $(source_h) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libjana-gtk.pc jana/libjana-gtk/jana-gtk-utils.c0000644000175000017500000000435211327631152017065 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include "jana-gtk-utils.h" /** * jana_gtk_utils_treeview_resize: * @tree_view: A #GtkTreeView * @allocation: The widget's allocated size * @cell_renderer: A #GtkCellRenderer * * A convenience callback that can be used in conjunction with * #GtkTreeView::size-allocate that will set the cell renderer width to the * width of the first column in @tree_view. This can be useful if you want * correctly sized rows when using #JanaGtkCellRendererEvent or * #JanaGtkCellRendererNote. */ void jana_gtk_utils_treeview_resize (GtkWidget *tree_view, GtkAllocation *allocation, gpointer cell_renderer) { gint last_width0, last_width1, width; /* Store the last two negotiated widths to stop oscillation when * crossing the threshold for which scroll-bars are required. */ last_width0 = GPOINTER_TO_INT ( g_object_get_data (G_OBJECT (tree_view), "last_width0")); last_width1 = GPOINTER_TO_INT ( g_object_get_data (G_OBJECT (tree_view), "last_width1")); width = gtk_tree_view_column_get_width ( gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), 0)); if ((width != last_width0) && (width != last_width1)) { g_object_set_data (G_OBJECT (tree_view), "last_width1", GINT_TO_POINTER (last_width0)); g_object_set_data (G_OBJECT (tree_view), "last_width0", GINT_TO_POINTER (width)); g_object_set (G_OBJECT (cell_renderer), "cell_width", width, NULL); gtk_tree_view_columns_autosize (GTK_TREE_VIEW (tree_view)); } } jana/libjana-gtk/data/0000755000175000017500000000000011327631152014774 5ustar paulliupaulliujana/libjana-gtk/data/landwater.vmf0000644000175000017500000115713311327631152017502 0ustar paulliupaulliu%!VMF % Vector Map Format for Sunclock % % List of colors RoyalBlue % color 0 Chartreuse2 % color 1 LemonChiffon % color 2 ; % Default color 1 % Palette (possibly several codes for each color: ci j1 j2 j3 ... ) c0 0 c1 1 c2 2 ; % Background value 2 % Coordinate range (latitude, longitude) range -90 90 -180 180 % List of closed curves % Set internal flag flag 2 % Fill mode = fill areas within closed curves closedcurves #0 1 31.159 32.154 31.324 31.857 31.390 32.060 31.434 31.978 31.486 31.753 31.492 31.429 31.544 31.088 31.423 30.797 31.459 30.692 31.533 30.808 31.451 30.396 31.266 30.181 31.170 29.841 30.992 29.571 30.863 29.275 30.863 28.951 31.003 28.659 31.069 28.335 31.118 27.984 31.201 27.703 31.288 27.390 31.401 27.088 31.462 26.764 31.514 26.429 31.585 26.099 31.593 25.769 31.519 25.445 31.615 25.165 31.896 25.011 32.008 24.709 31.997 24.368 32.049 24.033 32.165 23.731 32.195 23.368 32.376 23.132 32.635 23.027 32.753 22.687 32.852 22.368 32.915 22.049 32.915 21.676 32.791 21.363 32.747 21.022 32.613 20.714 32.462 20.423 32.264 20.176 32.025 19.984 31.739 19.929 31.453 20.000 31.192 20.137 30.909 20.082 30.668 19.901 30.459 19.665 30.316 19.374 30.275 19.044 30.385 18.742 30.555 18.473 30.742 18.214 30.874 17.912 30.986 17.604 31.088 17.297 31.170 16.967 31.223 16.643 31.231 16.302 31.299 15.973 31.445 15.681 31.681 15.489 31.951 15.374 32.234 15.313 32.412 15.066 32.464 14.725 32.566 14.407 32.714 14.115 32.786 13.780 32.852 13.451 32.885 13.126 32.805 12.791 32.819 12.445 32.923 12.132 33.085 11.797 33.170 11.516 33.269 11.242 33.558 10.978 33.615 10.659 33.714 10.330 33.929 10.093 34.212 10.055 34.409 10.308 34.580 10.588 34.791 10.824 35.049 10.989 35.302 11.071 35.604 10.989 35.794 10.720 36.030 10.500 36.319 10.516 36.505 10.791 36.753 10.989 36.995 10.978 36.843 10.604 36.819 10.297 37.129 10.198 37.234 9.890 37.308 9.599 37.220 9.247 37.069 8.951 36.945 8.637 36.923 8.280 36.893 7.879 37.005 7.577 37.019 7.247 36.918 6.896 37.019 6.566 36.989 6.275 36.841 5.973 36.769 5.632 36.657 5.302 36.794 5.011 36.887 4.665 36.898 4.302 36.896 3.934 36.816 3.604 36.772 3.236 36.758 2.901 36.607 2.560 36.602 2.214 36.560 1.857 36.536 1.500 36.497 1.148 36.374 0.830 36.253 0.505 36.096 0.214 35.857 -0.005 35.849 -0.368 35.745 -0.703 35.659 -1.033 35.445 -1.253 35.269 -1.516 35.118 -1.819 35.091 -2.165 35.115 -2.511 35.181 -2.841 35.330 -3.060 35.209 -3.445 35.242 -3.797 35.206 -4.143 35.173 -4.484 35.272 -4.819 35.459 -5.093 35.684 -5.297 35.874 -5.451 35.766 -5.863 35.514 -6.022 35.242 -6.143 34.970 -6.258 34.701 -6.396 34.445 -6.549 34.192 -6.720 33.962 -6.918 33.797 -7.203 33.657 -7.511 33.533 -7.819 33.423 -8.137 33.283 -8.440 33.085 -8.670 32.868 -8.901 32.665 -9.143 32.420 -9.269 32.137 -9.313 31.898 -9.500 31.659 -9.692 31.390 -9.808 31.099 -9.830 30.808 -9.835 30.574 -9.769 30.319 -9.626 30.030 -9.703 29.786 -9.874 29.552 -10.066 29.313 -10.247 29.091 -10.462 28.915 -10.720 28.769 -11.011 28.571 -11.247 28.352 -11.467 28.217 -11.758 28.102 -12.060 28.030 -12.379 27.984 -12.703 27.863 -12.978 27.629 -13.176 27.354 -13.297 27.093 -13.423 26.816 -13.527 26.610 -13.747 26.462 -14.027 26.316 -14.291 26.104 -14.478 25.832 -14.582 25.563 -14.709 25.297 -14.824 25.008 -14.841 24.725 -14.907 24.514 -15.110 24.310 -15.335 24.096 -15.555 23.918 -15.802 23.742 -15.879 23.396 -16.022 23.121 -16.165 22.871 -16.269 22.602 -16.374 22.341 -16.538 22.173 -16.775 21.915 -16.918 21.637 -16.967 21.346 -17.022 21.060 -17.066 20.931 -17.027 21.033 -16.852 20.772 -16.703 20.637 -16.489 20.374 -16.308 20.110 -16.225 19.843 -16.269 19.560 -16.396 19.409 -16.401 19.055 -16.247 18.777 -16.159 18.497 -16.082 18.209 -16.044 17.920 -16.033 17.632 -16.060 17.352 -16.143 17.082 -16.258 16.824 -16.385 16.549 -16.473 16.266 -16.527 15.975 -16.533 15.698 -16.588 15.445 -16.747 15.203 -16.907 14.978 -17.099 14.821 -17.341 14.712 -17.407 14.558 -17.121 14.330 -16.940 14.069 -16.808 13.997 -16.703 14.069 -16.544 13.813 -16.577 13.555 -16.544 13.363 -16.357 13.442 -16.071 13.473 -15.764 13.495 -15.484 13.470 -15.434 13.442 -15.769 13.412 -16.071 13.275 -16.319 13.404 -16.604 13.324 -16.797 13.041 -16.764 12.747 -16.769 12.673 -16.621 12.615 -16.396 12.651 -16.055 12.596 -15.764 12.701 -15.555 12.734 -15.489 12.563 -15.747 12.604 -16.038 12.577 -16.335 12.577 -16.621 12.385 -16.736 12.220 -16.456 12.217 -16.242 11.918 -16.159 11.986 -15.879 11.948 -15.830 11.805 -15.830 11.890 -15.538 11.934 -15.264 11.868 -15.088 11.734 -15.484 11.651 -15.341 11.615 -15.187 11.404 -15.401 11.143 -15.269 11.096 -15.132 11.041 -15.055 10.907 -14.945 10.915 -14.758 10.742 -14.665 10.755 -14.566 10.489 -14.593 10.239 -14.407 10.115 -14.110 9.915 -13.901 9.794 -13.665 9.514 -13.577 9.308 -13.357 9.093 -13.242 8.846 -13.132 8.604 -13.115 8.514 -13.016 8.379 -13.231 8.192 -13.033 7.945 -12.890 7.755 -12.747 7.665 -12.489 7.467 -12.357 7.242 -12.104 7.137 -11.835 6.984 -11.588 6.786 -11.385 6.621 -11.165 6.489 -10.901 6.297 -10.742 6.157 -10.418 6.003 -10.187 5.808 -9.984 5.607 -9.764 5.418 -9.549 5.203 -9.341 5.036 -9.104 4.904 -8.852 4.772 -8.599 4.632 -8.341 4.536 -8.066 4.415 -7.802 4.352 -7.522 4.467 -7.258 4.585 -6.995 4.695 -6.736 4.794 -6.467 4.896 -6.192 5.005 -5.923 5.074 -5.626 5.102 -5.346 5.168 -5.192 5.146 -4.769 5.187 -4.478 5.209 -4.187 5.258 -4.126 5.220 -4.484 5.250 -4.621 5.297 -4.203 5.299 -3.923 5.247 -3.791 5.176 -3.330 5.255 -3.159 5.102 -3.016 4.975 -2.604 4.896 -2.319 4.769 -2.049 4.885 -1.775 5.030 -1.527 5.110 -1.236 5.201 -0.967 5.288 -0.692 5.426 -0.445 5.544 -0.176 5.668 0.082 5.766 0.346 5.871 0.593 6.033 0.429 5.769 0.769 5.898 1.011 6.099 1.209 6.184 1.484 6.247 1.769 6.291 2.055 6.327 2.346 6.354 2.637 6.382 2.929 6.387 3.225 6.514 3.451 6.489 3.637 6.415 4.011 6.376 4.297 6.266 4.560 6.088 4.791 5.852 5.011 5.736 5.209 5.525 5.390 5.426 5.527 5.203 5.407 4.981 5.451 4.690 5.571 4.464 5.786 4.352 6.027 4.371 6.264 4.398 6.599 4.505 6.753 4.709 6.786 4.544 6.973 4.580 7.132 4.646 7.159 4.569 7.379 4.574 7.588 4.527 7.863 4.555 8.198 4.734 8.308 4.849 8.330 4.637 8.555 4.569 8.797 4.184 8.973 4.003 9.220 3.997 9.467 3.920 9.665 3.596 9.698 3.346 9.846 3.093 9.940 2.813 9.874 2.527 9.824 2.247 9.786 1.953 9.786 1.640 9.670 1.440 9.516 1.165 9.440 1.019 9.692 0.624 9.626 0.599 9.516 0.511 9.368 0.283 9.571 0.192 9.852 0.121 9.846 0.140 9.555 0.187 9.352 -0.231 9.319 -0.486 9.203 -0.714 9.066 -0.755 8.901 -0.731 8.769 -1.047 8.929 -1.294 9.077 -1.445 9.330 -1.607 9.379 -1.396 9.104 -1.365 9.055 -1.659 9.231 -1.860 9.379 -1.986 9.440 -2.371 9.654 -2.475 9.890 -2.547 9.984 -2.549 9.802 -2.766 10.027 -2.945 10.253 -3.140 10.467 -3.371 10.643 -3.574 10.846 -3.799 11.022 -4.000 11.231 -4.212 11.418 -4.409 11.637 -4.662 11.791 -4.896 11.907 -5.080 12.071 -5.418 12.176 -5.690 12.159 -5.942 12.363 -5.997 12.571 -5.857 12.819 -5.907 13.000 -6.036 12.610 -6.143 12.324 -6.481 12.462 -6.720 12.621 -6.953 12.786 -7.242 12.846 -7.514 12.956 -7.783 13.066 -8.044 13.203 -8.297 13.341 -8.569 13.379 -8.794 13.253 -8.989 13.055 -9.283 13.104 -9.560 13.198 -9.821 13.280 -10.077 13.385 -10.349 13.522 -10.588 13.692 -10.841 13.786 -11.129 13.835 -11.412 13.791 -11.703 13.786 -11.989 13.736 -12.272 13.604 -12.492 13.445 -12.621 13.209 -12.824 12.973 -13.080 12.863 -13.286 12.659 -13.527 12.522 -13.838 12.473 -14.099 12.346 -14.382 12.330 -14.670 12.275 -14.937 12.181 -15.203 12.093 -15.503 12.022 -15.739 11.846 -15.964 11.775 -16.250 11.797 -16.536 11.813 -16.824 11.797 -17.121 11.758 -17.398 11.731 -17.687 11.725 -17.975 11.775 -18.228 11.918 -18.484 12.049 -18.692 12.269 -18.929 12.445 -19.176 12.599 -19.440 12.725 -19.692 12.863 -19.948 13.005 -20.190 13.165 -20.467 13.264 -20.739 13.374 -20.997 13.500 -21.245 13.665 -21.484 13.835 -21.747 13.967 -21.975 14.154 -22.209 14.335 -22.467 14.467 -22.747 14.533 -22.986 14.451 -23.330 14.473 -23.604 14.484 -23.898 14.484 -24.181 14.489 -24.462 14.593 -24.717 14.720 -24.989 14.824 -25.277 14.819 -25.563 14.857 -25.843 14.890 -26.126 14.962 -26.385 15.044 -26.651 15.126 -26.926 15.192 -27.203 15.275 -27.464 15.401 -27.720 15.555 -27.973 15.720 -28.187 15.945 -28.393 16.170 -28.593 16.429 -28.821 16.604 -29.066 16.775 -29.330 16.907 -29.604 17.022 -29.882 17.110 -30.159 17.214 -30.426 17.335 -30.684 17.484 -30.945 17.632 -31.195 17.797 -31.437 17.978 -31.679 18.170 -31.953 18.280 -32.245 18.330 -32.533 18.313 -32.739 18.088 -32.849 17.879 -33.066 18.005 -33.236 18.093 -33.585 18.357 -33.868 18.434 -34.126 18.346 -34.212 18.478 -34.159 18.791 -34.354 19.005 -34.508 19.308 -34.703 19.549 -34.780 19.879 -34.698 20.154 -34.516 20.440 -34.429 20.791 -34.385 21.099 -34.387 21.440 -34.354 21.808 -34.170 22.082 -34.055 22.385 -34.014 22.736 -34.074 23.044 -34.063 23.390 -34.003 23.731 -34.052 24.071 -34.129 24.407 -34.168 24.769 -33.992 25.027 -34.014 25.385 -33.948 25.643 -33.731 25.863 -33.742 26.209 -33.734 26.555 -33.613 26.868 -33.478 27.170 -33.305 27.451 -33.135 27.725 -32.959 28.000 -32.753 28.247 -32.574 28.516 -32.368 28.758 -32.159 28.989 -31.937 29.203 -31.714 29.418 -31.527 29.676 -31.349 29.940 -31.124 30.159 -30.887 30.352 -30.640 30.527 -30.390 30.692 -30.129 30.846 -29.885 31.027 -29.618 31.159 -29.374 31.346 -29.159 31.560 -28.959 31.797 -28.805 32.060 -28.602 32.313 -28.352 32.451 -28.077 32.566 -27.791 32.610 -27.511 32.681 -27.236 32.786 -26.956 32.874 -26.670 32.901 -26.382 32.923 -26.187 32.835 -25.970 32.582 -25.728 32.769 -25.475 32.984 -25.302 33.264 -25.190 33.538 -25.074 33.830 -24.978 34.132 -24.874 34.429 -24.772 34.731 -24.646 35.016 -24.445 35.236 -24.206 35.423 -23.918 35.511 -23.783 35.396 -23.368 35.456 -23.091 35.522 -22.863 35.538 -22.541 35.505 -22.250 35.527 -22.220 35.423 -22.341 35.346 -21.959 35.313 -21.670 35.258 -21.398 35.137 -21.165 35.082 -20.852 35.033 -20.637 34.846 -20.415 34.692 -20.115 34.736 -19.832 34.714 -19.712 34.692 -19.783 35.000 -19.607 35.236 -19.401 35.456 -19.181 35.637 -18.973 35.885 -18.854 36.165 -18.717 36.368 -18.481 36.582 -18.236 36.813 -17.970 36.929 -17.791 37.176 -17.635 37.412 -17.486 37.676 -17.354 37.945 -17.236 38.170 -17.126 38.516 -17.052 38.769 -16.937 39.088 -16.761 39.308 -16.615 39.566 -16.420 39.786 -16.214 39.956 -15.986 40.121 -15.753 40.324 -15.525 40.522 -15.239 40.615 -15.044 40.676 -14.854 40.742 -14.511 40.742 -14.346 40.681 -14.148 40.615 -13.791 40.582 -13.519 40.560 -13.253 40.560 -12.940 40.516 -12.665 40.582 -12.354 40.500 -12.080 40.516 -11.805 40.478 -11.505 40.451 -11.261 40.434 -10.970 40.544 -10.698 40.566 -10.404 40.445 -10.250 40.209 -10.126 39.973 -9.929 39.758 -9.626 39.709 -9.368 39.621 -9.080 39.533 -8.849 39.456 -8.533 39.330 -8.258 39.330 -7.975 39.434 -7.755 39.319 -7.448 39.313 -7.214 39.440 -6.986 39.522 -6.802 39.308 -6.574 39.137 -6.407 38.934 -6.099 38.813 -5.813 38.846 -5.538 38.956 -5.264 39.055 -4.973 39.137 -4.706 39.242 -4.530 39.456 -4.264 39.593 -4.000 39.670 -3.709 39.835 -3.522 39.885 -3.288 40.055 -2.997 40.170 -2.720 40.203 -2.555 40.451 -2.478 40.714 -2.261 40.890 -2.005 40.967 -1.934 41.286 -1.728 41.505 -1.500 41.687 -1.234 41.846 -0.984 41.973 -0.794 42.154 -0.563 42.357 -0.360 42.538 -0.143 42.753 0.066 42.951 0.277 43.143 0.486 43.341 0.695 43.544 0.887 43.758 1.063 43.989 1.255 44.198 1.445 44.418 1.621 44.648 1.783 44.885 1.923 45.137 2.055 45.390 2.203 45.643 2.349 45.890 2.530 46.115 2.739 46.319 2.934 46.527 3.135 46.736 3.349 46.934 3.563 47.126 3.772 47.330 3.984 47.527 4.203 47.714 4.418 47.912 4.657 48.071 4.909 48.209 5.146 48.379 5.374 48.560 5.615 48.720 5.863 48.874 6.115 49.016 6.393 49.088 6.665 49.181 6.923 49.313 7.162 49.473 7.398 49.637 7.662 49.769 7.931 49.846 8.151 50.055 8.396 50.214 8.646 50.346 8.912 50.473 9.140 50.643 9.396 50.797 9.690 50.824 9.975 50.879 10.269 50.918 10.409 51.159 10.462 51.247 10.538 51.099 10.821 51.126 11.118 51.121 11.396 51.104 11.665 51.214 11.860 51.159 11.953 50.857 11.887 50.588 11.668 50.390 11.538 50.126 11.475 49.846 11.423 49.555 11.319 49.286 11.255 48.995 11.305 48.709 11.280 48.412 11.162 48.143 11.124 47.852 11.154 47.566 11.126 47.286 10.970 47.038 10.827 46.786 10.714 46.516 10.758 46.236 10.816 45.934 10.813 45.681 10.673 45.418 10.547 45.159 10.440 44.907 10.431 44.599 10.453 44.302 10.621 44.055 10.808 43.835 11.027 43.643 11.291 43.495 11.475 43.291 11.599 43.049 11.552 42.725 11.591 42.621 11.780 42.890 11.909 43.148 12.069 43.385 12.374 43.357 12.602 43.203 12.821 43.000 12.942 42.758 13.170 42.549 13.335 42.357 13.604 42.203 13.797 41.989 13.940 41.736 14.159 41.533 14.390 41.363 14.604 41.165 14.698 40.868 14.874 40.665 14.973 40.423 15.036 40.148 15.302 40.038 15.360 39.830 15.176 39.736 15.495 39.560 15.698 39.440 15.973 39.286 16.255 39.209 16.544 39.165 16.813 39.115 17.099 39.027 17.371 38.929 17.635 38.802 17.896 38.654 18.113 38.505 18.242 38.258 18.426 38.049 18.640 37.797 18.755 37.544 19.016 37.418 19.299 37.341 19.596 37.258 19.863 37.253 20.140 37.198 20.445 37.198 20.723 37.154 21.014 37.099 21.170 37.165 21.569 36.956 21.846 36.874 22.115 36.813 22.286 36.555 22.484 36.335 22.665 36.110 22.816 35.813 23.027 35.687 23.286 35.533 23.566 35.495 23.885 35.544 24.003 35.692 24.220 35.429 24.478 35.198 24.731 35.066 24.992 34.940 25.253 34.791 25.511 34.654 25.769 34.505 26.016 34.341 26.277 34.192 26.541 34.044 26.810 33.962 27.077 33.879 27.321 33.736 27.610 33.560 27.838 33.533 28.082 33.330 28.308 33.121 28.541 32.929 28.791 32.769 29.049 32.643 29.327 32.582 29.574 32.390 29.871 32.484 29.874 32.610 29.541 32.714 29.308 32.857 29.080 33.077 28.824 33.192 28.552 33.264 28.335 33.489 28.115 33.692 27.915 33.923 27.805 34.231 28.038 34.429 28.332 34.434 28.596 34.555 28.879 34.643 29.154 34.703 29.415 34.830 29.412 34.962 29.110 34.885 28.824 34.824 28.538 34.786 28.239 34.670 28.091 34.725 28.069 35.093 27.863 35.319 27.613 35.484 27.363 35.648 27.115 35.808 26.885 35.995 26.640 36.170 26.396 36.330 26.143 36.500 25.923 36.643 25.720 36.802 25.464 36.984 25.217 37.148 24.918 37.198 24.692 37.253 24.437 37.440 24.266 37.648 24.157 37.934 23.984 38.198 23.783 38.423 23.530 38.582 23.261 38.725 23.008 38.841 22.802 38.951 22.453 39.093 22.184 39.044 21.893 39.000 21.640 39.099 21.354 39.137 21.080 39.209 20.835 39.396 20.615 39.549 20.385 39.736 20.272 39.989 20.126 40.275 19.942 40.516 19.745 40.720 19.511 40.874 19.236 41.027 18.973 41.159 18.684 41.247 18.451 41.418 18.192 41.538 17.940 41.709 17.750 41.940 17.563 42.165 17.327 42.319 17.085 42.407 16.830 42.610 16.582 42.742 16.302 42.808 16.008 42.841 15.734 42.736 15.456 42.769 15.225 42.742 14.876 42.918 14.613 42.995 14.396 43.022 14.033 43.110 13.783 43.253 13.500 43.264 13.217 43.264 12.951 43.407 12.728 43.560 12.646 43.885 12.632 44.170 12.714 44.445 12.780 44.714 12.797 44.973 12.995 45.198 13.135 45.456 13.327 45.676 13.396 45.962 13.415 46.264 13.423 46.560 13.495 46.846 13.582 47.126 13.673 47.407 13.854 47.643 13.995 47.907 14.005 48.192 14.016 48.473 14.104 48.764 14.321 48.967 14.536 49.165 14.665 49.434 14.766 49.709 14.830 50.000 14.901 50.286 15.036 50.549 15.099 50.841 15.165 51.137 15.258 51.418 15.379 51.681 15.514 51.940 15.679 52.198 15.978 52.187 16.253 52.297 16.437 52.533 16.544 52.813 16.646 53.093 16.734 53.379 16.799 53.670 16.926 53.951 17.019 54.225 17.033 54.527 16.975 54.819 17.060 55.110 17.327 55.264 17.604 55.286 17.830 55.484 17.898 55.780 17.934 56.082 17.995 56.374 18.217 56.566 18.505 56.643 18.736 56.813 18.865 57.082 18.934 57.379 18.953 57.692 19.140 57.797 19.423 57.747 19.709 57.714 19.986 57.808 20.269 57.890 20.505 58.066 20.462 58.253 20.442 58.500 20.739 58.670 20.964 58.802 21.198 58.984 21.382 59.231 21.593 59.429 21.846 59.571 22.096 59.720 22.365 59.830 22.541 59.670 22.692 59.401 22.926 59.220 23.148 59.022 23.390 58.852 23.582 58.654 23.637 58.346 23.717 58.027 23.772 57.725 23.860 57.418 23.970 57.132 24.168 56.896 24.398 56.709 24.632 56.533 24.901 56.407 25.181 56.368 25.467 56.363 25.742 56.319 26.038 56.401 26.236 56.346 25.857 55.989 25.668 55.764 25.497 55.527 25.264 55.313 25.052 55.088 24.860 54.824 24.665 54.643 24.470 54.500 24.231 54.280 24.104 53.995 24.058 53.681 24.102 53.368 24.140 53.082 24.154 52.742 24.102 52.489 23.978 52.198 24.008 51.885 24.250 51.698 24.302 51.495 24.423 51.341 24.621 51.368 24.962 51.571 25.247 51.571 25.538 51.505 25.772 51.560 26.030 51.368 26.080 51.121 25.835 50.951 25.569 50.857 25.297 50.758 25.011 50.808 24.849 50.747 25.157 50.544 25.453 50.407 25.676 50.209 25.956 50.077 26.135 50.104 26.393 50.154 26.668 50.049 26.863 49.885 27.047 49.632 27.190 49.412 27.448 49.220 27.618 48.918 27.821 48.819 28.099 48.654 28.382 48.516 28.646 48.385 28.893 48.247 29.151 48.115 29.357 47.934 29.475 47.802 29.673 48.066 30.022 48.044 29.945 48.478 30.027 48.758 30.225 48.907 30.462 49.005 30.363 49.121 30.157 49.363 30.060 49.648 30.173 50.000 29.934 50.181 29.690 50.385 29.473 50.604 29.187 50.703 28.962 50.868 28.720 51.038 28.434 51.132 28.173 51.280 27.951 51.478 27.841 51.753 27.786 52.071 27.651 52.363 27.448 52.604 27.258 52.791 27.104 53.060 26.989 53.374 26.786 53.593 26.717 53.885 26.706 54.209 26.582 54.489 26.514 54.786 26.659 55.060 26.766 55.357 26.915 55.610 27.036 55.912 27.165 56.203 27.165 56.522 27.071 56.835 26.882 56.995 26.580 57.082 26.297 57.137 26.027 57.209 25.780 57.390 25.703 57.731 25.626 58.011 25.577 58.313 25.574 58.632 25.484 58.929 25.420 59.214 25.437 59.527 25.387 59.846 25.357 60.176 25.354 60.484 25.245 60.786 25.181 61.104 25.126 61.429 25.154 61.692 25.107 61.978 25.168 62.258 25.206 62.462 25.245 62.813 25.236 63.132 25.247 63.462 25.374 63.731 25.385 64.060 25.272 64.368 25.242 64.665 25.313 64.989 25.360 65.297 25.363 65.610 25.415 65.923 25.456 66.242 25.492 66.390 25.146 66.709 24.865 66.747 24.791 67.088 24.607 67.203 24.343 67.291 24.058 67.434 23.865 67.610 23.852 67.956 23.725 68.165 23.659 68.385 23.816 68.654 23.802 68.692 23.569 68.451 23.335 68.544 23.113 68.725 22.962 69.000 22.835 69.280 22.766 69.593 22.852 69.868 22.951 70.176 22.942 70.401 22.569 70.121 22.459 69.808 22.382 69.533 22.343 69.214 22.332 69.005 22.005 69.176 21.816 69.401 21.607 69.626 21.398 69.841 21.173 70.044 20.975 70.269 20.819 70.527 20.714 70.819 20.761 71.110 20.876 71.407 20.997 71.659 21.129 71.956 21.321 72.137 21.610 72.258 21.890 72.104 22.223 72.258 22.283 72.456 22.203 72.725 21.918 72.610 21.681 72.659 21.659 72.918 21.382 72.643 21.096 72.742 20.841 72.885 20.549 72.879 20.280 72.769 19.997 72.692 19.728 72.698 19.478 72.780 19.236 72.879 18.984 72.923 18.714 72.918 18.412 72.956 18.154 73.000 17.835 73.071 17.560 73.154 17.286 73.214 16.995 73.269 16.679 73.319 16.464 73.346 16.146 73.451 15.901 73.571 15.640 73.742 15.418 73.863 15.104 73.956 14.852 74.132 14.610 74.297 14.412 74.401 14.143 74.478 13.841 74.604 13.596 74.687 13.321 74.714 12.992 74.786 12.777 74.879 12.451 75.000 12.198 75.132 11.964 75.308 11.736 75.484 11.486 75.632 11.247 75.764 10.962 75.868 10.695 75.956 10.423 76.082 10.179 76.192 9.986 76.286 9.723 76.341 9.346 76.357 9.135 76.462 8.920 76.604 8.610 76.802 8.385 76.989 8.195 77.214 8.099 77.495 8.198 77.764 8.357 78.016 8.610 78.137 8.854 78.203 9.088 78.418 9.179 78.698 9.258 78.978 9.239 79.269 9.250 79.330 9.352 79.005 9.599 78.956 9.843 79.115 10.093 79.247 10.302 79.423 10.297 79.681 10.418 79.857 10.709 79.846 10.995 79.852 11.316 79.780 11.538 79.775 11.852 79.819 12.154 79.940 12.363 80.088 12.624 80.203 12.907 80.264 13.192 80.319 13.431 80.275 13.607 80.192 13.901 80.203 14.198 80.115 14.486 80.176 14.739 80.121 15.027 80.060 15.316 80.110 15.580 80.231 15.799 80.418 15.860 80.709 15.846 80.863 15.915 81.005 16.220 81.225 16.360 81.451 16.335 81.742 16.434 82.033 16.599 82.280 16.879 82.330 17.118 82.390 17.294 82.626 17.420 82.901 17.574 83.176 17.753 83.346 17.981 83.555 18.157 83.819 18.297 84.082 18.514 84.291 18.723 84.489 18.951 84.676 19.157 84.808 19.385 85.077 19.560 85.319 19.618 85.357 19.599 85.165 19.852 85.407 19.736 85.577 19.827 86.000 20.005 86.264 20.113 86.478 20.349 86.736 20.574 86.868 20.755 86.962 21.069 86.857 21.332 86.929 21.519 87.159 21.602 87.462 21.692 87.758 21.887 87.989 22.148 88.082 22.286 88.016 21.986 88.176 21.695 88.203 21.668 88.346 21.750 88.544 22.025 88.687 21.651 88.808 21.723 89.038 21.945 89.055 21.788 89.341 22.036 89.500 22.148 89.549 21.813 89.654 22.033 89.852 22.330 89.879 22.338 89.923 22.027 90.005 21.860 90.154 22.102 90.423 22.338 90.599 22.624 90.522 22.887 90.505 23.168 90.511 23.382 90.396 23.484 90.143 23.668 89.868 23.791 89.577 23.890 89.478 23.885 89.764 23.662 89.984 23.500 90.247 23.475 90.555 23.126 90.604 22.907 90.786 22.819 91.082 22.827 91.407 22.585 91.632 22.302 91.780 22.052 91.863 21.761 91.940 21.486 91.989 21.203 92.055 20.951 92.203 20.896 92.280 21.016 92.264 20.712 92.407 20.478 92.593 20.418 92.714 20.541 92.742 20.266 92.846 20.234 92.956 20.308 93.049 19.964 93.055 19.948 93.176 20.000 93.440 19.808 93.670 19.599 93.824 19.324 93.912 19.242 93.615 18.989 93.918 19.184 94.033 18.824 94.126 18.637 94.231 18.313 94.368 18.052 94.462 17.766 94.522 17.514 94.577 17.220 94.516 16.929 94.429 16.632 94.346 16.390 94.253 16.096 94.220 16.038 94.368 16.272 94.582 16.354 94.692 16.008 94.720 16.110 94.907 15.865 94.962 16.033 95.137 15.896 95.247 15.973 95.330 15.753 95.434 15.959 95.654 16.190 95.830 16.327 96.082 16.503 96.275 16.668 96.269 16.560 96.604 16.799 96.808 17.047 96.879 17.302 96.951 17.000 97.198 16.690 97.297 16.522 97.478 16.451 97.659 16.093 97.604 15.835 97.703 15.544 97.758 15.264 97.769 14.975 97.802 14.712 97.923 14.420 97.978 14.137 98.077 13.832 98.093 13.695 98.170 13.890 98.231 13.577 98.357 13.321 98.484 13.038 98.588 12.747 98.654 12.473 98.648 12.198 98.637 11.887 98.648 11.750 98.753 11.610 98.775 11.327 98.731 11.022 98.692 10.769 98.549 10.508 98.489 10.223 98.511 10.107 98.610 10.206 98.698 9.879 98.566 9.629 98.500 9.332 98.390 9.058 98.346 8.777 98.253 8.514 98.225 8.245 98.401 8.297 98.665 8.038 98.841 7.838 99.033 7.654 99.214 7.363 99.418 7.228 99.604 6.989 99.698 6.769 99.835 6.555 100.033 6.310 100.176 6.058 100.319 5.758 100.368 5.486 100.374 5.195 100.412 4.929 100.467 4.709 100.604 4.429 100.604 4.162 100.670 3.929 100.780 3.676 100.962 3.442 101.137 3.212 101.302 2.912 101.335 2.692 101.516 2.547 101.775 2.368 101.978 2.201 102.225 2.074 102.495 1.887 102.709 1.750 102.962 1.613 103.214 1.429 103.423 1.363 103.588 1.456 103.901 1.495 104.071 1.500 104.275 1.794 104.176 2.052 104.060 2.310 103.940 2.574 103.786 2.745 103.560 3.005 103.440 3.299 103.440 3.569 103.423 3.863 103.379 4.137 103.429 4.418 103.473 4.709 103.445 4.973 103.346 5.228 103.209 5.462 103.038 5.626 102.797 5.819 102.582 6.049 102.418 6.214 102.192 6.349 101.951 6.547 101.742 6.791 101.577 6.904 101.319 6.874 101.027 7.003 100.769 7.157 100.538 7.324 100.335 7.580 100.176 7.659 100.286 7.420 100.418 7.324 100.489 7.703 100.390 7.984 100.330 8.266 100.275 8.467 100.137 8.706 99.951 8.997 99.918 9.272 99.802 9.234 99.505 9.321 99.275 9.610 99.198 9.893 99.159 10.184 99.187 10.423 99.236 10.695 99.363 10.945 99.489 11.236 99.555 11.516 99.654 11.777 99.797 12.036 99.918 12.299 100.000 12.591 99.973 12.871 100.022 13.140 100.049 13.379 100.044 13.486 100.324 13.530 100.615 13.415 100.929 13.096 100.918 12.810 100.879 12.648 100.973 12.635 101.302 12.651 101.582 12.610 101.885 12.500 102.071 12.327 102.286 12.137 102.566 11.967 102.769 11.703 102.901 11.602 103.022 11.225 103.104 10.926 103.176 10.992 103.429 11.091 103.599 10.802 103.665 10.558 103.632 10.602 103.907 10.533 104.236 10.382 104.484 10.198 104.687 10.085 104.967 9.890 105.038 9.643 104.852 9.357 104.830 9.063 104.813 8.750 104.868 8.591 104.868 8.701 105.198 8.915 105.379 9.126 105.560 9.239 105.830 9.360 106.121 9.593 106.154 9.832 105.989 9.909 105.951 9.659 106.220 9.632 106.505 9.918 106.407 10.074 106.286 9.926 106.582 10.113 106.445 10.135 106.703 10.313 106.632 10.536 106.780 10.555 107.038 10.431 107.324 10.577 107.621 10.698 107.890 10.874 108.104 10.989 108.363 11.168 108.621 11.305 108.863 11.500 109.027 11.681 109.159 11.970 109.209 12.277 109.203 12.492 109.247 12.720 109.396 13.019 109.379 13.291 109.286 13.536 109.269 13.832 109.264 14.146 109.209 14.412 109.132 14.676 109.066 14.945 108.951 15.223 108.896 15.431 108.725 15.668 108.511 15.904 108.357 16.115 108.220 16.302 107.967 16.481 107.709 16.640 107.516 16.876 107.225 17.093 107.071 17.283 106.835 17.495 106.626 17.706 106.418 17.797 106.434 18.071 106.401 18.239 106.181 18.420 105.962 18.684 105.786 18.904 105.659 19.184 105.742 19.462 105.802 19.725 105.879 19.967 106.060 20.110 106.302 20.332 106.544 20.599 106.615 20.819 106.742 20.964 106.813 20.989 107.099 21.118 107.363 21.313 107.522 21.473 107.813 21.522 108.060 21.610 108.363 21.709 108.511 21.832 108.582 21.706 108.824 21.505 109.121 21.462 109.396 21.593 109.637 21.382 109.857 21.091 109.703 20.805 109.736 20.560 109.852 20.327 109.984 20.302 110.357 20.555 110.440 20.780 110.313 21.027 110.209 21.280 110.379 21.308 110.445 21.341 110.676 21.462 111.000 21.495 111.253 21.552 111.544 21.709 111.802 21.813 112.049 21.827 112.374 21.929 112.429 21.854 112.676 21.962 112.940 22.124 113.176 22.286 113.313 22.420 113.247 22.283 113.538 22.615 113.522 22.860 113.385 23.093 113.549 23.025 113.626 22.810 113.659 22.538 113.885 22.374 114.049 22.426 114.275 22.538 114.445 22.632 114.560 22.692 114.764 22.687 114.929 22.819 115.236 22.799 115.495 22.838 115.769 22.874 116.077 22.970 116.368 23.209 116.621 23.316 116.659 23.379 116.670 23.585 116.912 23.654 117.198 23.835 117.505 23.986 117.736 24.159 117.956 24.349 118.022 24.497 117.945 24.602 118.209 24.613 118.544 24.846 118.703 24.995 118.940 25.195 119.049 25.297 119.236 25.511 119.242 25.481 119.440 25.467 119.571 25.766 119.566 25.981 119.549 26.052 119.291 26.239 119.676 26.420 119.753 26.725 119.725 26.681 119.967 26.588 119.984 26.813 120.099 27.052 120.275 27.255 120.368 27.511 120.632 27.775 120.731 27.995 120.709 28.041 120.687 28.088 120.995 28.269 121.231 28.379 121.555 28.681 121.374 28.758 121.297 28.882 121.610 29.102 121.533 29.264 121.709 29.291 121.923 29.541 121.830 29.516 121.571 29.808 121.967 29.901 121.967 30.016 121.648 30.228 121.418 30.266 121.110 30.115 120.758 30.231 120.511 30.294 120.319 30.371 120.797 30.549 121.022 30.712 121.313 30.843 121.604 30.970 121.846 31.266 121.703 31.434 121.429 31.637 121.181 31.764 120.874 31.929 120.687 31.948 120.341 31.962 119.989 32.184 119.725 32.269 119.791 31.989 120.044 32.008 120.346 32.074 120.654 31.898 120.940 31.849 121.264 31.755 121.577 31.794 121.841 32.066 121.615 32.242 121.407 32.470 121.220 32.637 120.901 32.912 120.879 33.190 120.764 33.451 120.621 33.712 120.489 33.981 120.379 34.258 120.258 34.423 119.978 34.544 119.659 34.728 119.363 34.865 119.187 35.115 119.319 35.363 119.511 35.599 119.758 35.764 119.984 35.992 120.187 36.168 120.269 36.146 120.610 36.393 120.775 36.585 120.918 36.734 121.363 36.810 121.615 36.948 122.016 36.890 122.297 37.060 122.495 37.357 122.560 37.484 122.148 37.453 121.852 37.514 121.484 37.651 121.132 37.808 120.824 37.731 120.456 37.585 120.231 37.349 119.923 37.151 119.692 37.137 119.330 37.280 119.011 37.563 118.984 37.824 119.038 38.088 118.857 38.113 118.527 38.146 118.143 38.269 117.835 38.495 117.610 38.769 117.582 39.036 117.731 39.201 118.005 39.093 118.363 39.176 118.764 39.223 119.022 39.530 119.253 39.769 119.429 39.940 119.714 40.071 120.049 40.206 120.401 40.423 120.610 40.679 120.901 40.871 121.126 40.882 121.489 40.868 121.846 40.640 122.165 40.396 122.214 40.157 122.000 39.951 121.769 39.720 121.500 39.495 121.385 39.305 121.731 39.030 121.456 38.835 121.269 38.978 121.764 39.132 122.088 39.354 122.330 39.503 122.648 39.643 122.989 39.758 123.319 39.835 123.665 39.841 124.071 39.951 124.401 39.690 124.720 39.599 125.093 39.451 125.385 39.151 125.330 38.882 125.187 38.734 125.357 38.665 125.467 38.566 125.071 38.269 124.907 38.110 124.868 37.951 125.165 37.810 125.467 37.931 125.780 37.816 126.154 37.813 126.566 37.651 126.637 37.297 126.742 37.088 126.808 36.909 126.830 36.937 126.456 36.736 126.308 36.398 126.538 36.118 126.593 35.898 126.742 35.588 126.571 35.316 126.396 35.049 126.357 34.794 126.500 34.593 126.429 34.398 126.637 34.519 126.907 34.624 127.231 34.574 127.418 34.755 127.522 34.887 127.714 34.973 128.060 34.956 128.412 35.115 128.670 35.104 129.044 35.327 129.319 35.555 129.440 35.865 129.538 36.077 129.456 36.385 129.418 36.673 129.451 36.964 129.423 37.242 129.330 37.497 129.159 37.747 128.978 37.981 128.764 38.234 128.588 38.497 128.440 38.736 128.247 38.923 127.945 39.115 127.676 39.327 127.467 39.613 127.533 39.832 127.698 39.995 128.005 40.071 128.363 40.250 128.670 40.426 128.973 40.643 129.231 40.802 129.544 40.992 129.731 41.299 129.758 41.571 129.692 41.830 129.879 42.060 130.104 42.258 130.385 42.360 130.725 42.621 130.912 42.725 131.291 42.948 131.478 43.195 131.714 43.220 131.934 43.157 132.093 43.179 132.319 42.890 132.423 42.821 132.830 42.728 133.159 42.827 133.610 42.926 133.962 43.102 134.286 43.255 134.632 43.431 134.945 43.651 135.220 43.863 135.473 44.102 135.637 44.341 135.857 44.533 136.159 44.772 136.390 45.000 136.643 45.231 136.890 45.431 137.192 45.654 137.456 45.874 137.731 46.107 137.973 46.360 138.154 46.613 138.346 46.893 138.489 47.137 138.698 47.360 138.978 47.624 139.159 47.876 139.374 48.093 139.670 48.305 139.967 48.547 140.176 48.835 140.275 49.066 140.319 49.360 140.429 49.670 140.527 49.945 140.500 50.165 140.571 50.489 140.489 50.769 140.511 51.038 140.670 51.343 140.780 51.588 140.951 51.819 141.236 52.074 141.407 52.264 141.357 52.500 141.203 52.788 141.220 53.000 140.918 53.066 140.923 53.102 141.313 53.335 141.236 53.505 140.918 53.720 140.484 53.973 140.253 54.187 139.901 54.242 139.549 54.220 139.071 54.179 138.725 53.863 138.703 53.585 138.516 53.610 138.330 53.846 138.412 53.585 137.868 53.632 137.429 53.953 137.637 54.137 137.467 54.283 137.495 54.069 137.181 53.841 137.033 53.901 136.698 54.209 136.786 54.481 136.808 54.626 136.615 54.593 136.082 54.640 135.626 54.819 135.236 55.085 135.511 55.239 135.940 55.442 136.280 55.640 136.643 55.813 137.038 55.997 137.418 56.214 137.775 56.459 138.110 56.706 138.330 56.948 138.654 57.129 139.011 57.335 139.429 57.536 139.813 57.739 140.209 57.937 140.533 58.214 140.703 58.434 141.060 58.602 141.516 58.832 141.852 59.066 142.165 59.239 142.626 59.346 143.165 59.379 143.709 59.387 144.302 59.379 144.791 59.409 145.418 59.316 145.857 59.223 146.231 59.415 146.577 59.335 147.165 59.297 147.692 59.374 148.247 59.272 148.764 59.475 148.934 59.728 149.313 59.728 149.852 59.610 150.385 59.519 150.775 59.522 151.473 59.302 151.885 59.181 152.044 59.140 151.412 58.959 151.242 58.871 151.764 58.989 152.302 58.967 152.863 59.165 153.341 59.159 153.808 59.151 154.374 59.190 154.962 59.426 154.995 59.489 154.440 59.591 154.214 59.868 154.352 60.115 154.615 60.354 154.962 60.544 155.412 60.747 155.830 61.008 156.099 61.223 156.544 61.495 156.747 61.698 157.214 61.783 157.753 61.797 158.330 61.868 158.896 61.810 159.423 61.736 159.775 61.805 160.269 61.451 160.055 61.228 159.896 60.967 160.137 60.703 160.363 60.871 160.907 61.093 161.308 61.302 161.709 61.489 162.104 61.654 162.703 61.676 163.115 62.011 163.088 62.308 163.203 62.541 163.374 62.643 163.995 62.648 164.588 62.516 165.154 62.423 165.280 62.423 164.549 62.212 164.115 61.918 164.066 61.646 163.923 61.393 163.901 61.143 163.698 60.904 163.555 60.761 163.093 60.593 162.500 60.412 161.989 60.162 161.769 59.959 161.368 59.728 161.022 59.547 160.577 59.316 160.225 59.099 159.835 58.830 159.643 58.569 159.275 58.382 158.940 58.190 158.522 58.003 158.176 57.931 157.604 57.797 157.132 57.690 156.874 57.390 156.934 57.113 156.670 56.909 156.341 56.736 156.049 56.412 155.857 56.129 155.736 55.849 155.648 55.560 155.593 55.275 155.555 54.984 155.593 54.701 155.659 54.407 155.736 54.126 155.841 53.841 155.923 53.552 155.984 53.264 156.044 52.978 156.093 52.692 156.181 52.464 156.357 52.143 156.440 51.854 156.495 51.560 156.489 51.283 156.593 51.027 156.824 51.294 157.330 51.508 157.621 51.709 157.973 51.953 158.247 52.223 158.434 52.478 158.495 52.739 158.549 52.973 158.632 53.143 159.242 53.228 159.709 53.245 159.973 53.569 159.885 53.860 159.868 54.132 160.033 54.338 160.374 54.522 160.753 54.541 161.225 54.544 161.714 54.775 162.071 55.044 161.929 55.305 161.742 55.596 161.753 55.863 161.940 56.118 162.170 56.338 162.495 56.404 162.824 56.077 162.912 56.250 163.308 56.549 163.247 56.745 162.984 56.981 162.808 57.286 162.769 57.519 163.049 57.780 163.170 57.893 162.626 57.786 162.291 58.063 161.973 58.349 162.088 58.610 162.335 58.841 162.709 59.071 163.033 59.332 163.242 59.624 163.302 59.882 163.555 59.975 163.989 60.008 164.555 59.890 165.027 60.137 165.231 60.316 165.819 60.390 166.181 60.000 166.143 59.890 166.335 60.137 166.731 60.363 167.115 60.475 167.604 60.571 168.187 60.563 168.758 60.552 169.308 60.291 169.797 60.055 170.005 60.019 170.379 60.363 170.588 60.525 170.945 60.728 171.467 60.879 171.945 61.077 172.275 61.255 172.670 61.418 172.984 61.651 173.516 61.764 174.044 61.896 174.626 62.069 175.225 62.187 175.659 62.321 176.225 62.500 176.703 62.648 177.055 62.755 177.247 62.574 177.588 62.500 178.220 62.379 178.802 62.420 179.176 62.665 179.522 62.956 179.363 63.214 179.220 63.393 178.879 63.577 178.626 63.992 178.538 64.264 178.363 64.302 178.055 64.481 177.434 64.703 177.181 64.626 176.434 64.676 176.269 64.838 175.973 64.742 175.291 64.717 174.923 64.868 175.934 64.846 176.549 64.923 176.978 65.052 176.637 64.904 177.357 64.717 177.780 64.648 178.516 64.753 179.066 64.904 179.615 65.115 -179.885 65.357 -179.544 65.629 -179.429 65.896 -179.780 66.148 -179.544 66.286 -179.071 66.258 -178.560 65.956 -178.835 65.662 -178.533 65.484 -178.181 65.511 -177.489 65.582 -176.841 65.470 -176.170 65.231 -175.857 64.951 -175.709 64.805 -175.148 64.670 -174.462 64.467 -174.033 64.440 -173.489 64.475 -173.346 64.368 -173.049 64.563 -172.742 64.860 -172.835 65.140 -172.297 65.286 -172.390 65.511 -172.374 65.635 -172.473 65.511 -171.808 65.621 -171.225 65.747 -171.258 65.723 -170.615 65.981 -170.209 66.146 -169.989 66.310 -170.511 66.544 -171.011 66.755 -171.495 66.956 -171.984 66.984 -172.753 67.000 -173.357 67.096 -174.236 67.025 -174.363 66.731 -174.044 66.511 -174.011 66.357 -174.093 66.448 -174.484 66.703 -174.824 67.000 -174.868 67.313 -174.879 67.478 -175.220 67.775 -175.681 67.942 -176.308 68.121 -176.984 68.264 -177.538 68.415 -178.066 68.629 -178.687 68.838 -179.280 68.934 -179.714 69.058 175.637 69.272 175.000 69.396 174.549 69.549 173.588 69.657 172.819 69.824 172.121 69.874 171.280 70.025 171.725 70.096 170.896 70.014 170.522 69.728 170.352 69.544 170.544 69.266 170.890 69.003 170.918 68.821 170.484 68.849 169.560 69.110 169.154 69.261 168.396 69.549 168.143 69.701 167.665 69.522 166.819 69.544 165.989 69.585 165.170 69.651 164.379 69.712 163.687 69.679 162.852 69.602 162.121 69.374 161.527 69.099 161.495 68.813 161.407 68.659 161.115 69.077 161.148 69.357 160.973 69.629 160.709 69.769 159.940 70.058 159.813 70.299 160.055 70.580 159.813 70.805 159.280 70.956 158.527 71.055 157.698 71.085 156.797 71.066 155.857 71.025 155.181 70.951 154.242 70.863 153.412 70.846 152.522 71.008 151.923 71.299 151.527 71.341 150.681 71.398 150.275 71.629 149.780 71.780 149.220 71.970 149.951 72.190 149.341 72.294 148.445 72.319 147.462 72.146 146.786 71.890 146.302 71.714 145.549 71.830 145.115 72.044 145.725 72.126 145.989 71.964 146.214 72.269 146.538 72.269 145.368 72.302 144.747 72.346 146.242 72.409 146.462 72.536 145.484 72.618 144.549 72.676 143.610 72.701 142.632 72.766 141.687 72.772 140.890 72.516 140.654 72.473 139.676 72.214 139.396 72.126 139.923 71.865 139.615 71.514 139.753 71.514 139.060 71.574 138.368 71.310 138.033 71.234 137.659 71.478 136.786 71.610 136.066 71.544 135.236 71.363 134.571 71.467 133.566 71.684 132.962 71.799 132.489 71.429 132.055 71.173 131.901 70.874 131.500 70.852 130.841 71.008 130.170 71.192 129.654 71.508 129.225 71.725 129.187 71.865 128.956 72.082 128.269 72.302 127.676 72.302 126.907 71.964 127.159 71.690 127.225 71.563 127.209 71.953 126.934 72.250 126.473 72.357 125.676 72.560 124.962 72.695 124.115 72.758 123.198 72.882 122.242 72.953 121.401 72.981 120.423 72.967 119.890 73.203 118.577 73.497 118.533 73.591 117.368 73.665 116.368 73.679 115.330 73.582 114.352 73.401 113.720 73.124 113.549 72.720 113.511 72.835 113.297 73.124 113.489 73.401 113.308 73.679 113.335 73.843 112.841 73.761 111.775 73.973 111.143 73.953 109.978 73.720 109.907 73.659 110.544 73.470 109.440 73.335 108.709 73.217 107.984 73.162 106.824 73.033 106.181 72.810 105.593 72.857 105.429 73.118 105.934 73.321 106.516 73.558 107.165 73.665 108.055 73.885 108.681 74.099 109.473 74.324 109.940 74.530 110.742 74.703 111.709 74.912 112.456 75.126 113.203 75.412 113.604 75.635 112.967 75.742 112.940 75.665 113.692 75.953 113.577 76.176 112.940 76.434 112.126 76.681 111.308 76.723 110.165 76.731 108.857 76.615 107.874 76.607 106.780 76.964 107.055 77.049 105.758 77.170 104.907 77.475 105.786 77.679 104.330 77.580 103.022 77.360 102.099 77.102 101.324 76.846 100.995 76.549 101.231 76.451 101.511 76.475 100.005 76.385 99.181 76.063 99.835 75.788 99.527 75.376 99.758 75.536 99.445 75.783 99.407 76.071 99.549 76.176 98.571 76.008 97.451 75.937 96.385 76.000 95.907 76.135 95.236 76.096 94.143 75.953 93.352 75.750 92.297 75.651 91.242 75.566 90.110 75.429 89.132 75.225 88.368 75.047 87.396 74.745 86.978 74.703 86.495 74.665 86.104 74.423 86.912 74.365 86.703 74.308 86.220 74.058 87.060 73.802 87.412 73.582 86.747 73.415 85.978 73.162 86.571 73.118 86.560 73.390 85.896 73.637 86.407 73.849 86.615 73.747 85.313 73.720 84.308 73.665 83.291 73.659 82.247 73.604 81.214 73.462 80.516 73.184 80.451 72.920 80.791 72.632 80.720 72.390 81.170 72.264 82.082 71.995 82.484 71.824 83.264 71.555 83.538 71.275 83.264 71.019 83.324 70.717 83.615 70.431 83.654 70.266 82.967 70.712 83.093 70.885 82.742 70.560 82.297 70.407 82.220 70.832 82.319 71.126 82.291 71.363 82.714 71.629 83.143 71.745 82.516 71.739 81.577 71.995 80.863 72.157 80.352 72.327 79.555 72.382 78.610 72.264 77.786 72.088 77.747 71.879 77.824 72.008 76.907 71.890 76.148 71.599 76.346 71.412 77.027 71.310 77.813 71.096 78.390 70.967 78.549 71.151 77.143 71.209 76.379 71.305 75.560 71.533 75.412 71.835 75.286 72.107 75.516 72.376 75.648 72.662 75.511 72.753 74.989 72.390 75.099 72.113 74.896 71.940 74.165 71.750 73.527 71.453 73.198 71.192 73.593 70.915 73.901 70.648 74.275 70.374 74.093 70.113 73.742 69.819 73.604 69.549 73.758 69.266 73.819 69.115 74.198 69.126 75.033 69.234 75.786 69.132 76.571 68.973 77.231 68.775 77.709 68.497 77.868 68.247 77.934 67.992 77.511 67.745 77.725 67.648 78.456 67.582 78.676 67.588 77.758 67.810 77.220 68.099 77.264 68.374 77.253 68.618 77.055 68.882 76.615 68.951 75.956 68.854 75.203 68.690 74.533 68.393 74.429 68.121 74.720 67.830 74.791 67.577 74.478 67.349 74.011 67.058 73.868 66.838 73.440 66.670 72.852 66.481 72.385 66.264 72.005 66.352 71.286 66.343 70.549 66.434 69.874 66.582 69.242 66.805 69.346 66.766 70.093 66.632 70.676 66.717 71.429 66.956 71.621 67.206 72.115 67.459 72.467 67.690 72.940 67.948 73.159 68.234 73.192 68.497 73.533 68.745 73.027 68.975 72.577 69.266 72.555 69.544 72.582 69.841 72.637 70.135 72.538 70.401 72.648 70.681 72.758 70.973 72.714 71.214 72.335 71.484 71.934 71.750 72.308 72.019 72.599 72.302 72.813 72.613 72.775 72.810 72.126 72.901 71.297 72.896 70.291 72.887 69.451 72.580 68.934 72.283 68.775 71.995 68.593 71.720 68.319 71.484 67.791 71.299 67.077 71.044 66.758 70.805 66.940 70.580 67.258 70.294 67.165 70.041 67.104 69.747 66.791 69.618 67.066 69.489 67.967 69.206 68.165 68.962 68.687 68.860 69.055 68.538 68.802 68.316 68.313 68.566 67.643 68.802 67.077 68.956 66.396 69.110 65.742 69.245 64.945 69.473 64.429 69.613 63.703 69.712 62.918 69.753 62.088 69.824 61.264 69.734 60.621 69.527 60.247 69.250 60.560 69.019 60.846 68.723 60.374 68.585 59.879 68.374 59.571 68.544 59.093 68.832 59.192 68.975 58.841 68.808 58.176 68.637 57.440 68.596 56.692 68.613 55.956 68.503 55.220 68.258 54.709 68.247 54.005 68.352 53.582 68.643 53.808 68.896 53.918 68.986 54.170 68.882 53.308 68.717 52.659 68.538 52.544 68.462 52.165 68.423 51.429 68.310 50.703 68.091 50.022 67.942 49.478 67.769 48.846 67.643 48.187 67.453 47.868 67.165 47.742 66.918 47.484 66.824 46.742 66.832 46.291 67.049 45.692 67.255 45.247 67.489 45.027 67.720 45.495 67.810 46.275 67.942 46.637 68.192 46.352 68.445 45.896 68.571 45.165 68.549 44.374 68.533 43.692 68.104 44.242 67.879 44.148 67.604 44.000 67.261 43.835 67.058 44.335 66.761 44.462 66.500 44.313 66.220 44.110 66.041 43.978 66.154 43.478 66.415 42.989 66.448 42.308 66.212 41.687 66.030 41.143 65.876 40.566 65.673 40.071 65.442 39.736 65.176 39.995 64.926 40.346 64.635 40.330 64.604 39.643 64.739 38.890 64.775 38.253 65.008 37.725 65.154 37.066 64.909 36.593 64.668 36.769 64.418 37.209 64.343 37.846 64.008 37.984 63.857 37.401 63.937 36.742 64.102 36.247 64.308 35.797 64.396 35.176 64.681 34.868 64.953 34.819 65.212 34.610 65.451 34.538 65.755 34.808 66.003 34.643 66.214 34.093 66.382 33.555 66.588 33.165 66.819 32.681 67.063 32.286 67.146 32.209 67.038 32.841 66.786 33.456 66.709 34.033 66.596 34.588 66.448 35.308 66.343 35.978 66.286 36.692 66.195 37.363 66.088 38.005 66.074 38.714 66.154 39.407 66.291 40.038 66.478 40.577 66.717 41.000 66.981 41.308 67.245 41.225 67.533 41.044 67.758 40.676 67.937 40.214 68.104 39.681 68.280 38.945 68.382 38.445 68.665 37.764 68.843 37.148 69.025 36.505 69.184 35.846 69.228 35.093 69.305 34.280 69.245 33.621 69.170 33.280 69.412 33.016 69.522 32.319 69.662 32.291 69.723 32.868 69.846 31.973 69.695 31.385 69.780 30.500 69.747 30.016 69.835 29.588 70.025 29.225 70.124 28.945 70.102 30.126 70.294 30.852 70.492 30.604 70.637 29.978 70.786 29.154 70.632 28.505 70.396 28.319 70.236 28.176 70.574 28.038 70.821 28.154 71.025 28.159 70.951 27.429 70.659 27.159 70.533 26.676 70.827 26.429 70.516 25.797 70.261 25.434 70.203 25.088 70.527 25.236 70.846 25.648 70.898 24.995 70.728 24.473 70.486 24.038 70.242 23.418 70.036 23.126 70.187 22.434 70.242 21.659 70.124 21.544 69.973 21.978 69.841 21.841 69.885 21.093 69.695 20.599 69.484 20.500 69.407 20.143 69.753 20.368 69.852 20.099 69.566 19.835 69.533 19.643 69.742 19.374 69.484 19.126 69.330 19.220 69.396 18.709 69.319 18.313 69.052 17.648 68.786 17.533 68.624 16.797 68.456 16.868 68.387 17.478 68.299 17.110 68.275 16.445 68.110 16.445 67.956 16.291 68.129 15.731 67.956 15.544 67.764 15.055 67.637 15.516 67.448 15.275 67.409 14.747 67.255 14.703 67.181 15.148 67.052 14.308 66.854 13.742 66.615 13.462 66.335 13.280 66.214 13.714 66.049 12.940 65.854 12.786 65.569 12.566 65.272 12.566 65.049 12.159 64.937 11.577 64.838 11.478 64.854 11.824 64.563 11.549 64.467 11.115 64.382 10.599 64.148 10.181 63.915 9.962 63.712 9.802 63.538 10.192 63.701 10.780 63.896 10.907 63.962 11.297 63.736 11.187 63.525 10.780 63.368 10.176 63.456 9.868 63.560 9.451 63.407 9.115 63.176 8.544 62.995 8.440 62.912 8.429 62.984 8.055 62.832 8.181 62.964 7.423 62.819 7.099 62.739 7.676 62.714 7.857 62.585 7.374 62.607 6.670 62.486 6.484 62.341 7.022 62.220 7.071 62.341 6.527 62.253 6.401 62.179 6.060 62.096 6.000 62.115 5.516 62.055 5.209 61.918 5.390 61.882 5.934 61.827 6.280 61.852 5.456 61.635 5.187 61.387 5.308 61.148 5.220 61.159 5.879 61.195 6.445 61.231 6.780 61.250 7.264 61.291 7.462 61.008 7.137 61.069 6.698 61.093 6.049 61.052 5.500 60.898 5.192 60.684 5.330 60.481 5.511 60.286 5.247 60.253 5.538 60.228 5.654 60.113 5.857 60.396 6.264 60.451 6.791 60.228 6.357 59.942 5.857 59.808 5.918 59.772 6.044 59.624 5.533 59.393 5.324 59.376 5.687 59.467 6.038 59.527 6.308 59.272 6.159 59.000 6.082 58.948 6.264 58.929 5.654 58.635 5.566 58.429 5.951 58.280 6.522 58.121 6.835 58.025 7.253 58.066 7.764 58.181 8.209 58.387 8.670 58.659 9.077 58.843 9.390 59.022 9.764 59.107 10.275 59.404 10.423 59.629 10.418 59.777 10.637 59.393 10.676 59.168 10.984 59.011 11.258 58.676 11.231 58.376 11.423 58.234 11.753 57.865 11.742 57.621 11.852 57.352 12.049 57.088 12.253 56.835 12.522 56.549 12.808 56.275 12.643 56.011 12.709 55.745 12.956 55.437 12.962 55.360 13.462 55.409 13.956 55.536 14.297 55.819 14.247 56.044 14.621 56.159 14.995 56.168 15.495 56.192 15.929 56.516 16.170 56.761 16.396 57.060 16.495 57.349 16.566 57.621 16.610 57.890 16.604 58.146 16.725 58.429 16.709 58.615 16.478 58.646 16.423 58.687 17.049 58.849 17.484 59.008 17.797 59.192 18.330 59.354 18.401 59.264 17.698 59.332 17.203 59.445 16.698 59.508 16.390 59.552 17.071 59.552 17.538 59.670 17.610 59.393 18.044 59.500 18.429 59.739 18.863 59.978 18.879 60.223 18.473 60.440 18.115 60.580 17.665 60.742 17.280 61.036 17.181 61.330 17.176 61.629 17.225 61.827 17.385 62.154 17.516 62.437 17.511 62.626 17.962 62.865 18.077 63.036 18.495 63.236 18.945 63.464 19.489 63.621 20.022 63.753 20.467 64.019 20.896 64.280 21.225 64.519 21.456 64.764 21.187 65.044 21.473 65.330 21.560 65.538 21.984 65.626 22.055 65.676 22.319 65.821 22.676 65.783 23.330 65.791 24.060 65.761 24.648 65.500 25.236 65.212 25.291 64.918 25.264 64.788 24.626 64.525 24.280 64.286 23.901 64.049 23.516 63.832 23.093 63.654 22.676 63.418 22.319 63.212 21.912 63.082 21.533 62.810 21.231 62.536 21.132 62.291 21.297 61.981 21.324 61.698 21.538 61.467 21.538 61.124 21.445 60.860 21.379 60.588 21.582 60.462 22.022 60.297 22.577 60.190 22.989 59.942 23.170 59.843 23.148 59.989 23.588 60.025 24.269 60.132 24.725 60.212 25.220 60.332 25.852 60.431 26.313 60.486 26.753 60.508 27.396 60.536 27.929 60.582 28.571 60.288 28.874 60.176 29.379 60.102 29.890 59.929 29.995 59.962 29.192 59.819 28.731 59.723 28.209 59.470 27.923 59.440 27.346 59.500 26.780 59.580 26.236 59.602 25.681 59.511 25.159 59.478 24.648 59.354 24.115 59.201 23.604 58.956 23.511 58.703 23.626 58.382 23.780 58.291 24.346 57.997 24.396 57.714 24.330 57.426 24.390 57.165 24.264 56.997 23.808 57.099 23.330 57.354 23.082 57.571 22.709 57.701 22.379 57.569 21.813 57.341 21.495 57.060 21.379 56.810 21.104 56.486 21.027 56.236 20.995 55.951 21.055 55.670 21.137 55.376 21.242 55.115 21.214 54.915 21.005 55.041 20.698 55.332 21.022 55.508 21.066 55.107 20.720 54.959 20.319 54.838 19.951 54.555 19.769 54.385 19.379 54.360 18.879 54.547 18.549 54.736 18.533 54.805 17.808 54.736 17.324 54.604 16.879 54.478 16.445 54.294 16.159 54.190 15.615 54.110 15.143 54.005 14.681 53.956 14.225 53.986 13.940 53.797 14.511 53.698 14.357 53.830 13.934 54.093 13.681 54.217 13.275 54.385 12.863 54.371 12.544 54.162 12.022 54.038 11.560 53.967 11.242 54.085 10.912 54.352 10.945 54.393 10.291 54.574 9.989 54.799 9.742 54.931 9.604 55.228 9.593 55.536 9.670 55.750 9.868 55.956 10.214 56.187 10.484 56.363 10.874 56.519 10.582 56.632 10.253 57.011 10.192 57.264 10.511 57.560 10.478 57.662 10.401 57.505 9.879 57.253 9.571 57.137 9.115 57.063 8.604 56.788 8.291 56.703 8.522 57.000 8.912 57.030 9.269 56.997 9.582 56.670 9.253 56.613 9.176 56.714 8.874 56.566 8.456 56.437 8.165 56.250 8.170 55.942 8.214 55.610 8.159 55.478 8.418 55.146 8.588 54.868 8.665 54.618 8.863 54.407 8.791 54.250 8.819 53.992 8.973 53.805 9.379 53.662 9.538 53.849 8.896 53.764 8.538 53.497 8.401 53.571 8.082 53.698 7.687 53.610 7.198 53.354 7.165 53.319 7.011 53.442 6.621 53.404 6.143 53.316 5.676 53.115 5.352 52.942 4.929 52.788 4.676 52.500 4.588 52.236 4.418 51.992 4.115 51.791 3.885 51.654 3.923 51.541 4.055 51.478 3.692 51.363 4.077 51.374 3.368 51.247 2.951 51.099 2.549 51.016 2.110 50.893 1.681 50.613 1.577 50.319 1.588 50.140 1.473 49.948 1.104 49.863 0.676 49.723 0.275 49.459 0.236 49.305 -0.209 49.349 -0.643 49.393 -1.099 49.640 -1.357 49.621 -1.835 49.286 -1.670 49.019 -1.571 48.690 -1.533 48.615 -1.995 48.629 -2.379 48.599 -2.780 48.813 -3.115 48.761 -3.549 48.687 -3.940 48.640 -4.401 48.429 -4.593 48.247 -4.412 48.000 -4.544 47.857 -4.137 47.802 -3.747 47.712 -3.275 47.585 -2.984 47.530 -2.643 47.319 -2.379 47.214 -2.000 46.887 -2.071 46.624 -1.874 46.445 -1.632 46.275 -1.225 45.989 -1.099 45.731 -1.115 45.489 -0.830 45.220 -0.687 45.063 -0.621 45.451 -0.940 45.442 -1.132 45.146 -1.187 44.857 -1.231 44.646 -1.187 44.283 -1.291 43.997 -1.357 43.717 -1.434 43.456 -1.621 43.346 -1.984 43.346 -2.368 43.431 -2.747 43.390 -3.121 43.481 -3.522 43.473 -3.890 43.415 -4.335 43.437 -4.720 43.500 -5.110 43.560 -5.478 43.621 -5.879 43.588 -6.297 43.577 -6.687 43.563 -7.077 43.695 -7.467 43.736 -7.813 43.624 -8.170 43.418 -8.308 43.299 -8.852 43.151 -9.154 42.923 -9.203 42.690 -8.967 42.492 -8.802 42.253 -8.769 41.929 -8.841 41.668 -8.813 41.374 -8.764 41.099 -8.676 40.808 -8.703 40.673 -8.703 40.206 -8.857 39.962 -8.940 39.692 -9.071 39.440 -9.242 39.234 -9.379 38.940 -9.445 38.712 -9.368 38.841 -9.071 38.937 -8.934 38.615 -9.198 38.462 -9.060 38.437 -8.786 38.069 -8.835 37.775 -8.802 37.500 -8.819 37.220 -8.901 37.058 -8.841 37.093 -8.434 37.036 -8.060 37.049 -7.736 37.179 -7.407 37.209 -7.033 37.165 -6.824 36.959 -6.516 36.799 -6.335 36.478 -6.236 36.206 -6.027 36.055 -5.714 36.135 -5.412 36.374 -5.209 36.492 -4.885 36.585 -4.560 36.717 -4.275 36.745 -3.918 36.725 -3.555 36.750 -3.203 36.720 -2.841 36.805 -2.522 36.797 -2.143 37.022 -1.896 37.291 -1.736 37.478 -1.467 37.563 -1.126 37.651 -0.808 37.931 -0.714 38.220 -0.577 38.434 -0.363 38.591 -0.044 38.802 0.110 39.052 -0.192 39.327 -0.297 39.602 -0.269 39.854 -0.088 40.085 0.132 40.313 0.363 40.563 0.566 40.714 0.764 41.022 0.989 41.126 1.330 41.212 1.709 41.291 2.077 41.486 2.363 41.629 2.703 41.780 3.027 42.011 3.225 42.297 3.242 42.588 3.110 42.879 3.066 43.118 3.165 43.308 3.495 43.492 3.819 43.549 4.093 43.423 4.527 43.442 4.835 43.429 5.137 43.236 5.456 43.115 5.846 43.099 6.214 43.242 6.610 43.451 6.852 43.632 7.170 43.764 7.505 43.846 7.907 44.030 8.198 44.253 8.445 44.407 8.791 44.338 9.187 44.203 9.527 44.069 9.868 43.909 10.192 43.632 10.286 43.371 10.429 43.093 10.527 42.898 10.676 42.703 10.962 42.445 11.187 42.332 11.538 42.102 11.802 41.923 12.099 41.698 12.330 41.486 12.621 41.338 12.945 41.266 13.247 41.228 13.626 41.052 13.918 40.830 14.143 40.651 14.445 40.591 14.835 40.299 14.962 40.099 15.209 40.033 15.544 39.838 15.775 39.563 15.885 39.302 16.038 39.022 16.126 38.766 16.132 38.577 15.890 38.299 15.769 38.058 15.648 37.923 15.907 38.080 16.154 38.308 16.379 38.527 16.566 38.802 16.626 38.920 16.984 39.080 17.148 39.379 17.093 39.574 16.813 39.750 16.533 40.041 16.626 40.299 16.791 40.489 17.066 40.407 17.319 40.294 17.720 40.115 17.973 39.885 18.137 39.915 18.401 40.209 18.456 40.442 18.225 40.640 17.956 40.783 17.615 40.948 17.308 41.096 16.978 41.203 16.626 41.327 16.286 41.530 15.962 41.849 16.082 41.918 15.637 41.920 15.253 42.025 14.901 42.203 14.615 42.401 14.324 42.621 14.066 42.882 13.912 43.162 13.808 43.434 13.665 43.629 13.434 43.802 13.099 43.970 12.775 44.151 12.473 44.412 12.308 44.703 12.264 44.948 12.412 45.264 12.236 45.497 12.456 45.580 12.830 45.720 13.170 45.712 13.571 45.525 13.632 45.242 13.593 44.997 13.731 44.898 13.995 45.135 14.209 45.294 14.478 45.093 14.808 44.827 14.896 44.566 15.027 44.360 15.313 44.225 15.280 43.901 15.516 43.709 15.835 43.516 16.077 43.505 16.484 43.376 16.874 43.190 17.170 42.995 17.489 42.912 17.549 42.967 17.231 42.797 17.764 42.654 18.099 42.464 18.434 42.374 18.692 42.140 19.022 41.918 19.258 41.720 19.571 41.475 19.467 41.190 19.473 40.912 19.445 40.577 19.390 40.349 19.407 40.104 19.709 39.904 19.951 39.646 20.088 39.429 20.258 39.195 20.527 39.033 20.830 38.934 20.984 38.742 20.863 38.473 21.082 38.379 21.286 38.335 21.599 38.376 22.033 38.371 22.401 38.299 22.720 38.093 22.967 38.151 22.385 38.272 22.060 38.253 21.747 38.135 21.396 37.868 21.203 37.621 21.418 37.374 21.659 37.069 21.615 36.854 21.863 36.934 22.176 36.673 22.357 36.558 22.484 36.739 22.769 36.519 23.011 36.549 23.115 36.830 23.055 37.118 22.940 37.382 22.786 37.522 22.896 37.371 23.198 37.544 23.379 37.758 23.132 37.934 23.137 37.986 23.533 37.816 23.813 37.794 24.038 38.148 24.027 38.335 23.775 38.495 23.467 38.648 23.198 38.783 22.841 38.885 22.714 39.091 22.951 39.299 23.000 39.206 23.192 39.582 22.973 39.838 22.786 40.088 22.588 40.401 22.626 40.525 22.857 40.291 23.137 40.060 23.357 40.019 23.544 40.245 23.527 40.047 23.824 40.074 23.945 40.313 23.852 40.297 24.154 40.588 23.802 40.753 23.896 40.810 24.264 40.909 24.566 40.923 24.918 40.956 25.225 40.865 25.610 40.794 25.995 40.602 26.236 40.629 26.643 40.527 26.676 40.357 26.319 40.176 26.341 40.456 26.725 40.599 27.066 40.775 27.357 40.984 27.604 41.016 27.989 41.047 28.368 41.000 28.670 41.157 29.016 41.338 28.687 41.470 28.341 41.670 28.082 41.940 28.000 42.212 27.824 42.434 27.588 42.629 27.665 42.827 27.890 43.140 27.934 43.374 28.170 43.484 28.527 43.805 28.599 44.099 28.654 44.365 28.703 44.621 28.852 44.846 29.044 44.860 29.544 45.151 29.670 45.434 29.698 45.692 29.731 45.761 29.995 46.036 30.423 46.283 30.659 46.527 30.852 46.618 31.269 46.706 31.571 46.775 31.907 47.027 31.879 47.099 31.857 46.786 31.973 46.588 32.198 46.544 32.396 46.533 31.797 46.495 31.698 46.313 31.951 46.129 32.341 46.115 32.764 46.143 33.192 46.052 33.571 45.871 33.604 45.747 33.198 45.596 32.835 45.382 32.659 45.228 33.143 45.107 33.500 44.832 33.571 44.552 33.505 44.396 33.879 44.514 34.242 44.725 34.516 44.813 34.907 44.923 35.247 45.074 35.566 45.014 36.000 45.099 36.374 45.393 36.451 45.412 35.934 45.321 35.560 45.473 35.231 45.717 35.011 45.986 34.863 46.234 34.945 46.288 35.225 46.536 35.681 46.648 36.082 46.703 36.412 46.739 36.813 46.909 37.247 47.055 37.588 47.074 38.044 47.159 38.423 47.198 38.720 47.173 39.253 46.997 39.082 46.876 38.692 46.717 38.412 46.640 37.945 46.533 37.808 46.357 38.071 46.168 38.423 46.077 38.374 45.962 38.110 45.909 37.956 45.538 37.648 45.332 37.593 45.302 37.159 45.324 36.802 45.121 36.742 44.975 37.176 44.745 37.407 44.659 37.797 44.489 38.099 44.349 38.445 44.231 38.802 44.041 39.104 43.838 39.390 43.621 39.659 43.426 39.951 43.236 40.269 43.104 40.593 42.992 40.956 42.797 41.231 42.607 41.500 42.324 41.599 42.047 41.714 41.755 41.731 41.516 41.516 41.327 41.247 41.195 40.901 41.058 40.560 40.951 40.187 40.986 39.808 41.069 39.434 41.049 39.055 40.964 38.676 40.929 38.313 41.003 37.923 41.082 37.610 41.137 37.225 41.297 36.929 41.308 36.560 41.371 36.242 41.662 36.005 41.651 35.659 41.731 35.297 41.989 35.115 42.003 34.846 41.951 34.467 41.970 34.077 41.986 33.687 41.992 33.297 41.893 32.929 41.802 32.555 41.670 32.231 41.511 31.901 41.368 31.566 41.168 31.324 41.080 30.945 41.135 30.577 41.168 30.209 41.154 29.819 41.201 29.445 41.148 29.104 40.896 29.176 40.777 29.462 40.723 29.687 40.651 29.137 40.459 28.940 40.385 28.544 40.390 28.176 40.426 27.835 40.360 27.407 40.426 27.099 40.363 26.731 40.170 26.440 39.945 26.203 39.659 26.137 39.478 26.236 39.544 26.637 39.456 26.841 39.223 26.725 38.909 26.929 38.635 26.819 38.426 26.830 38.519 26.434 38.236 26.434 38.102 26.868 37.948 27.198 37.659 27.148 37.396 27.286 37.187 27.462 37.000 27.379 37.003 27.758 37.030 28.115 36.948 28.154 36.805 27.918 36.725 27.648 36.703 28.132 36.794 28.533 36.670 28.896 36.538 29.088 36.288 29.280 36.179 29.615 36.203 29.923 36.266 30.291 36.396 30.500 36.679 30.571 36.854 30.764 36.832 31.132 36.745 31.467 36.607 31.791 36.467 32.099 36.236 32.319 36.071 32.604 36.074 32.962 36.135 33.297 36.168 33.643 36.291 33.962 36.519 34.214 36.712 34.489 36.775 34.819 36.643 35.137 36.585 35.484 36.723 35.681 36.841 36.093 36.569 36.115 36.343 35.852 36.052 35.934 35.783 35.835 35.519 35.808 35.234 35.929 34.953 35.890 34.668 35.962 34.440 35.835 34.212 35.654 33.929 35.549 33.668 35.412 33.407 35.269 33.148 35.148 32.863 35.027 32.604 34.912 32.321 34.841 32.044 34.747 31.780 34.615 31.536 34.440 31.324 34.209 31.181 33.918 31.124 33.588 31.107 33.236 31.099 32.973 31.082 32.731 31.132 32.341 30.758 32.330 30.514 32.330 ; #1 1 52.745 -128.143 52.415 -128.269 52.492 -128.066 52.396 -127.923 52.335 -127.621 52.681 -127.077 52.489 -127.170 52.223 -126.824 52.245 -126.995 52.132 -127.462 51.986 -127.709 51.618 -127.698 51.714 -127.049 51.651 -127.286 51.426 -127.637 51.330 -127.335 51.220 -127.571 50.926 -127.247 50.915 -126.923 50.920 -126.434 50.750 -126.115 50.904 -125.626 50.766 -125.665 50.602 -126.110 50.492 -125.912 50.549 -125.511 50.500 -125.110 50.799 -124.901 50.766 -124.852 50.418 -124.973 50.431 -124.549 50.360 -124.588 50.058 -124.714 49.835 -124.533 49.827 -124.082 50.080 -123.923 50.022 -123.857 49.712 -123.758 49.632 -123.857 49.495 -123.874 49.544 -123.352 49.368 -123.044 49.201 -123.126 49.008 -122.907 48.777 -122.637 48.503 -122.560 48.201 -122.434 47.986 -122.280 47.670 -122.368 47.368 -122.401 47.146 -122.868 47.310 -122.747 47.530 -122.582 47.794 -122.549 47.775 -122.681 47.451 -122.995 47.566 -123.005 47.794 -122.780 48.066 -122.813 48.140 -123.187 48.159 -123.626 48.214 -124.055 48.338 -124.555 48.099 -124.676 47.838 -124.505 47.571 -124.341 47.302 -124.236 46.973 -124.038 46.610 -123.940 46.390 -124.033 46.236 -123.495 46.192 -123.797 46.011 -123.934 45.723 -123.923 45.456 -123.918 45.151 -123.967 44.868 -124.027 44.558 -124.038 44.294 -124.093 44.003 -124.121 43.720 -124.148 43.407 -124.253 43.159 -124.401 42.868 -124.500 42.591 -124.407 42.302 -124.396 42.033 -124.247 41.755 -124.170 41.475 -124.060 41.179 -124.110 40.860 -124.137 40.668 -124.269 40.352 -124.335 40.113 -124.115 39.890 -123.885 39.613 -123.764 39.319 -123.769 39.030 -123.687 38.791 -123.527 38.566 -123.286 38.253 -122.951 38.066 -122.918 37.893 -122.615 38.030 -122.418 38.096 -122.027 38.077 -121.637 38.055 -121.676 38.055 -122.060 37.929 -122.319 37.602 -122.126 37.668 -122.368 37.423 -122.412 37.148 -122.313 36.975 -122.022 36.799 -121.786 36.549 -121.896 36.261 -121.786 36.041 -121.538 35.799 -121.346 35.596 -121.115 35.365 -120.868 35.137 -120.687 34.854 -120.621 34.563 -120.549 34.473 -120.231 34.434 -119.885 34.393 -119.544 34.206 -119.231 34.069 -118.967 34.038 -118.626 33.830 -118.396 33.739 -118.148 33.566 -117.830 33.385 -117.566 33.157 -117.357 32.879 -117.264 32.646 -117.176 32.341 -117.038 32.085 -116.863 31.819 -116.670 31.555 -116.626 31.319 -116.423 31.041 -116.302 30.816 -116.104 30.481 -116.000 30.305 -115.841 30.000 -115.775 29.742 -115.632 29.563 -115.379 29.418 -115.093 29.250 -114.819 29.027 -114.599 28.830 -114.379 28.624 -114.159 28.341 -114.126 28.044 -114.159 27.777 -114.143 27.769 -114.269 27.791 -114.533 27.827 -114.918 27.681 -114.901 27.497 -114.648 27.264 -114.451 27.126 -114.181 26.978 -113.901 26.799 -113.604 26.827 -113.242 26.618 -113.049 26.429 -112.786 26.297 -112.505 26.096 -112.308 25.709 -112.115 25.560 -112.071 25.280 -112.082 24.973 -112.126 24.791 -112.005 24.563 -111.747 24.360 -111.473 24.217 -111.242 24.055 -110.984 23.857 -110.758 23.673 -110.516 23.492 -110.286 23.236 -110.143 22.948 -110.033 22.962 -109.764 23.151 -109.516 23.420 -109.429 23.646 -109.615 23.898 -109.775 24.091 -109.940 24.228 -110.275 24.255 -110.538 24.478 -110.709 24.764 -110.692 25.025 -110.780 25.266 -110.940 25.527 -111.082 25.766 -111.275 26.038 -111.341 26.321 -111.418 26.577 -111.522 26.728 -111.764 26.849 -111.934 27.104 -112.055 27.321 -112.258 27.577 -112.434 27.761 -112.676 28.033 -112.764 28.321 -112.857 28.503 -113.066 28.780 -113.242 28.956 -113.473 29.220 -113.637 29.445 -113.841 29.640 -114.088 29.821 -114.341 30.047 -114.555 30.316 -114.643 30.604 -114.665 30.896 -114.731 31.146 -114.863 31.440 -114.857 31.821 -114.901 31.794 -114.714 31.648 -114.423 31.555 -114.055 31.563 -113.791 31.354 -113.571 31.245 -113.225 31.069 -113.071 30.788 -113.093 30.527 -112.956 30.275 -112.813 29.984 -112.725 29.731 -112.577 29.478 -112.407 29.266 -112.253 28.981 -112.121 28.758 -111.901 28.514 -111.709 28.332 -111.451 28.093 -111.258 27.923 -110.951 27.874 -110.659 27.651 -110.593 27.346 -110.495 27.159 -110.258 27.016 -109.945 26.750 -109.786 26.698 -109.489 26.431 -109.236 26.253 -109.214 25.967 -109.412 25.676 -109.313 25.676 -108.973 25.588 -108.984 25.500 -108.885 25.363 -108.659 25.115 -108.236 24.929 -108.104 24.780 -108.011 24.495 -107.698 24.379 -107.610 24.206 -107.357 24.025 -107.110 23.816 -106.896 23.580 -106.720 23.357 -106.511 23.135 -106.335 22.907 -106.088 22.720 -105.885 22.489 -105.720 22.206 -105.643 21.926 -105.599 21.668 -105.445 21.451 -105.236 21.137 -105.242 20.874 -105.440 20.662 -105.324 20.478 -105.544 20.277 -105.610 20.008 -105.500 19.764 -105.324 19.547 -105.121 19.319 -104.912 19.184 -104.670 19.074 -104.374 18.934 -104.115 18.783 -103.863 18.574 -103.654 18.343 -103.462 18.225 -103.181 18.129 -102.896 18.044 -102.610 17.970 -102.319 17.962 -102.022 17.832 -101.758 17.626 -101.544 17.467 -101.297 17.302 -101.049 17.176 -100.780 17.082 -100.495 16.975 -100.214 16.857 -99.918 16.714 -99.676 16.659 -99.374 16.602 -99.082 16.522 -98.791 16.335 -98.549 16.220 -98.198 16.102 -97.967 15.967 -97.725 15.934 -97.423 15.882 -97.132 15.750 -96.857 15.670 -96.560 15.687 -96.264 15.791 -95.989 15.898 -95.709 16.000 -95.423 16.159 -95.170 16.269 -94.907 16.283 -94.698 16.176 -94.451 16.058 -94.104 16.181 -94.286 16.173 -94.115 16.011 -93.879 15.821 -93.637 15.640 -93.407 15.453 -93.181 15.201 -92.863 15.058 -92.753 14.849 -92.549 14.643 -92.346 14.453 -92.121 14.272 -91.890 14.113 -91.643 13.986 -91.379 13.920 -91.093 13.926 -90.791 13.898 -90.500 13.794 -90.225 13.670 -89.956 13.530 -89.714 13.492 -89.407 13.404 -89.126 13.236 -88.659 13.242 -88.516 13.179 -88.313 13.176 -87.967 13.371 -87.764 13.346 -87.489 13.022 -87.346 12.995 -87.560 12.808 -87.533 12.632 -87.346 12.453 -87.137 12.272 -86.890 12.060 -86.703 11.824 -86.538 11.624 -86.330 11.442 -86.104 11.253 -85.885 10.962 -85.786 10.714 -85.692 10.497 -85.764 10.245 -85.835 9.975 -85.698 9.852 -85.451 9.665 -85.176 9.802 -84.951 10.107 -85.187 10.113 -85.033 9.953 -84.786 9.698 -84.648 9.525 -84.478 9.429 -84.192 9.291 -83.934 9.113 -83.709 8.841 -83.610 8.580 -83.670 8.415 -83.385 8.624 -83.385 8.615 -83.203 8.387 -83.104 8.137 -82.929 8.184 -82.852 8.302 -82.632 8.313 -82.363 8.225 -82.126 8.143 -81.791 7.942 -81.632 7.717 -81.484 7.769 -81.143 7.538 -80.962 7.264 -80.857 7.239 -80.555 7.382 -80.308 7.525 -80.055 7.794 -80.198 8.008 -80.401 8.255 -80.390 8.357 -80.110 8.552 -79.841 8.791 -79.720 8.945 -79.511 9.063 -79.115 8.948 -78.984 8.775 -78.714 8.503 -78.462 8.464 -78.214 8.242 -77.907 8.286 -78.165 8.036 -78.368 7.750 -78.291 7.516 -78.148 7.297 -77.956 7.091 -77.736 6.857 -77.637 6.643 -77.434 6.335 -77.401 6.088 -77.412 5.838 -77.280 5.577 -77.434 5.354 -77.385 5.058 -77.368 4.747 -77.308 4.478 -77.335 4.121 -77.346 3.934 -77.198 3.734 -77.148 3.475 -77.308 3.261 -77.462 2.973 -77.654 2.761 -77.747 2.582 -77.918 2.516 -78.187 2.442 -78.484 2.223 -78.648 1.898 -78.626 1.706 -78.951 1.401 -78.846 1.187 -78.995 1.088 -79.264 0.962 -79.593 0.912 -79.813 0.736 -80.055 0.409 -80.027 0.135 -80.060 -0.104 -80.220 -0.313 -80.429 -0.602 -80.401 -0.865 -80.593 -1.019 -80.857 -1.313 -80.791 -1.602 -80.824 -1.896 -80.753 -2.162 -80.890 -2.335 -80.846 -2.481 -80.599 -2.662 -80.324 -2.475 -80.027 -2.437 -79.879 -2.124 -79.857 -2.148 -79.835 -2.448 -79.791 -2.706 -79.786 -2.981 -79.879 -3.231 -80.022 -3.363 -80.280 -3.533 -80.511 -3.709 -80.747 -3.923 -80.934 -4.137 -81.126 -4.371 -81.291 -4.662 -81.319 -4.953 -81.154 -5.220 -81.159 -5.451 -80.962 -5.725 -80.885 -5.890 -81.110 -6.137 -81.038 -6.297 -80.791 -6.431 -80.533 -6.566 -80.275 -6.728 -80.033 -6.956 -79.857 -7.187 -79.687 -7.453 -79.571 -7.712 -79.440 -7.951 -79.280 -8.146 -79.071 -8.398 -78.923 -8.646 -78.775 -8.926 -78.687 -9.184 -78.566 -9.429 -78.429 -9.703 -78.313 -9.973 -78.220 -10.236 -78.115 -10.484 -77.967 -10.728 -77.808 -10.984 -77.676 -11.264 -77.610 -11.462 -77.379 -11.698 -77.209 -11.997 -77.143 -12.220 -76.989 -12.448 -76.797 -12.698 -76.654 -12.945 -76.511 -13.190 -76.363 -13.434 -76.209 -13.753 -76.258 -13.942 -76.324 -14.209 -76.203 -14.445 -76.033 -14.684 -75.874 -14.852 -75.626 -15.058 -75.423 -15.277 -75.220 -15.464 -75.022 -15.599 -74.758 -15.739 -74.495 -15.882 -74.242 -16.030 -73.995 -16.192 -73.742 -16.286 -73.456 -16.418 -73.198 -16.549 -72.918 -16.659 -72.643 -16.777 -72.368 -16.970 -72.148 -17.126 -71.896 -17.253 -71.615 -17.437 -71.407 -17.703 -71.302 -17.879 -71.044 -18.058 -70.808 -18.231 -70.566 -18.440 -70.346 -18.736 -70.341 -19.025 -70.302 -19.310 -70.264 -19.591 -70.192 -19.874 -70.143 -20.165 -70.143 -20.445 -70.181 -20.745 -70.192 -21.027 -70.143 -21.310 -70.077 -21.585 -70.110 -21.874 -70.165 -22.157 -70.214 -22.448 -70.253 -22.731 -70.291 -23.014 -70.407 -23.176 -70.571 -23.464 -70.538 -23.695 -70.440 -23.970 -70.505 -24.264 -70.527 -24.549 -70.566 -24.835 -70.538 -25.113 -70.467 -25.396 -70.500 -25.629 -70.659 -25.920 -70.676 -26.212 -70.659 -26.484 -70.692 -26.769 -70.775 -27.058 -70.857 -27.308 -70.940 -27.602 -70.951 -27.852 -71.099 -28.129 -71.154 -28.415 -71.209 -28.676 -71.330 -28.945 -71.489 -29.228 -71.434 -29.500 -71.319 -29.786 -71.313 -30.058 -71.385 -30.277 -71.582 -30.538 -71.698 -30.830 -71.687 -31.118 -71.654 -31.407 -71.604 -31.698 -71.544 -31.975 -71.516 -32.266 -71.489 -32.536 -71.445 -32.810 -71.522 -33.080 -71.676 -33.365 -71.687 -33.651 -71.670 -33.898 -71.857 -34.168 -71.989 -34.448 -72.033 -34.736 -72.099 -35.011 -72.203 -35.253 -72.385 -35.505 -72.560 -35.783 -72.626 -36.041 -72.791 -36.330 -72.852 -36.621 -73.022 -36.816 -73.154 -37.126 -73.214 -37.225 -73.555 -37.489 -73.637 -37.769 -73.615 -38.038 -73.478 -38.330 -73.516 -38.662 -73.467 -38.887 -73.368 -39.179 -73.247 -39.451 -73.253 -39.725 -73.374 -39.918 -73.549 -40.192 -73.714 -40.484 -73.775 -40.764 -73.890 -41.036 -73.967 -41.330 -73.879 -41.563 -73.692 -41.681 -73.632 -41.780 -73.308 -41.602 -73.060 -41.563 -72.780 -41.544 -72.396 -41.679 -72.434 -41.865 -72.791 -42.044 -72.549 -42.313 -72.451 -42.283 -72.637 -42.453 -72.676 -42.569 -72.758 -42.860 -72.808 -43.091 -72.852 -43.368 -73.066 -43.692 -72.934 -43.874 -73.044 -44.165 -73.170 -44.409 -72.769 -44.505 -72.643 -44.761 -72.797 -44.929 -73.137 -45.107 -73.374 -45.363 -73.093 -45.379 -73.330 -45.665 -73.429 -45.876 -73.571 -46.184 -73.654 -46.126 -73.495 -46.201 -73.500 -46.486 -73.802 -46.272 -73.918 -46.236 -74.302 -46.135 -74.148 -45.915 -74.143 -45.887 -74.500 -46.082 -74.764 -46.261 -75.033 -46.420 -75.324 -46.764 -75.538 -46.681 -75.484 -46.552 -75.088 -46.624 -75.016 -46.821 -74.637 -46.816 -74.286 -47.157 -74.066 -47.324 -74.385 -47.615 -74.231 -47.635 -74.505 -47.764 -74.505 -47.802 -74.110 -47.665 -73.758 -47.736 -73.665 -47.942 -73.429 -47.959 -73.478 -48.124 -73.445 -48.093 -73.758 -48.088 -74.181 -48.036 -74.440 -48.115 -74.484 -48.357 -74.115 -48.604 -74.192 -48.799 -74.341 -49.082 -74.418 -49.415 -74.335 -49.157 -74.038 -49.338 -74.016 -49.640 -73.830 -49.604 -73.962 -49.701 -74.225 -49.909 -74.077 -50.115 -74.104 -50.126 -74.467 -50.283 -74.473 -50.473 -74.132 -50.739 -74.093 -50.580 -73.687 -50.742 -73.720 -50.951 -74.060 -51.187 -73.868 -51.464 -73.731 -51.690 -73.687 -51.970 -73.484 -51.808 -73.335 -51.953 -73.258 -51.788 -73.110 -51.766 -72.786 -51.538 -73.022 -51.580 -72.786 -51.857 -72.533 -52.099 -72.582 -52.398 -72.654 -52.316 -72.654 -52.041 -72.692 -52.110 -72.857 -52.168 -73.060 -52.132 -73.555 -52.253 -73.621 -52.585 -73.593 -52.549 -73.192 -52.602 -73.137 -52.863 -73.352 -53.063 -73.203 -52.901 -72.962 -52.632 -72.830 -52.560 -72.445 -52.585 -71.764 -52.668 -72.066 -52.799 -72.571 -52.901 -72.907 -53.195 -72.912 -53.431 -72.632 -53.184 -72.407 -53.077 -72.198 -52.962 -71.797 -52.802 -71.368 -52.973 -71.220 -53.170 -71.560 -53.456 -71.841 -53.385 -71.830 -53.327 -72.093 -53.415 -72.390 -53.668 -72.077 -53.794 -71.681 -53.843 -71.187 -53.607 -70.956 -53.319 -70.967 -53.025 -70.852 -52.739 -70.709 -52.640 -70.297 -52.519 -69.857 -52.374 -69.516 -52.234 -69.170 -52.302 -68.566 -52.038 -68.665 -51.777 -68.874 -51.621 -69.313 -51.577 -69.165 -51.407 -69.016 -51.077 -69.209 -50.942 -69.231 -50.662 -69.121 -50.401 -68.940 -50.195 -68.527 -50.003 -68.764 -49.887 -68.698 -49.865 -68.588 -50.085 -68.297 -49.970 -67.885 -49.706 -67.731 -49.365 -67.698 -49.146 -67.632 -48.904 -67.396 -48.687 -67.115 -48.516 -66.769 -48.343 -66.407 -48.140 -66.066 -47.887 -66.049 -47.747 -65.951 -47.500 -65.758 -47.212 -65.797 -47.082 -66.126 -47.052 -66.549 -46.909 -66.901 -46.703 -67.187 -46.492 -67.473 -46.217 -67.599 -45.945 -67.527 -45.695 -67.335 -45.445 -67.121 -45.236 -66.852 -45.124 -66.500 -44.989 -66.104 -44.995 -65.698 -44.761 -65.654 -44.508 -65.379 -44.242 -65.275 -43.964 -65.253 -43.676 -65.302 -43.423 -65.099 -43.201 -64.857 -43.049 -64.445 -42.937 -64.555 -42.734 -64.896 -42.527 -64.571 -42.648 -64.258 -42.857 -64.049 -42.761 -63.670 -42.478 -63.588 -42.192 -63.681 -42.212 -64.110 -42.412 -64.187 -42.343 -64.538 -42.184 -64.846 -41.953 -65.049 -41.668 -65.011 -41.390 -65.071 -41.107 -65.159 -40.805 -65.033 -40.791 -64.813 -40.909 -64.451 -41.025 -64.093 -41.151 -63.758 -41.157 -63.368 -41.124 -62.995 -41.003 -62.648 -40.758 -62.297 -40.547 -62.335 -40.247 -62.418 -39.959 -62.330 -39.772 -62.148 -39.398 -62.132 -39.223 -62.286 -38.893 -62.302 -38.940 -61.989 -38.997 -61.610 -38.992 -61.236 -38.973 -60.874 -38.929 -60.500 -38.876 -60.137 -38.824 -59.769 -38.750 -59.412 -38.684 -59.049 -38.588 -58.703 -38.495 -58.352 -38.371 -58.022 -38.223 -57.714 -37.992 -57.527 -37.731 -57.385 -37.514 -57.143 -37.264 -56.956 -37.019 -56.764 -36.750 -56.670 -36.420 -56.720 -36.327 -56.989 -36.129 -57.269 -35.854 -57.374 -35.591 -57.231 -35.338 -57.187 -35.113 -57.412 -34.942 -57.692 -34.802 -58.000 -34.657 -58.308 -34.423 -58.495 -34.203 -58.434 -33.923 -58.456 -33.643 -58.538 -33.354 -58.467 -33.107 -58.324 -32.904 -58.159 -32.591 -58.209 -32.624 -58.154 -32.907 -58.082 -33.126 -58.258 -33.376 -58.385 -33.657 -58.434 -33.937 -58.368 -34.162 -58.148 -34.382 -57.912 -34.462 -57.643 -34.448 -57.297 -34.566 -57.000 -34.720 -56.714 -34.835 -56.390 -34.890 -56.077 -34.791 -55.720 -34.838 -55.363 -34.923 -55.022 -34.868 -54.698 -34.668 -54.324 -34.596 -54.093 -34.390 -53.824 -34.146 -53.637 -33.893 -53.489 -33.673 -53.275 -33.478 -53.022 -33.275 -52.775 -33.036 -52.588 -32.766 -52.462 -32.492 -52.363 -32.187 -52.165 -31.986 -52.187 -31.654 -52.093 -31.420 -51.967 -31.245 -51.714 -31.033 -51.495 -30.747 -51.330 -30.473 -51.225 -30.203 -51.242 -30.239 -51.121 -30.343 -50.725 -30.549 -50.687 -30.813 -50.786 -31.041 -51.005 -31.247 -51.165 -31.492 -51.330 -31.654 -51.538 -31.945 -51.967 -31.887 -51.780 -31.734 -51.495 -31.544 -51.236 -31.338 -51.000 -31.118 -50.786 -30.876 -50.599 -30.632 -50.429 -30.376 -50.269 -30.104 -50.165 -29.832 -50.038 -29.574 -49.890 -29.332 -49.714 -29.099 -49.516 -28.893 -49.291 -28.714 -49.038 -28.467 -48.813 -28.250 -48.665 -27.959 -48.599 -27.676 -48.610 -27.390 -48.599 -27.135 -48.555 -26.808 -48.626 -26.525 -48.648 -26.212 -48.720 -25.890 -48.626 -25.668 -48.451 -25.492 -48.615 -25.382 -48.489 -25.332 -48.253 -25.148 -47.978 -24.986 -47.923 -24.775 -47.648 -24.643 -47.374 -24.467 -47.099 -24.264 -46.901 -24.110 -46.626 -23.951 -46.297 -23.835 -46.071 -23.777 -45.764 -23.755 -45.451 -23.549 -45.209 -23.412 -44.967 -23.343 -44.643 -23.217 -44.643 -23.014 -44.522 -22.997 -44.264 -23.003 -43.863 -23.049 -43.615 -22.997 -43.280 -22.783 -43.187 -22.865 -43.066 -22.970 -42.808 -22.942 -42.500 -22.951 -42.121 -22.766 -41.951 -22.492 -41.901 -22.294 -41.670 -22.184 -41.379 -22.069 -41.093 -21.843 -40.995 -21.552 -41.033 -21.272 -40.956 -21.008 -40.824 -20.802 -40.637 -20.596 -40.423 -20.305 -40.302 -20.055 -40.159 -19.808 -40.033 -19.607 -39.813 -19.335 -39.703 -19.047 -39.725 -18.755 -39.742 -18.473 -39.709 -18.195 -39.615 -17.959 -39.434 -17.761 -39.203 -17.481 -39.192 -17.190 -39.198 -16.909 -39.143 -16.624 -39.088 -16.341 -39.016 -16.066 -38.934 -15.780 -38.896 -15.495 -38.962 -15.206 -39.000 -14.901 -39.022 -14.632 -39.049 -14.341 -39.000 -14.041 -38.989 -13.786 -39.044 -13.533 -39.055 -13.261 -38.929 -12.852 -38.835 -12.690 -38.692 -12.907 -38.489 -12.868 -38.258 -12.648 -38.066 -12.409 -37.907 -12.173 -37.736 -11.920 -37.593 -11.580 -37.445 -11.332 -37.363 -11.115 -37.192 -10.934 -37.016 -10.720 -36.824 -10.563 -36.571 -10.404 -36.341 -10.176 -36.165 -9.964 -35.973 -9.687 -35.830 -9.522 -35.588 -9.305 -35.401 -9.066 -35.231 -8.805 -35.115 -8.536 -35.011 -8.261 -34.929 -7.989 -34.857 -7.668 -34.863 -7.453 -34.824 -7.096 -34.852 -6.868 -34.901 -6.582 -34.962 -6.266 -35.066 -6.030 -35.115 -5.750 -35.187 -5.475 -35.280 -5.225 -35.429 -5.102 -35.687 -5.066 -35.978 -5.099 -36.269 -5.096 -36.560 -5.011 -36.824 -4.920 -37.099 -4.734 -37.313 -4.613 -37.571 -4.423 -37.791 -4.242 -38.016 -4.025 -38.214 -3.797 -38.423 -3.665 -38.654 -3.495 -38.890 -3.335 -39.126 -3.192 -39.379 -3.052 -39.648 -2.912 -39.890 -2.832 -40.154 -2.808 -40.451 -2.852 -40.742 -2.885 -41.033 -2.937 -41.302 -2.885 -41.599 -2.772 -41.896 -2.808 -42.170 -2.728 -42.451 -2.596 -42.698 -2.478 -42.956 -2.390 -43.242 -2.481 -43.505 -2.547 -43.775 -2.755 -44.165 -2.514 -44.077 -2.505 -44.264 -2.690 -44.374 -2.973 -44.467 -3.206 -44.698 -3.137 -44.703 -2.868 -44.665 -2.582 -44.588 -2.316 -44.451 -2.319 -44.676 -2.209 -44.659 -1.948 -44.549 -1.731 -44.747 -1.538 -44.956 -1.602 -45.275 -1.404 -45.445 -1.269 -45.692 -1.203 -45.907 -1.085 -46.154 -1.044 -46.379 -0.923 -46.670 -0.802 -46.923 -0.692 -47.192 -0.687 -47.451 -0.695 -47.758 -0.750 -48.055 -1.038 -48.225 -1.247 -48.346 -1.514 -48.440 -1.519 -48.643 -1.703 -48.879 -1.871 -49.099 -2.077 -49.286 -2.343 -49.401 -2.615 -49.560 -2.530 -49.577 -2.250 -49.484 -1.904 -49.500 -1.967 -49.824 -1.857 -50.071 -1.984 -50.374 -1.841 -50.615 -1.607 -50.714 -1.343 -50.819 -1.080 -50.868 -0.964 -50.973 -1.157 -51.203 -1.299 -51.429 -1.440 -51.709 -1.585 -51.962 -1.615 -52.242 -1.577 -52.582 -1.500 -52.527 -1.382 -52.258 -1.332 -51.978 -1.093 -51.802 -0.838 -51.709 -0.577 -51.560 -0.371 -51.396 -0.107 -51.258 0.060 -51.016 0.214 -50.775 0.429 -50.577 0.673 -50.418 0.885 -50.220 1.071 -50.005 1.310 -49.896 1.593 -49.934 1.766 -50.154 1.838 -50.440 2.096 -50.687 2.343 -50.725 2.593 -50.824 2.876 -50.923 3.157 -51.022 3.442 -51.066 3.769 -51.126 4.011 -51.187 4.283 -51.445 4.063 -51.478 4.102 -51.571 4.294 -51.687 4.492 -51.901 4.703 -52.055 4.854 -52.302 5.055 -52.511 5.247 -52.736 5.440 -52.956 5.516 -53.236 5.596 -53.516 5.731 -53.786 5.514 -54.055 5.657 -54.033 5.854 -54.148 5.915 -54.434 5.967 -54.720 5.986 -55.033 5.885 -55.000 5.857 -55.038 5.929 -55.286 5.973 -55.577 5.830 -55.874 5.832 -56.088 5.915 -56.368 5.956 -56.654 5.973 -56.956 5.643 -57.165 5.780 -57.165 6.060 -57.170 6.286 -57.396 6.404 -57.588 6.604 -57.797 6.791 -58.033 6.865 -58.319 6.549 -58.582 6.725 -58.604 7.000 -58.511 7.288 -58.478 7.555 -58.648 7.745 -58.830 7.945 -59.038 8.118 -59.264 8.266 -59.588 8.354 -59.797 8.541 -60.022 8.618 -60.313 8.558 -60.582 8.571 -60.890 8.462 -61.110 8.533 -61.500 8.599 -61.324 8.775 -61.154 9.085 -61.038 9.277 -60.857 9.500 -60.940 9.593 -61.203 9.808 -61.516 9.736 -61.769 9.865 -62.121 9.854 -62.297 10.107 -62.484 10.074 -62.824 10.157 -62.687 10.401 -62.907 10.552 -62.769 10.544 -62.473 10.668 -62.044 10.701 -62.247 10.734 -62.544 10.723 -62.835 10.709 -63.137 10.665 -63.418 10.659 -63.736 10.610 -64.143 10.522 -63.868 10.456 -64.038 10.363 -64.352 10.236 -64.571 10.126 -64.791 10.071 -65.110 10.137 -65.390 10.242 -65.742 10.319 -65.923 10.547 -66.110 10.626 -66.368 10.624 -66.670 10.604 -66.962 10.552 -67.253 10.522 -67.544 10.478 -67.846 10.514 -68.137 10.758 -68.297 10.967 -68.319 11.223 -68.484 11.382 -68.747 11.459 -69.033 11.508 -69.319 11.511 -69.621 11.750 -69.786 12.033 -69.852 12.154 -70.071 11.951 -70.258 11.690 -70.192 11.593 -69.841 11.492 -70.049 11.365 -70.247 11.264 -70.522 11.206 -70.819 11.082 -71.082 10.948 -71.396 10.725 -71.522 10.437 -71.467 10.190 -71.313 9.942 -71.148 9.679 -71.060 9.374 -71.093 9.148 -71.280 9.055 -71.555 9.220 -71.753 9.431 -71.874 9.582 -71.995 9.879 -72.071 10.135 -71.918 10.365 -71.736 10.607 -71.604 10.931 -71.692 11.115 -71.764 11.354 -71.923 11.607 -71.885 11.698 -71.582 11.830 -71.341 12.069 -71.154 12.332 -71.291 12.426 -71.643 12.280 -71.885 12.192 -72.115 11.920 -72.253 11.777 -72.505 11.668 -72.780 11.500 -73.022 11.330 -73.258 11.272 -73.544 11.288 -73.841 11.316 -74.126 11.060 -74.247 10.802 -74.478 10.934 -74.451 10.995 -74.467 11.085 -74.764 10.978 -74.995 10.775 -75.231 10.555 -75.473 10.277 -75.588 10.058 -75.582 9.750 -75.648 9.456 -75.709 9.396 -75.956 9.212 -76.159 8.964 -76.324 8.786 -76.555 8.585 -76.841 8.313 -76.769 8.008 -76.764 8.080 -76.890 8.294 -77.038 8.508 -77.253 8.698 -77.467 8.876 -77.681 9.093 -77.879 9.253 -78.126 9.357 -78.401 9.426 -78.676 9.475 -78.989 9.544 -79.236 9.580 -79.549 9.407 -79.797 9.288 -80.011 9.157 -80.291 9.069 -80.571 8.915 -80.819 8.808 -81.088 8.786 -81.379 9.036 -81.780 8.945 -81.929 9.066 -82.203 9.258 -82.313 9.500 -82.478 9.662 -82.731 9.852 -82.934 10.052 -83.121 10.280 -83.319 10.522 -83.478 10.780 -83.599 11.000 -83.747 11.283 -83.857 11.536 -83.736 11.799 -83.731 12.060 -83.731 12.305 -83.676 12.651 -83.643 12.508 -83.604 12.492 -83.516 12.813 -83.516 13.096 -83.544 13.385 -83.555 13.668 -83.500 13.945 -83.423 14.187 -83.258 14.453 -83.214 14.747 -83.335 14.879 -83.275 15.074 -83.258 15.269 -83.560 15.299 -83.852 15.451 -84.005 15.640 -84.055 15.830 -84.407 15.827 -84.588 15.959 -84.879 15.923 -85.165 15.901 -85.462 15.975 -85.736 15.956 -85.989 15.810 -86.302 15.794 -86.593 15.772 -86.890 15.810 -87.192 15.849 -87.522 15.887 -87.813 15.745 -88.060 15.786 -88.319 15.832 -88.582 15.956 -88.857 16.234 -88.659 16.500 -88.401 16.643 -88.319 16.918 -88.247 17.198 -88.286 17.500 -88.242 17.772 -88.220 18.044 -88.121 18.321 -88.170 18.420 -88.319 18.734 -88.148 18.593 -88.038 18.321 -87.896 18.368 -87.791 18.648 -87.714 18.934 -87.621 19.255 -87.577 19.541 -87.555 19.824 -87.516 19.981 -87.456 20.258 -87.396 20.495 -87.220 20.701 -87.000 20.948 -86.841 21.209 -86.797 21.467 -86.907 21.541 -87.236 21.473 -87.451 21.527 -87.742 21.591 -88.110 21.563 -88.363 21.486 -88.659 21.396 -88.945 21.346 -89.253 21.310 -89.560 21.253 -89.863 21.132 -90.143 20.901 -90.374 20.668 -90.456 20.379 -90.484 20.085 -90.484 19.843 -90.588 19.591 -90.709 19.313 -90.786 19.115 -91.016 18.904 -91.346 18.698 -91.297 18.489 -91.484 18.486 -91.835 18.621 -91.973 18.684 -92.286 18.566 -92.632 18.492 -92.846 18.409 -93.137 18.385 -93.626 18.302 -93.758 18.247 -94.022 18.170 -94.313 18.225 -94.588 18.464 -94.780 18.602 -95.044 18.706 -95.313 18.725 -95.643 18.810 -95.857 19.091 -96.044 19.305 -96.242 19.563 -96.357 19.849 -96.456 20.085 -96.632 20.305 -96.830 20.522 -97.033 20.764 -97.192 21.027 -97.319 21.294 -97.440 21.536 -97.577 21.920 -97.725 21.830 -97.626 21.464 -97.418 21.635 -97.401 21.852 -97.615 22.110 -97.753 22.396 -97.819 22.668 -97.846 22.937 -97.753 23.258 -97.764 23.624 -97.742 23.821 -97.747 24.126 -97.709 24.418 -97.670 24.701 -97.604 24.981 -97.527 25.250 -97.407 25.508 -97.258 25.786 -97.165 26.044 -97.214 26.316 -97.363 26.563 -97.445 26.865 -97.527 27.121 -97.473 27.319 -97.676 27.338 -97.544 27.495 -97.346 27.777 -97.385 27.857 -97.297 28.055 -97.110 28.187 -96.929 28.404 -96.659 28.635 -96.500 28.613 -96.176 28.643 -95.901 28.739 -95.720 28.865 -95.423 29.091 -95.176 29.332 -94.934 29.582 -94.995 29.723 -94.863 29.580 -94.665 29.464 -94.665 29.442 -94.643 29.571 -94.341 29.673 -94.000 29.871 -93.901 29.805 -93.791 29.775 -93.418 29.750 -93.093 29.640 -92.786 29.563 -92.467 29.657 -92.137 29.783 -91.901 29.662 -91.621 29.541 -91.346 29.363 -91.214 29.223 -91.132 29.148 -90.830 29.261 -90.538 29.190 -90.236 29.423 -90.093 29.407 -89.824 29.264 -89.560 29.063 -89.308 29.168 -89.082 29.363 -89.324 29.508 -89.621 29.703 -89.560 29.918 -89.390 29.995 -89.516 30.055 -89.736 30.082 -89.967 30.102 -90.335 30.338 -90.236 30.275 -89.923 30.181 -89.610 30.310 -89.319 30.398 -88.962 30.368 -88.676 30.365 -88.341 30.555 -88.038 30.324 -87.879 30.236 -87.797 30.349 -87.467 30.448 -87.209 30.464 -87.038 30.418 -86.714 30.434 -86.324 30.302 -86.088 30.176 -85.648 30.005 -85.527 29.766 -85.346 29.742 -84.967 29.819 -84.692 29.967 -84.396 30.088 -84.132 29.984 -83.808 29.783 -83.571 29.558 -83.379 29.332 -83.159 29.159 -82.896 28.948 -82.703 28.703 -82.648 28.382 -82.698 28.115 -82.780 27.827 -82.802 27.852 -82.676 27.854 -82.478 27.533 -82.626 27.321 -82.560 27.038 -82.429 26.909 -82.165 26.646 -81.956 26.462 -81.912 26.162 -81.802 25.937 -81.654 25.780 -81.357 25.533 -81.203 25.261 -81.066 25.148 -80.874 25.203 -80.527 25.346 -80.363 25.626 -80.286 25.863 -80.137 26.162 -80.099 26.464 -80.055 26.745 -80.038 27.014 -80.104 27.247 -80.247 27.560 -80.352 27.830 -80.467 28.091 -80.599 28.360 -80.725 28.654 -80.813 28.654 -80.725 28.431 -80.604 28.154 -80.577 28.033 -80.538 28.445 -80.571 28.709 -80.670 28.967 -80.846 29.217 -80.995 29.484 -81.121 29.758 -81.236 30.030 -81.319 30.316 -81.390 30.593 -81.462 30.945 -81.489 31.148 -81.401 31.415 -81.313 31.665 -81.192 31.887 -81.016 32.137 -80.797 32.393 -80.797 32.382 -80.692 32.429 -80.533 32.541 -80.280 32.728 -79.945 32.863 -79.676 33.044 -79.429 33.272 -79.231 33.505 -79.055 33.725 -78.824 33.882 -78.516 33.907 -78.181 34.044 -77.929 34.275 -77.764 34.500 -77.478 34.657 -77.319 34.714 -76.989 34.876 -76.505 35.014 -76.868 35.033 -76.698 35.242 -76.577 35.442 -76.918 35.462 -76.879 35.442 -76.511 35.382 -76.159 35.569 -75.874 35.824 -75.769 35.788 -75.989 35.863 -76.060 35.959 -76.297 36.052 -76.571 36.107 -76.687 36.173 -76.253 36.201 -75.934 36.327 -75.901 36.549 -75.973 36.547 -75.879 36.269 -75.791 35.942 -75.637 36.011 -75.643 36.277 -75.775 36.558 -75.863 36.846 -75.989 36.904 -76.363 37.085 -76.637 37.275 -77.060 37.264 -76.890 37.093 -76.440 37.363 -76.615 37.341 -76.423 37.495 -76.302 37.679 -76.549 38.033 -76.934 37.907 -76.764 37.692 -76.451 37.860 -76.297 38.077 -76.566 38.231 -76.918 38.387 -77.225 38.725 -77.115 38.500 -77.143 38.321 -76.857 38.148 -76.451 38.434 -76.538 38.602 -76.505 38.931 -76.505 39.140 -76.489 39.330 -76.357 39.508 -75.984 39.387 -75.978 39.126 -76.176 38.860 -76.247 38.679 -76.132 38.514 -76.214 38.316 -76.005 38.181 -75.857 37.951 -75.758 37.695 -75.830 37.310 -75.940 37.459 -75.758 37.651 -75.571 37.920 -75.429 38.181 -75.247 38.437 -75.082 38.679 -75.121 38.975 -75.313 39.253 -75.423 39.530 -75.566 39.761 -75.418 39.876 -75.236 39.503 -75.505 39.272 -75.242 39.063 -74.890 39.272 -74.588 39.470 -74.390 39.854 -74.121 39.953 -74.044 40.234 -73.984 40.448 -74.104 40.679 -74.121 41.096 -73.929 40.854 -73.940 40.868 -73.802 41.044 -73.516 41.170 -73.154 41.266 -72.819 41.297 -72.396 41.324 -72.033 41.357 -71.632 41.659 -71.379 41.604 -71.110 41.640 -70.703 41.621 -70.335 41.799 -70.082 41.907 -70.049 41.772 -70.412 42.027 -70.637 42.313 -70.923 42.585 -70.742 42.799 -70.802 43.099 -70.681 43.371 -70.456 43.604 -70.258 43.810 -69.951 43.901 -69.813 43.920 -69.654 44.000 -69.297 44.173 -69.049 44.462 -68.879 44.382 -68.698 44.451 -68.418 44.459 -68.049 44.563 -67.731 44.662 -67.374 44.863 -67.082 45.115 -67.126 45.140 -66.989 45.096 -66.621 45.269 -66.165 45.247 -65.912 45.352 -65.527 45.503 -65.176 45.646 -64.802 45.940 -64.665 45.843 -64.500 45.764 -64.357 45.431 -64.780 45.390 -64.489 45.393 -64.077 45.368 -63.582 45.308 -63.692 45.121 -64.110 45.223 -64.363 45.184 -64.703 45.041 -65.060 44.786 -65.533 44.665 -65.692 44.505 -66.022 44.250 -66.143 43.978 -66.170 43.766 -65.989 43.563 -65.681 43.648 -65.335 43.777 -65.005 43.975 -64.731 44.214 -64.456 44.382 -64.291 44.574 -64.082 44.508 -63.802 44.615 -63.511 44.720 -63.110 44.786 -62.692 44.898 -62.368 45.025 -61.956 45.129 -61.626 45.247 -61.148 45.404 -61.308 45.635 -61.538 45.753 -61.879 45.783 -62.110 45.657 -62.484 45.717 -62.764 45.788 -63.291 45.863 -63.659 46.058 -63.929 46.198 -64.198 46.327 -64.588 46.632 -64.753 46.879 -64.863 47.102 -65.110 47.407 -64.923 47.701 -64.786 47.813 -65.038 47.695 -65.495 47.810 -65.736 47.953 -66.088 48.022 -66.588 48.077 -66.500 48.137 -66.088 48.102 -65.714 48.027 -65.302 48.170 -64.901 48.357 -64.588 48.549 -64.247 48.824 -64.352 49.063 -64.505 49.195 -64.901 49.247 -65.335 49.236 -65.775 49.198 -66.214 49.110 -66.626 48.986 -67.027 48.876 -67.440 48.750 -67.830 48.618 -68.220 48.453 -68.577 48.294 -68.934 48.085 -69.247 47.876 -69.538 47.640 -69.786 47.420 -70.055 47.190 -70.308 46.986 -70.610 46.830 -71.104 46.956 -71.038 47.137 -70.714 47.396 -70.473 47.591 -70.170 47.824 -69.907 48.104 -69.819 48.269 -70.181 48.393 -70.797 48.385 -70.577 48.297 -70.159 48.192 -69.736 48.371 -69.385 48.618 -69.159 48.841 -68.896 49.063 -68.500 49.184 -68.198 49.297 -67.797 49.376 -67.368 49.646 -67.203 49.887 -67.022 50.121 -66.621 50.220 -66.319 50.258 -65.907 50.297 -65.418 50.283 -64.967 50.294 -64.516 50.288 -64.066 50.269 -63.615 50.266 -63.181 50.288 -62.742 50.261 -62.319 50.165 -61.769 50.157 -61.473 50.217 -60.989 50.231 -60.571 50.253 -60.154 50.390 -59.797 50.607 -59.451 50.802 -59.093 51.030 -58.879 51.245 -58.549 51.319 -58.115 51.442 -57.648 51.453 -57.209 51.516 -56.824 51.714 -56.462 51.865 -56.082 52.121 -55.769 52.385 -55.863 52.552 -56.258 52.615 -56.005 52.854 -55.978 53.069 -55.951 53.308 -55.874 53.552 -56.159 53.706 -56.599 53.585 -57.258 53.810 -57.170 54.060 -57.324 54.190 -57.676 54.206 -58.209 54.104 -58.055 54.069 -58.165 53.981 -58.643 53.791 -59.005 53.640 -59.335 53.495 -59.808 53.305 -60.170 53.382 -60.231 53.695 -60.626 53.651 -60.176 53.813 -59.797 53.885 -59.319 54.085 -58.703 54.049 -59.242 54.121 -58.962 54.209 -58.500 54.338 -58.110 54.497 -57.527 54.695 -57.835 54.769 -58.319 54.860 -58.797 55.099 -59.159 54.904 -59.692 55.066 -59.560 55.198 -59.791 55.162 -60.335 55.440 -60.363 55.698 -60.538 55.830 -60.956 56.041 -61.357 56.264 -61.764 56.519 -61.951 56.780 -62.313 56.714 -62.203 56.720 -61.791 57.005 -61.434 57.228 -61.791 57.451 -62.253 57.596 -62.038 57.890 -62.192 58.036 -62.473 58.077 -62.984 58.168 -62.846 58.365 -62.742 58.401 -63.275 58.473 -63.368 58.745 -62.984 58.970 -63.236 59.030 -63.670 59.170 -63.648 59.385 -63.841 59.599 -63.984 59.912 -64.220 60.005 -64.478 60.082 -64.571 60.269 -64.610 60.107 -65.011 59.843 -65.203 59.511 -65.291 59.332 -65.516 59.115 -65.582 59.011 -65.632 58.860 -65.945 58.500 -65.967 58.599 -66.016 58.750 -66.423 58.489 -66.802 58.335 -67.247 58.071 -67.648 58.242 -67.835 58.459 -67.951 58.382 -68.192 58.107 -68.363 57.887 -69.060 57.981 -68.824 58.135 -68.385 58.445 -68.236 58.701 -68.357 58.885 -68.764 58.860 -69.302 58.712 -69.896 58.901 -69.797 59.019 -69.462 59.280 -69.462 59.558 -69.643 59.838 -69.648 59.962 -70.077 60.016 -70.742 60.016 -70.632 60.008 -70.082 60.121 -69.687 60.434 -69.753 60.703 -69.593 60.962 -69.445 60.898 -69.846 61.041 -70.330 61.088 -70.907 61.192 -71.489 61.442 -71.736 61.635 -71.984 61.841 -72.374 61.981 -72.687 62.195 -73.038 62.398 -73.522 62.374 -74.049 62.195 -74.643 62.277 -75.187 62.255 -75.769 62.420 -76.385 62.525 -76.967 62.533 -77.549 62.332 -78.055 62.047 -78.126 61.755 -77.956 61.519 -77.643 61.220 -77.747 60.967 -77.995 60.777 -77.813 60.505 -77.626 60.192 -77.544 59.981 -77.341 59.673 -77.527 59.445 -77.797 59.228 -77.995 58.986 -78.352 58.742 -78.522 58.555 -78.330 58.357 -77.896 58.173 -77.451 57.956 -77.093 57.701 -76.852 57.426 -76.681 57.143 -76.560 56.852 -76.522 56.563 -76.522 56.277 -76.566 56.005 -76.742 55.745 -77.077 55.536 -77.335 55.330 -77.709 55.151 -78.104 54.995 -78.522 54.865 -78.973 54.706 -79.566 54.511 -79.538 54.220 -79.286 54.014 -79.099 53.734 -79.027 53.478 -79.005 53.148 -78.934 52.879 -78.802 52.599 -78.703 52.316 -78.505 52.063 -78.654 51.830 -78.923 51.398 -78.868 51.527 -79.159 51.560 -79.467 51.313 -79.692 50.907 -79.484 51.038 -79.648 51.234 -79.984 51.297 -80.429 51.091 -80.852 51.146 -80.835 51.376 -80.505 51.659 -80.588 51.890 -80.857 52.063 -81.198 52.217 -81.681 52.357 -81.615 52.646 -81.846 52.882 -82.132 53.140 -82.253 53.404 -82.154 53.687 -82.176 53.973 -82.203 54.223 -82.401 54.522 -82.352 54.813 -82.236 55.099 -82.363 55.170 -82.874 55.225 -83.473 55.250 -83.736 55.283 -84.242 55.261 -84.747 55.137 -85.286 55.275 -85.236 55.508 -85.522 55.673 -85.929 55.777 -86.407 55.898 -86.885 55.997 -87.423 56.179 -87.703 56.423 -88.005 56.599 -88.429 56.799 -88.835 56.898 -89.313 56.981 -89.824 57.129 -90.297 57.239 -90.775 57.212 -91.291 57.102 -91.780 56.992 -92.478 57.245 -92.456 57.522 -92.516 57.797 -92.714 58.077 -92.835 58.346 -93.011 58.668 -93.203 58.764 -93.698 58.670 -94.170 58.354 -94.280 58.371 -94.319 58.665 -94.253 58.805 -94.489 59.036 -94.813 59.316 -94.736 59.599 -94.786 59.901 -94.791 60.176 -94.703 60.486 -94.648 60.742 -94.412 61.022 -94.137 61.291 -93.984 61.549 -93.813 61.799 -93.440 61.989 -93.253 62.220 -92.989 62.247 -92.725 62.456 -92.632 62.569 -92.203 62.706 -92.253 62.835 -92.121 62.819 -91.445 62.962 -90.863 63.192 -90.692 63.415 -90.923 63.563 -91.484 63.629 -92.209 63.797 -92.615 63.879 -93.319 64.036 -93.665 64.049 -93.456 63.896 -92.868 63.783 -92.165 63.720 -91.593 63.602 -91.033 63.640 -90.451 63.896 -90.055 64.110 -89.918 64.044 -89.423 64.005 -88.874 64.104 -88.297 64.316 -87.940 64.582 -87.626 64.805 -87.319 65.099 -87.016 65.272 -87.440 65.275 -88.093 65.316 -88.797 65.486 -89.313 65.709 -89.747 65.849 -90.357 65.885 -91.137 65.937 -91.027 65.885 -90.143 65.901 -89.615 65.690 -88.824 65.555 -88.516 65.363 -88.000 65.371 -87.275 65.580 -86.819 65.824 -86.429 66.077 -86.033 66.423 -86.527 66.530 -85.802 66.387 -85.291 66.272 -84.626 66.239 -84.044 66.310 -83.808 66.602 -84.148 66.912 -84.747 66.819 -84.231 66.684 -83.934 66.423 -83.588 66.492 -83.044 66.654 -82.445 66.874 -82.060 67.052 -81.533 67.360 -81.308 67.618 -81.489 67.846 -81.951 68.135 -82.143 68.382 -82.484 68.481 -82.165 68.580 -81.489 68.865 -81.626 69.104 -81.462 69.305 -82.132 69.500 -82.879 69.571 -82.610 69.673 -82.698 69.701 -83.522 69.824 -84.297 69.813 -85.247 69.607 -85.478 69.352 -85.429 69.071 -84.934 68.819 -85.093 68.654 -85.659 68.352 -85.769 68.058 -85.978 67.819 -86.346 67.464 -86.549 67.236 -87.203 67.423 -87.626 67.662 -88.077 67.937 -88.335 68.247 -88.181 68.429 -87.841 68.723 -87.973 68.967 -88.374 69.195 -89.055 69.036 -89.632 68.717 -89.758 68.387 -90.137 68.544 -90.527 68.832 -90.511 69.234 -91.011 69.412 -90.599 69.555 -91.137 69.571 -91.698 69.668 -92.511 69.852 -92.390 70.176 -92.044 70.407 -92.099 70.648 -92.440 70.890 -92.912 71.214 -92.912 71.467 -93.280 71.714 -94.011 71.849 -94.500 71.879 -94.984 71.604 -95.626 71.371 -95.720 71.192 -96.423 70.937 -96.527 70.632 -96.110 70.390 -96.440 70.113 -96.478 69.841 -95.995 69.679 -95.352 69.591 -94.648 69.473 -93.802 69.310 -93.571 69.305 -93.753 69.363 -93.945 69.137 -94.214 68.860 -94.527 68.901 -93.901 68.643 -93.604 68.434 -94.011 68.198 -94.440 68.058 -95.143 67.871 -95.549 67.613 -95.478 67.330 -95.297 67.027 -95.297 66.920 -95.725 66.723 -95.802 66.945 -96.115 67.052 -95.473 67.275 -95.824 67.519 -96.286 67.769 -96.192 68.151 -96.038 68.091 -96.516 68.223 -96.698 68.451 -97.560 68.357 -98.165 68.239 -98.505 67.942 -98.209 67.942 -97.544 67.690 -97.253 67.720 -97.929 67.992 -98.451 67.846 -98.593 67.745 -99.203 67.819 -99.934 67.805 -100.769 67.723 -101.456 67.750 -102.192 67.879 -102.918 68.069 -103.516 68.063 -104.385 68.275 -104.907 68.467 -105.412 68.750 -105.582 68.896 -106.198 68.780 -106.929 68.665 -107.665 68.549 -108.374 68.234 -108.495 68.234 -107.802 68.332 -107.099 68.481 -106.198 68.305 -106.324 68.162 -106.775 68.027 -107.692 67.764 -107.923 67.464 -107.665 67.170 -107.407 66.926 -107.484 66.544 -107.478 66.654 -107.758 66.984 -108.302 67.137 -107.984 67.459 -108.533 67.484 -108.945 67.720 -109.407 67.896 -109.973 67.896 -110.571 67.775 -111.291 67.723 -112.033 67.673 -112.791 67.698 -113.538 67.745 -114.313 67.871 -115.187 68.162 -115.027 68.247 -114.368 68.415 -114.038 68.659 -114.451 68.854 -115.038 68.929 -115.951 68.871 -116.527 68.929 -117.231 69.036 -118.049 69.206 -118.703 69.310 -119.467 69.407 -120.236 69.602 -120.830 69.764 -121.522 69.808 -122.346 69.742 -123.027 69.451 -123.379 69.412 -124.165 69.723 -124.291 70.025 -124.445 70.030 -124.808 69.753 -125.082 69.462 -125.363 69.467 -126.071 69.701 -126.571 69.973 -126.841 70.242 -127.159 70.497 -127.819 70.294 -127.923 70.030 -128.341 69.824 -128.962 69.791 -129.714 69.629 -130.390 69.305 -130.857 69.434 -131.176 69.335 -131.901 69.165 -132.423 68.901 -132.659 68.802 -133.137 69.047 -133.000 69.255 -132.500 69.484 -131.956 69.591 -131.220 69.723 -130.610 70.074 -129.764 70.113 -130.500 69.934 -131.165 69.758 -132.077 69.673 -132.571 69.462 -133.159 69.313 -133.868 69.093 -134.445 68.802 -134.385 68.827 -134.654 68.797 -135.368 68.854 -136.016 68.907 -136.797 69.019 -137.533 69.223 -138.313 69.368 -138.841 69.560 -139.522 69.607 -140.247 69.651 -141.110 69.775 -141.791 69.940 -142.456 70.085 -143.225 70.058 -144.016 69.989 -144.830 70.085 -145.577 70.181 -146.390 70.187 -147.214 70.299 -148.016 70.407 -148.769 70.497 -149.588 70.464 -150.462 70.431 -151.275 70.544 -152.137 70.810 -152.538 70.904 -153.291 70.827 -154.198 71.033 -154.962 70.863 -155.742 71.055 -155.852 71.305 -156.423 71.157 -157.082 70.931 -157.621 70.816 -158.412 70.799 -159.258 70.602 -159.775 70.374 -159.758 70.464 -160.066 70.379 -160.791 70.231 -161.775 70.146 -162.236 69.912 -162.659 69.657 -163.027 69.368 -163.203 69.132 -163.621 68.951 -164.247 68.887 -165.038 68.871 -165.857 68.717 -166.214 68.404 -166.511 68.286 -166.319 68.104 -165.714 67.937 -165.082 67.758 -164.571 67.522 -164.011 67.245 -163.786 67.069 -163.352 67.052 -162.538 66.964 -161.797 66.640 -161.703 66.613 -161.132 66.549 -160.374 66.409 -160.830 66.492 -161.473 66.794 -162.280 66.632 -162.093 66.297 -161.451 66.069 -161.830 66.055 -162.555 66.082 -163.231 66.192 -163.929 66.538 -163.841 66.563 -164.533 66.429 -165.148 66.239 -165.692 66.140 -166.088 66.027 -166.764 65.854 -167.313 65.703 -167.890 65.547 -167.868 65.382 -167.044 65.313 -166.390 65.190 -166.742 64.981 -166.615 64.769 -166.429 64.569 -166.011 64.492 -165.357 64.492 -164.791 64.574 -164.159 64.538 -163.280 64.462 -162.868 64.519 -162.511 64.728 -161.945 64.854 -161.302 64.753 -160.868 64.475 -161.253 64.236 -161.016 63.956 -160.852 63.684 -160.890 63.486 -161.352 63.475 -162.077 63.341 -162.505 63.129 -162.934 63.080 -163.588 63.239 -164.038 63.074 -164.484 62.764 -164.764 62.503 -164.714 62.453 -165.209 62.206 -165.566 61.901 -165.747 61.687 -166.038 61.475 -165.934 61.179 -165.571 61.286 -165.286 61.525 -164.918 61.495 -164.918 61.239 -165.192 61.025 -164.984 60.885 -164.495 60.920 -163.813 60.755 -163.648 60.681 -164.148 60.860 -164.709 60.621 -165.170 60.412 -165.005 60.223 -164.577 59.967 -164.187 59.808 -163.797 59.843 -163.231 59.970 -162.703 60.220 -162.549 60.571 -162.214 60.404 -162.335 60.181 -162.264 59.887 -162.071 59.618 -161.835 59.346 -161.940 59.126 -161.852 58.997 -161.753 58.681 -161.863 58.637 -161.489 58.819 -161.110 58.981 -160.500 58.865 -159.995 58.852 -159.560 58.514 -158.995 58.832 -158.813 59.014 -158.313 58.951 -158.429 58.681 -158.302 58.701 -157.813 58.830 -157.313 59.025 -156.923 59.003 -156.896 58.739 -157.066 58.503 -157.429 58.212 -157.401 57.940 -157.632 57.596 -157.588 57.511 -157.621 57.387 -158.104 57.187 -158.489 56.857 -158.808 56.736 -159.187 56.610 -159.588 56.440 -160.038 56.225 -160.385 55.898 -160.407 55.819 -160.758 55.970 -161.154 55.915 -161.626 55.764 -162.055 55.511 -162.467 55.316 -162.703 55.181 -163.082 54.945 -163.313 55.008 -163.132 55.099 -162.615 55.091 -162.170 55.266 -161.890 55.547 -161.626 55.473 -161.330 55.492 -160.819 55.582 -160.451 55.758 -160.011 55.690 -159.681 55.755 -159.527 55.890 -159.192 56.058 -158.632 56.212 -158.379 56.429 -158.346 56.566 -157.945 56.734 -157.478 56.876 -157.027 57.030 -156.626 57.275 -156.423 57.495 -156.077 57.643 -155.703 57.816 -155.291 58.016 -154.857 58.129 -154.412 58.324 -154.181 58.569 -153.863 58.794 -153.396 58.997 -153.538 59.124 -154.115 59.409 -153.934 59.654 -153.527 59.772 -153.143 59.948 -152.742 60.228 -152.879 60.266 -152.665 60.486 -152.258 60.734 -151.868 60.967 -151.566 61.132 -151.071 61.283 -150.544 61.407 -149.681 61.242 -149.907 60.953 -149.401 60.942 -149.819 60.981 -150.401 60.849 -150.940 60.657 -151.330 60.354 -151.352 60.096 -151.599 59.821 -151.824 59.692 -151.308 59.519 -151.390 59.352 -151.874 59.203 -151.577 59.269 -151.060 59.538 -150.456 59.607 -150.121 59.799 -149.742 59.995 -149.275 59.967 -148.637 60.181 -148.280 60.440 -148.099 60.500 -148.341 60.552 -148.445 60.731 -148.462 60.951 -148.330 61.143 -147.940 61.036 -147.934 60.959 -147.593 60.975 -147.104 61.104 -146.527 60.997 -146.599 60.775 -146.346 60.613 -145.868 60.409 -145.489 60.588 -144.863 60.409 -144.852 60.203 -144.467 60.047 -144.049 60.049 -143.429 60.093 -142.846 60.058 -142.269 60.005 -141.484 59.832 -141.220 59.723 -140.681 59.747 -140.132 59.942 -139.648 59.882 -139.154 59.783 -139.341 59.610 -139.648 59.407 -139.440 59.286 -139.049 59.135 -138.511 58.951 -138.071 58.681 -137.665 58.505 -137.379 58.321 -136.791 58.357 -136.401 58.495 -136.121 58.701 -136.456 58.860 -136.863 58.962 -136.857 58.885 -136.269 58.830 -135.945 58.459 -135.747 58.299 -135.313 58.390 -135.088 58.679 -135.214 59.074 -135.396 59.310 -135.401 59.250 -135.319 58.967 -135.170 58.723 -134.978 58.426 -134.731 58.371 -134.077 58.113 -133.907 57.901 -133.549 57.618 -133.368 57.379 -133.330 57.203 -133.291 57.005 -132.879 56.761 -132.527 56.549 -132.324 56.253 -131.813 56.038 -131.973 55.670 -132.071 55.794 -131.813 56.011 -131.264 55.835 -131.022 55.571 -130.879 55.239 -130.764 55.077 -130.835 54.849 -130.753 54.920 -130.368 55.181 -130.115 55.440 -130.082 55.717 -130.093 55.788 -130.088 55.431 -130.022 55.132 -130.082 55.146 -129.945 55.453 -129.808 55.426 -129.659 55.066 -129.841 54.915 -130.005 54.668 -130.137 54.442 -130.077 54.481 -130.313 54.286 -130.264 54.217 -129.725 54.102 -129.841 53.953 -130.049 53.723 -129.791 53.475 -129.423 53.621 -129.192 53.868 -128.868 53.819 -128.659 53.530 -128.681 53.382 -128.099 53.412 -128.297 53.500 -128.753 53.401 -128.879 53.151 -128.599 52.876 -128.275 ; #2 2 -69.571 75.665 -69.646 75.049 -69.747 74.374 -69.863 73.599 -70.041 72.940 -70.316 72.753 -70.555 72.511 -70.758 71.890 -71.033 71.484 -71.327 71.308 -71.604 71.253 -71.879 70.874 -72.077 70.176 -72.288 69.571 -72.401 68.714 -72.258 67.852 -72.019 67.478 -71.695 67.736 -71.467 67.852 -71.234 68.363 -71.014 68.934 -70.739 69.203 -70.423 69.187 -70.607 68.571 -70.475 68.044 -70.242 67.725 -69.962 68.033 -69.962 68.731 -69.753 69.187 -69.505 68.945 -69.357 69.407 -69.190 69.571 -68.934 69.566 -68.670 69.764 -68.434 70.005 -68.162 69.714 -67.841 69.632 -67.835 69.044 -67.854 68.280 -67.805 67.522 -67.769 66.769 -67.723 66.005 -67.662 65.247 -67.607 64.505 -67.527 63.780 -67.577 63.049 -67.593 62.368 -67.519 61.577 -67.442 60.918 -67.379 60.203 -67.387 59.445 -67.269 58.934 -67.126 58.291 -67.025 57.615 -66.920 56.918 -66.728 57.005 -66.536 57.165 -66.390 56.489 -66.212 55.967 -65.989 55.500 -65.890 54.830 -65.876 54.115 -65.871 53.418 -65.931 52.720 -65.984 52.016 -66.162 51.451 -66.335 50.896 -66.500 50.330 -66.786 50.247 -67.049 50.560 -67.181 50.467 -67.069 49.769 -66.975 49.121 -67.107 48.418 -67.343 48.852 -67.514 48.643 -67.654 47.995 -67.659 47.308 -67.404 47.198 -67.294 46.555 -67.544 46.275 -67.709 45.665 -67.775 44.940 -67.962 44.341 -68.038 43.604 -68.110 42.841 -68.327 42.313 -68.462 41.604 -68.613 40.951 -68.786 40.313 -68.986 39.802 -69.313 39.742 -69.582 39.593 -69.852 38.819 -69.624 38.599 -69.797 38.253 -69.668 37.489 -69.412 37.830 -69.357 37.368 -69.624 36.808 -69.473 36.280 -69.255 36.148 -69.093 35.473 -68.871 34.940 -68.591 34.670 -68.508 33.978 -68.701 33.396 -68.975 33.247 -69.250 32.896 -69.456 32.308 -69.613 31.621 -69.780 30.929 -69.819 30.088 -69.874 29.275 -70.005 28.527 -70.118 27.736 -70.159 26.907 -70.261 26.104 -70.338 25.286 -70.431 24.473 -70.516 23.643 -70.533 22.780 -70.423 21.962 -70.390 21.110 -70.288 20.302 -70.176 19.511 -70.091 18.687 -70.000 17.890 -70.107 17.049 -70.214 16.258 -70.283 15.429 -70.231 14.593 -70.209 13.813 -70.288 12.956 -70.486 12.396 -70.701 11.857 -70.676 10.940 -70.481 10.324 -70.272 9.747 -70.091 9.027 -70.236 8.896 -70.423 8.538 -70.209 7.791 -70.385 7.187 -70.580 6.621 -70.613 5.753 -70.654 4.885 -70.728 4.049 -70.821 3.220 -70.915 2.396 -71.066 1.637 -71.192 0.824 -71.387 0.181 -71.604 -0.418 -71.387 -0.951 -71.418 -1.714 -71.299 -2.275 -71.269 -2.967 -71.316 -3.852 -71.321 -4.753 -71.407 -5.670 -71.239 -6.115 -70.992 -5.698 -70.747 -5.742 -70.821 -6.500 -71.038 -7.082 -71.299 -7.500 -71.615 -7.538 -71.745 -8.418 -71.448 -8.786 -71.173 -9.082 -70.962 -9.687 -71.074 -10.225 -71.346 -10.511 -71.604 -11.077 -71.376 -11.797 -71.574 -12.187 -71.799 -11.626 -72.069 -11.346 -72.332 -11.703 -72.555 -12.313 -72.739 -13.082 -72.797 -14.044 -72.959 -14.022 -73.170 -14.242 -73.217 -15.209 -73.376 -16.077 -73.720 -16.511 -73.912 -16.560 -74.058 -16.291 -73.995 -15.280 -73.890 -14.280 -74.085 -14.258 -74.245 -15.110 -74.459 -15.813 -74.651 -16.604 -74.885 -17.214 -75.157 -17.577 -75.407 -18.126 -75.712 -18.132 -75.788 -19.341 -75.868 -20.324 -75.945 -21.374 -75.978 -22.484 -76.041 -23.626 -76.121 -24.786 -76.280 -25.890 -76.409 -26.775 -76.533 -27.907 -76.706 -28.907 -76.915 -29.775 -77.093 -30.786 -77.308 -31.676 -77.448 -32.852 -77.662 -33.769 -77.904 -34.500 -78.143 -35.258 -78.407 -35.896 -78.687 -36.247 -78.973 -36.044 -79.154 -34.846 -79.357 -33.797 -79.431 -32.374 -79.297 -30.967 -79.154 -29.621 -79.052 -27.797 -79.195 -28.016 -79.409 -29.027 -79.684 -29.791 -79.909 -28.484 -80.176 -28.148 -80.379 -29.214 -80.495 -30.885 -80.646 -32.346 -80.750 -34.027 -80.882 -35.621 -80.992 -37.313 -81.165 -38.852 -81.302 -40.511 -81.495 -41.962 -81.769 -42.648 -81.863 -44.434 -81.810 -46.434 -81.849 -48.440 -81.931 -50.368 -82.055 -52.242 -82.195 -54.077 -82.407 -55.555 -82.657 -56.599 -82.948 -58.071 -82.794 -58.956 -82.508 -59.291 -82.308 -60.874 -82.110 -62.484 -81.918 -63.973 -81.717 -65.434 -81.505 -66.835 -81.316 -68.302 -81.151 -69.863 -81.041 -71.599 -80.882 -73.148 -80.692 -74.549 -80.448 -75.357 -80.198 -76.302 -80.041 -78.896 -80.019 -77.758 -79.843 -76.505 -79.577 -76.143 -79.327 -76.791 -79.275 -78.242 -79.255 -79.841 -79.484 -80.495 -79.431 -81.038 -79.173 -81.830 -78.992 -82.912 -78.706 -83.390 -78.418 -83.885 -78.332 -83.049 -78.580 -82.132 -78.764 -81.022 -78.824 -79.566 -78.734 -78.159 -78.492 -77.577 -78.255 -78.368 -78.135 -79.659 -77.970 -81.000 -77.750 -81.033 -77.758 -79.934 -77.868 -78.643 -77.931 -77.302 -78.014 -75.989 -78.115 -74.687 -77.942 -73.538 -77.662 -73.000 -77.492 -73.962 -77.484 -75.324 -77.291 -76.242 -77.049 -76.967 -76.797 -77.577 -76.541 -78.126 -76.280 -78.440 -76.008 -77.791 -76.071 -76.703 -76.321 -76.192 -76.533 -75.434 -76.599 -74.220 -76.640 -72.978 -76.665 -71.725 -76.673 -70.429 -76.426 -69.797 -76.272 -68.868 -76.159 -67.775 -76.049 -66.648 -75.898 -65.648 -75.720 -64.720 -75.541 -63.786 -75.308 -63.802 -75.060 -63.544 -74.761 -63.154 -74.885 -62.522 -74.788 -61.945 -74.508 -61.802 -74.253 -61.451 -74.027 -61.385 -73.912 -61.209 -73.698 -60.753 -73.497 -61.346 -73.250 -61.659 -73.275 -60.885 -73.217 -60.209 -72.959 -60.165 -72.709 -60.780 -72.541 -61.407 -72.346 -61.000 -72.088 -61.126 -72.019 -62.275 -71.898 -62.049 -71.805 -61.148 -71.615 -61.484 -71.467 -61.434 -71.250 -61.082 -70.951 -61.280 -70.816 -61.918 -70.624 -61.775 -70.401 -62.209 -70.154 -62.066 -69.874 -62.484 -69.577 -62.478 -69.352 -62.918 -69.143 -63.423 -68.821 -63.527 -68.602 -63.786 -68.415 -63.137 -68.357 -63.467 -68.492 -64.220 -68.723 -64.104 -68.745 -64.423 -68.695 -65.187 -68.445 -65.357 -68.187 -64.989 -68.074 -65.385 -67.753 -65.467 -67.492 -65.516 -67.305 -65.000 -67.027 -64.775 -66.830 -64.049 -66.536 -63.940 -66.286 -63.566 -66.574 -62.720 -66.286 -62.632 -66.319 -61.841 -66.231 -61.247 -66.044 -60.709 -65.981 -61.154 -66.096 -61.819 -65.890 -62.368 -65.588 -61.973 -65.382 -62.055 -65.170 -61.709 -64.981 -61.126 -64.764 -60.692 -64.555 -60.242 -64.426 -59.626 -64.467 -59.022 -64.313 -58.830 -64.022 -58.665 -63.797 -58.297 -63.624 -57.747 -63.547 -57.066 -63.294 -57.027 -63.261 -57.599 -63.409 -58.132 -63.538 -58.764 -63.745 -59.247 -63.854 -59.758 -63.948 -60.308 -64.096 -60.890 -64.357 -61.198 -64.533 -61.665 -64.706 -62.324 -64.854 -62.725 -65.052 -63.170 -65.093 -63.896 -65.398 -63.956 -65.599 -64.099 -65.808 -64.495 -65.984 -64.813 -66.096 -65.368 -66.299 -65.824 -66.544 -66.198 -66.786 -66.462 -66.975 -66.879 -67.113 -67.440 -67.453 -67.522 -67.522 -66.747 -67.714 -66.797 -67.962 -67.038 -68.245 -66.907 -68.503 -67.055 -68.797 -67.209 -69.008 -66.868 -69.283 -67.165 -69.335 -67.951 -69.418 -68.555 -69.706 -68.385 -69.989 -68.434 -70.247 -68.060 -70.522 -67.797 -70.799 -67.593 -71.080 -67.429 -71.371 -67.505 -71.654 -67.291 -71.915 -66.940 -72.206 -66.923 -72.478 -67.011 -72.739 -67.473 -72.934 -68.154 -73.110 -68.956 -73.236 -69.863 -73.288 -70.841 -73.390 -71.758 -73.470 -72.764 -73.610 -73.637 -73.692 -74.637 -73.739 -75.604 -73.830 -76.632 -73.665 -76.780 -73.544 -77.352 -73.646 -78.434 -73.475 -78.885 -73.242 -79.495 -73.085 -80.302 -73.217 -80.615 -73.415 -80.956 -73.684 -81.148 -73.885 -81.703 -73.849 -82.588 -73.720 -83.522 -73.673 -84.495 -73.563 -85.473 -73.203 -85.846 -73.275 -86.555 -73.242 -87.429 -73.176 -88.324 -72.810 -88.896 -73.033 -89.390 -73.176 -90.165 -73.283 -91.055 -73.195 -92.088 -73.190 -93.060 -73.269 -93.995 -73.236 -94.984 -73.283 -95.989 -73.255 -96.962 -73.124 -97.918 -72.992 -98.648 -73.025 -99.648 -73.052 -100.621 -73.044 -101.720 -72.934 -102.418 -72.753 -103.011 -72.940 -103.516 -73.228 -103.253 -73.335 -102.401 -73.349 -101.407 -73.382 -100.390 -73.571 -99.527 -73.706 -99.912 -73.725 -100.945 -73.618 -101.901 -73.665 -102.835 -73.918 -102.484 -74.077 -101.725 -74.387 -101.418 -74.486 -100.511 -74.745 -100.451 -74.912 -100.060 -75.126 -99.632 -75.255 -100.533 -75.255 -101.643 -75.069 -102.462 -75.038 -103.665 -75.069 -104.786 -75.165 -105.874 -75.308 -106.852 -75.269 -107.951 -75.157 -109.011 -75.203 -110.390 -74.920 -110.500 -74.659 -110.022 -74.343 -110.154 -74.203 -111.060 -74.387 -111.544 -74.673 -111.538 -74.841 -112.170 -74.717 -112.962 -74.495 -113.258 -74.217 -113.346 -73.973 -113.791 -74.036 -114.621 -74.357 -114.731 -74.473 -115.610 -74.536 -116.637 -74.409 -117.659 -74.500 -118.429 -74.624 -119.291 -74.681 -120.368 -74.723 -121.467 -74.687 -122.555 -74.723 -123.621 -74.681 -124.725 -74.659 -125.819 -74.651 -126.912 -74.703 -127.973 -74.805 -128.989 -74.827 -130.077 -74.783 -131.176 -74.745 -132.264 -74.819 -133.368 -74.629 -134.269 -74.607 -135.308 -74.745 -136.363 -74.973 -137.011 -75.077 -138.055 -75.121 -139.209 -75.360 -139.890 -75.497 -140.824 -75.497 -141.978 -75.588 -142.929 -75.712 -144.071 -75.882 -144.857 -75.962 -146.022 -76.321 -145.819 -76.297 -146.879 -76.143 -148.022 -76.321 -149.132 -76.467 -148.473 -76.442 -147.291 -76.599 -146.302 -76.830 -145.709 -77.049 -145.874 -77.327 -146.049 -77.327 -146.984 -77.484 -148.192 -77.651 -149.192 -77.662 -150.181 -77.448 -151.148 -77.412 -152.269 -77.368 -153.132 -77.179 -154.060 -77.102 -155.286 -77.239 -156.198 -77.203 -157.368 -77.440 -157.764 -77.714 -158.005 -77.986 -157.890 -78.220 -156.714 -78.162 -155.357 -78.181 -154.060 -78.464 -154.137 -78.599 -155.522 -78.802 -155.445 -79.022 -154.445 -79.143 -153.088 -79.275 -151.775 -79.462 -150.538 -79.599 -149.126 -79.747 -147.764 -79.953 -146.582 -80.220 -145.918 -80.505 -145.626 -80.750 -146.522 -80.981 -147.555 -81.264 -148.379 -81.352 -149.901 -81.190 -151.495 -81.091 -153.192 -81.016 -155.000 -81.165 -156.637 -81.352 -155.868 -81.558 -154.335 -81.835 -154.665 -82.124 -154.071 -82.365 -152.819 -82.626 -151.907 -82.901 -152.566 -83.184 -153.005 -83.481 -152.956 -83.755 -153.099 -84.044 -152.874 -84.308 -151.703 -84.522 -149.731 -84.665 -147.077 -84.788 -144.121 -84.874 -141.088 -85.047 -138.995 -85.228 -140.857 -85.137 -144.258 -85.115 -147.808 -85.368 -150.170 -85.343 -153.445 -85.390 -157.176 -85.321 -160.632 -85.137 -163.346 -84.959 -166.005 -84.788 -168.132 -84.602 -170.769 -84.484 -173.533 -84.462 -176.599 -84.365 -179.049 -84.173 178.758 -84.025 176.368 -83.863 174.033 -83.720 172.198 -83.497 171.000 -83.396 168.560 -83.266 168.159 -83.011 167.863 -82.808 166.824 -82.569 165.615 -82.349 164.357 -82.124 163.643 -81.849 162.742 -81.571 161.258 -81.288 161.621 -81.052 160.665 -80.786 160.593 -80.527 160.489 -80.437 159.055 -80.253 158.599 -79.997 159.907 -79.747 159.934 -79.462 160.511 -79.184 160.324 -78.992 161.220 -78.874 162.544 -78.695 163.725 -78.580 164.951 -78.580 166.753 -78.464 166.374 -78.181 165.423 -78.060 164.610 -77.723 164.275 -77.544 163.747 -77.255 163.544 -77.016 162.835 -76.838 162.769 -76.574 162.841 -76.272 162.709 -76.008 162.813 -75.758 162.995 -75.481 162.830 -75.187 162.571 -75.016 163.357 -74.753 163.901 -74.673 164.797 -74.473 165.181 -74.181 164.918 -74.091 165.797 -73.918 165.885 -73.698 166.670 -73.489 167.456 -73.530 168.132 -73.475 168.846 -73.209 169.192 -72.986 169.703 -72.681 170.088 -72.396 170.192 -72.151 170.066 -71.964 170.632 -71.720 170.841 -71.484 170.308 -71.423 169.407 -71.228 168.753 -71.033 168.005 -70.786 167.659 -70.701 166.747 -70.654 165.967 -70.569 165.170 -70.497 164.308 -70.574 163.511 -70.374 162.846 -70.305 162.033 -70.231 161.258 -70.085 160.549 -69.863 160.137 -69.651 159.571 -69.495 158.896 -69.310 158.297 -69.115 157.385 -69.179 156.742 -69.201 155.995 -69.115 155.209 -68.918 154.511 -68.665 154.555 -68.429 153.940 -68.618 153.797 -68.896 153.599 -68.838 152.797 -68.838 152.088 -68.882 151.198 -68.508 151.011 -68.451 150.269 -68.341 149.560 -68.310 148.731 -68.052 148.434 -67.890 147.995 -68.052 147.220 -67.926 146.989 -67.692 146.462 -67.588 145.604 -67.313 145.698 -67.093 145.549 -67.146 144.797 -67.049 144.148 -66.907 143.511 -66.981 142.725 -66.824 142.110 -66.786 141.363 -66.731 140.654 -66.654 139.984 -66.555 139.291 -66.516 138.571 -66.415 137.890 -66.330 137.214 -66.319 136.505 -66.195 135.824 -66.060 135.126 -65.810 135.099 -65.525 135.258 -65.245 135.093 -65.030 134.764 -65.038 134.231 -65.335 134.132 -65.626 134.181 -65.901 134.390 -66.135 134.132 -66.077 133.368 -66.146 132.676 -66.195 131.989 -66.231 131.286 -66.214 130.560 -66.357 129.940 -66.596 129.516 -66.868 129.313 -67.096 128.956 -67.044 128.231 -66.956 127.538 -66.780 126.978 -66.481 126.852 -66.316 126.225 -66.467 125.549 -66.703 125.132 -66.615 124.621 -66.558 124.016 -66.698 123.368 -66.665 122.846 -66.577 122.088 -66.698 121.401 -66.819 120.758 -66.854 120.011 -66.920 119.313 -66.926 118.544 -66.964 117.841 -66.863 117.132 -66.626 116.742 -66.409 116.264 -66.376 115.560 -66.473 114.824 -66.247 114.473 -66.016 114.033 -65.791 113.555 -65.775 112.956 -65.882 112.308 -65.931 111.610 -66.060 110.973 -66.319 110.742 -66.549 110.407 -66.684 109.780 -66.772 108.956 -66.632 108.368 -66.440 107.797 -66.415 107.055 -66.343 106.368 -66.264 105.687 -66.154 105.011 -66.049 104.357 -65.997 103.670 -65.929 102.995 -65.931 102.291 -66.014 101.615 -66.107 100.956 -66.338 100.505 -66.519 99.951 -66.780 99.418 -66.670 98.962 -66.536 98.412 -66.640 97.665 -66.588 96.989 -66.646 96.253 -66.659 95.495 -66.574 94.797 -66.640 94.082 -66.596 93.363 -66.615 92.621 -66.549 91.918 -66.558 91.181 -66.640 90.489 -66.703 89.780 -66.728 88.984 -66.481 88.758 -66.146 88.445 -66.264 88.181 -66.569 88.082 -66.805 87.698 -66.975 87.093 -67.044 86.390 -67.157 85.736 -67.151 84.984 -67.146 84.247 -67.157 83.500 -67.305 82.824 -67.286 82.159 -67.547 81.753 -67.698 81.516 -67.860 80.868 -67.937 80.126 -68.052 79.418 -68.217 78.797 -68.440 78.280 -68.690 77.956 -68.975 77.901 -69.173 77.407 -69.313 76.681 -69.456 76.060 ; #3 1 -20.937 149.044 -20.805 148.819 -20.511 148.791 -20.264 148.736 -20.137 148.484 -20.016 148.253 -19.885 147.973 -19.758 147.709 -19.440 147.484 -19.409 147.236 -19.272 146.989 -19.184 146.687 -19.030 146.423 -18.786 146.291 -18.511 146.264 -18.291 146.066 -18.016 146.055 -17.739 146.110 -17.464 146.071 -17.192 145.956 -16.929 145.841 -16.712 145.626 -16.475 145.451 -16.203 145.445 -15.918 145.385 -15.635 145.319 -15.335 145.286 -15.074 145.275 -14.876 145.203 -14.712 144.956 -14.547 144.709 -14.294 144.571 -14.272 144.330 -14.390 144.121 -14.453 143.863 -14.201 143.709 -13.931 143.615 -13.654 143.555 -13.376 143.555 -13.088 143.505 -12.832 143.434 -12.558 143.341 -12.321 143.143 -12.025 143.159 -11.874 142.945 -11.593 142.846 -11.310 142.824 -11.016 142.725 -10.821 142.549 -10.841 142.363 -11.033 142.159 -11.341 142.121 -11.624 142.038 -11.915 141.973 -12.049 141.885 -12.277 141.731 -12.635 141.819 -12.824 141.725 -13.058 141.615 -13.341 141.648 -13.613 141.522 -13.901 141.484 -14.173 141.588 -14.464 141.538 -14.750 141.571 -15.038 141.637 -15.310 141.555 -15.588 141.451 -15.879 141.401 -16.159 141.385 -16.451 141.291 -16.712 141.170 -16.951 141.005 -17.223 140.918 -17.470 140.780 -17.621 140.522 -17.701 140.231 -17.657 139.945 -17.533 139.670 -17.385 139.407 -17.220 139.181 -16.962 139.055 -16.843 138.769 -16.777 138.478 -16.695 138.192 -16.514 137.956 -16.297 137.753 -16.165 137.489 -16.025 137.231 -15.912 136.951 -15.846 136.692 -15.662 136.451 -15.464 136.236 -15.288 136.005 -15.121 135.753 -14.970 135.500 -14.712 135.445 -14.464 135.615 -14.236 135.813 -13.989 135.934 -13.712 135.973 -13.453 135.901 -13.250 136.022 -13.179 136.291 -13.168 136.489 -12.885 136.560 -12.580 136.725 -12.387 136.907 -12.225 136.742 -12.005 136.555 -12.027 136.357 -12.236 136.280 -12.448 136.143 -12.228 136.005 -12.209 135.841 -12.168 135.720 -11.934 135.852 -11.865 135.813 -12.047 135.571 -12.203 135.286 -12.220 135.055 -12.030 134.797 -12.049 134.544 -12.000 134.231 -11.849 133.962 -11.772 133.742 -11.775 133.456 -11.684 133.198 -11.418 132.945 -11.453 132.676 -11.245 132.429 -11.255 132.220 -11.247 132.088 -11.272 131.890 -11.475 132.110 -11.484 132.445 -11.701 132.626 -12.041 132.670 -12.225 132.467 -12.214 132.253 -12.269 131.956 -12.286 131.659 -12.176 131.341 -12.214 131.110 -12.484 130.907 -12.473 130.731 -12.632 130.571 -12.772 130.357 -12.986 130.165 -13.291 130.231 -13.486 130.005 -13.626 129.813 -13.887 129.747 -14.071 129.555 -14.349 129.401 -14.577 129.637 -14.775 129.846 -14.843 129.769 -15.096 129.659 -15.025 129.533 -15.044 129.242 -14.942 129.110 -14.832 128.824 -14.802 128.489 -15.000 128.335 -15.321 128.165 -15.225 128.071 -14.923 128.126 -14.690 128.143 -14.486 127.896 -14.264 127.720 -14.060 127.495 -13.931 127.247 -13.827 127.033 -13.854 126.824 -14.088 126.681 -14.049 126.511 -14.126 126.324 -14.011 126.148 -14.077 126.066 -14.418 126.022 -14.527 125.780 -14.332 125.665 -14.407 125.593 -14.558 125.429 -14.695 125.214 -14.942 125.280 -15.099 125.291 -15.063 125.027 -15.319 125.000 -15.324 124.808 -15.407 124.648 -15.599 124.412 -15.865 124.538 -16.049 124.555 -16.247 124.429 -16.376 124.758 -16.398 124.687 -16.390 124.379 -16.299 124.121 -16.280 123.775 -16.456 123.582 -16.602 123.555 -16.849 123.830 -17.088 123.753 -17.420 123.577 -17.316 123.407 -17.058 123.264 -16.780 123.121 -16.519 123.005 -16.503 122.868 -16.747 122.714 -16.937 122.495 -17.143 122.258 -17.407 122.148 -17.687 122.181 -17.962 122.258 -18.181 122.258 -18.368 122.033 -18.549 121.791 -18.786 121.637 -19.071 121.511 -19.313 121.346 -19.516 121.126 -19.665 120.868 -19.780 120.588 -19.885 120.297 -19.937 119.995 -20.008 119.698 -20.014 119.412 -19.992 119.110 -20.190 118.879 -20.319 118.621 -20.354 118.302 -20.445 118.027 -20.624 117.791 -20.701 117.505 -20.665 117.187 -20.629 116.857 -20.703 116.626 -20.835 116.352 -20.964 116.115 -21.146 115.868 -21.332 115.637 -21.527 115.407 -21.651 115.115 -21.753 114.830 -21.953 114.582 -22.179 114.473 -22.459 114.269 -22.294 114.121 -21.915 114.115 -21.989 113.934 -22.258 113.824 -22.525 113.692 -22.786 113.731 -23.069 113.786 -23.354 113.769 -23.610 113.648 -23.863 113.495 -24.143 113.412 -24.434 113.407 -24.684 113.560 -24.953 113.643 -25.206 113.797 -25.464 113.945 -25.714 114.110 -25.967 114.225 -26.324 114.110 -26.099 113.835 -25.929 113.709 -25.629 113.522 -25.805 113.451 -26.069 113.577 -26.286 113.791 -26.571 113.769 -26.467 113.555 -26.190 113.324 -26.352 113.280 -26.582 113.478 -26.808 113.676 -27.052 113.846 -27.308 114.000 -27.580 114.115 -27.868 114.110 -28.146 114.209 -28.376 114.407 -28.626 114.566 -28.896 114.654 -29.140 114.846 -29.420 114.951 -29.706 114.945 -30.000 114.956 -30.280 115.005 -30.563 115.077 -30.835 115.203 -31.091 115.357 -31.357 115.495 -31.615 115.648 -31.896 115.731 -32.203 115.725 -32.593 115.698 -32.745 115.615 -33.033 115.670 -33.288 115.659 -33.569 115.445 -33.602 115.132 -33.679 114.978 -33.970 114.967 -34.269 115.077 -34.354 115.412 -34.516 115.698 -34.745 115.934 -34.879 116.258 -34.973 116.489 -35.033 116.868 -35.033 117.220 -35.082 117.577 -35.063 117.918 -34.942 118.253 -34.728 118.511 -34.538 118.797 -34.486 119.121 -34.401 119.429 -34.140 119.604 -33.970 119.890 -33.948 120.231 -33.920 120.566 -33.868 120.918 -33.841 121.253 -33.852 121.604 -33.893 121.978 -33.981 122.247 -33.920 122.577 -33.882 122.923 -33.953 123.242 -33.863 123.610 -33.629 123.852 -33.382 124.005 -33.113 124.143 -32.951 124.418 -32.882 124.758 -32.728 125.049 -32.593 125.352 -32.456 125.648 -32.302 125.940 -32.264 126.275 -32.308 126.621 -32.302 126.962 -32.269 127.297 -32.176 127.615 -32.096 127.951 -31.997 128.269 -31.874 128.577 -31.739 128.874 -31.665 129.209 -31.629 129.544 -31.604 129.885 -31.585 130.225 -31.599 130.566 -31.580 130.901 -31.505 131.220 -31.618 131.544 -31.766 131.835 -31.948 132.104 -32.005 132.418 -31.964 132.731 -32.118 133.033 -32.179 133.390 -32.176 133.676 -32.440 133.912 -32.538 134.209 -32.810 134.154 -33.107 134.280 -33.203 134.632 -33.429 134.830 -33.692 134.934 -33.918 135.181 -34.179 135.291 -34.538 135.308 -34.703 135.396 -34.871 135.846 -34.632 135.912 -34.434 136.121 -34.165 136.324 -33.956 136.555 -33.769 136.879 -33.676 137.159 -33.429 137.346 -33.162 137.473 -32.953 137.714 -32.668 137.775 -32.679 137.863 -32.959 137.956 -33.198 137.918 -33.495 137.912 -33.728 137.764 -33.967 137.582 -34.231 137.484 -34.514 137.467 -34.852 137.440 -34.923 137.126 -35.190 136.940 -35.181 137.280 -35.126 137.648 -34.871 137.819 -34.591 137.890 -34.264 138.055 -34.415 138.258 -34.698 138.467 -34.956 138.495 -35.247 138.451 -35.569 138.236 -35.610 138.582 -35.505 138.912 -35.379 139.247 -35.580 139.231 -35.698 139.181 -35.907 139.412 -36.033 139.555 -35.659 139.082 -35.720 139.148 -35.920 139.407 -36.154 139.610 -36.420 139.753 -36.695 139.852 -36.975 139.747 -37.255 139.802 -37.503 140.038 -37.717 140.264 -37.951 140.467 -38.063 140.797 -38.140 141.143 -38.363 141.434 -38.316 141.714 -38.360 142.104 -38.396 142.462 -38.549 142.780 -38.684 143.110 -38.805 143.451 -38.714 143.775 -38.516 144.044 -38.349 144.346 -38.162 144.560 -37.929 144.835 -38.074 145.077 -38.341 144.852 -38.462 144.989 -38.288 145.302 -38.437 145.467 -38.657 145.698 -38.835 145.951 -39.027 146.335 -38.830 146.346 -38.701 146.544 -38.626 146.896 -38.409 147.165 -38.203 147.423 -38.019 147.698 -37.890 148.022 -37.821 148.379 -37.810 148.747 -37.794 149.126 -37.766 149.473 -37.577 149.764 -37.374 149.973 -37.118 149.951 -36.852 149.945 -36.563 150.044 -36.283 150.121 -36.014 150.137 -35.734 150.258 -35.467 150.429 -35.217 150.615 -35.022 150.764 -34.736 150.830 -34.500 150.879 -34.209 151.055 -33.981 151.209 -33.643 151.291 -33.387 151.478 -33.179 151.626 -32.931 151.797 -32.742 152.115 -32.560 152.324 -32.349 152.533 -32.060 152.560 -31.808 152.764 -31.536 152.901 -31.258 152.978 -30.967 153.055 -30.684 153.011 -30.401 153.088 -30.126 153.192 -29.849 153.275 -29.563 153.335 -29.277 153.374 -29.003 153.489 -28.734 153.604 -28.448 153.571 -28.173 153.527 -27.898 153.423 -27.632 153.319 -27.374 153.148 -27.115 153.126 -26.805 153.143 -26.530 153.115 -26.253 153.093 -25.929 153.093 -25.690 152.929 -25.398 152.907 -25.198 152.648 -24.953 152.505 -24.734 152.341 -24.549 152.093 -24.266 151.945 -24.058 151.698 -23.995 151.456 -23.794 151.214 -23.566 150.956 -23.349 150.824 -23.060 150.769 -22.783 150.802 -22.492 150.654 -22.459 150.352 -22.239 150.093 -22.475 149.978 -22.445 149.780 -22.242 149.599 -21.962 149.495 -21.648 149.451 -21.431 149.319 -21.159 149.214 ; #4 2 66.220 -35.681 66.343 -35.610 66.330 -34.984 66.516 -34.538 66.703 -34.198 67.008 -33.802 67.288 -33.489 67.544 -33.242 67.728 -32.852 67.915 -32.209 68.187 -32.187 68.462 -32.445 68.486 -32.269 68.245 -31.791 68.093 -31.379 68.140 -30.571 68.228 -30.104 68.310 -29.703 68.316 -29.143 68.440 -28.363 68.522 -27.720 68.629 -26.973 68.739 -26.231 68.951 -25.637 69.148 -25.220 69.341 -24.637 69.533 -24.027 69.753 -23.473 69.907 -22.901 70.080 -22.489 70.124 -23.681 70.236 -24.445 70.343 -25.220 70.266 -26.016 70.209 -26.868 70.019 -27.500 70.102 -28.088 70.283 -26.989 70.423 -26.698 70.407 -27.758 70.453 -28.516 70.481 -28.879 70.676 -28.137 70.962 -27.989 71.038 -27.626 70.951 -26.802 71.066 -26.033 71.280 -25.566 71.489 -26.093 71.525 -27.071 71.580 -27.841 71.593 -28.044 71.755 -27.571 71.945 -28.192 72.038 -28.291 71.835 -27.484 71.604 -26.780 71.555 -25.934 71.371 -25.181 71.239 -24.555 70.945 -24.214 70.665 -24.000 70.464 -23.357 70.533 -22.648 70.670 -22.467 70.511 -21.769 70.775 -21.709 71.055 -21.857 71.376 -21.978 71.544 -22.368 71.690 -22.423 71.750 -22.912 71.984 -22.885 72.176 -23.687 72.346 -24.341 72.338 -25.143 72.332 -25.478 72.593 -24.764 72.786 -25.522 72.714 -26.467 72.824 -26.830 72.876 -25.588 73.063 -25.275 73.170 -26.286 73.143 -27.121 73.390 -26.973 73.308 -25.736 73.549 -25.000 73.766 -25.258 73.679 -24.374 73.739 -23.670 73.604 -22.703 73.582 -22.692 73.577 -23.643 73.297 -22.659 73.363 -21.802 73.456 -21.060 73.591 -20.467 73.863 -20.555 73.940 -21.676 73.794 -21.852 74.113 -22.225 74.374 -22.066 74.500 -21.681 74.415 -20.500 74.266 -19.654 74.500 -19.187 74.637 -19.769 74.723 -20.764 75.025 -21.093 75.077 -21.841 75.239 -20.868 75.459 -21.890 75.541 -21.901 75.368 -20.945 75.247 -19.791 75.527 -19.412 75.788 -19.610 75.945 -20.560 75.986 -21.253 76.176 -20.022 76.255 -21.121 76.516 -22.104 76.739 -22.121 76.874 -21.093 76.948 -20.093 76.821 -18.720 77.016 -18.154 77.291 -18.736 77.360 -19.819 77.519 -20.549 77.687 -20.060 77.714 -19.363 77.904 -20.890 77.750 -21.670 78.154 -21.473 78.453 -21.203 78.714 -21.077 78.951 -20.126 79.234 -19.495 79.547 -19.659 79.758 -18.841 79.942 -17.720 80.118 -18.286 79.997 -19.824 79.920 -20.379 80.242 -19.511 80.231 -17.681 80.401 -16.522 80.585 -17.110 80.574 -18.852 80.610 -19.962 80.750 -17.407 80.824 -15.604 81.066 -14.725 81.288 -13.505 81.558 -12.511 81.797 -13.484 81.918 -15.363 81.810 -17.275 81.547 -18.335 81.547 -20.308 81.302 -21.670 81.052 -22.632 80.810 -23.549 80.703 -24.115 81.077 -23.286 81.341 -22.610 81.624 -22.071 81.918 -22.055 82.041 -23.357 81.783 -24.302 81.585 -25.714 81.519 -26.896 81.904 -25.390 82.014 -27.143 81.945 -29.330 81.863 -31.066 81.824 -32.324 82.151 -30.396 82.179 -27.885 82.151 -25.747 82.264 -23.819 82.423 -22.143 82.673 -21.791 82.824 -23.703 82.901 -25.181 83.104 -26.016 83.088 -28.324 83.071 -30.615 82.962 -32.577 82.915 -34.280 83.088 -32.203 83.151 -29.918 83.151 -27.418 83.330 -26.203 83.481 -28.610 83.582 -30.995 83.566 -33.758 83.497 -36.170 83.431 -37.643 83.266 -38.566 83.058 -38.027 82.885 -39.286 83.151 -41.742 83.184 -43.489 83.011 -45.209 82.885 -45.709 82.838 -43.407 82.777 -41.159 82.582 -39.912 82.495 -40.225 82.657 -41.863 82.777 -44.368 82.657 -45.203 82.407 -43.940 82.236 -43.659 81.918 -44.577 81.849 -45.379 82.096 -46.643 82.294 -48.165 82.495 -49.769 82.379 -50.918 82.096 -50.291 81.863 -50.313 81.717 -50.374 81.931 -52.566 81.717 -53.593 82.195 -53.791 82.264 -55.280 82.179 -56.967 82.000 -58.868 81.703 -58.093 81.467 -56.995 81.442 -57.077 81.662 -58.385 81.890 -59.643 81.755 -61.225 81.456 -61.022 81.165 -61.648 81.091 -63.264 80.956 -63.577 80.750 -65.396 80.552 -66.538 80.277 -67.341 80.063 -66.418 80.107 -64.786 80.118 -64.341 79.835 -65.005 79.547 -64.934 79.275 -65.533 79.124 -66.643 79.071 -67.995 78.874 -69.148 78.695 -70.489 78.588 -71.731 78.379 -72.643 78.126 -72.681 77.876 -71.643 77.805 -70.632 77.698 -70.066 77.500 -69.654 77.555 -68.484 77.615 -67.176 77.599 -66.357 77.352 -66.555 77.368 -68.005 77.239 -68.462 77.170 -66.846 77.146 -66.725 77.179 -68.137 77.214 -69.440 77.179 -70.731 76.948 -71.044 76.854 -70.264 76.874 -69.830 76.673 -68.956 76.591 -68.434 76.338 -69.297 76.113 -68.407 75.992 -67.214 76.033 -66.835 76.192 -66.654 76.176 -65.775 76.129 -65.060 76.239 -64.176 76.288 -62.907 76.209 -61.813 76.071 -60.714 75.898 -59.747 75.736 -58.868 75.505 -58.335 75.308 -58.335 75.030 -57.819 74.783 -57.000 74.508 -56.462 74.302 -56.489 74.148 -56.599 73.904 -55.901 73.659 -55.813 73.343 -55.291 73.077 -55.258 72.786 -54.709 72.536 -54.824 72.409 -55.231 72.269 -54.956 72.027 -54.945 71.720 -55.593 71.442 -55.286 71.371 -54.500 71.563 -53.962 71.745 -53.714 72.063 -53.654 72.220 -53.703 71.854 -53.060 71.654 -52.533 71.610 -52.077 71.412 -52.527 71.418 -51.846 71.245 -52.115 71.228 -51.852 71.115 -51.824 71.008 -51.407 70.753 -51.011 70.522 -50.879 70.363 -50.951 70.486 -51.742 70.676 -52.423 70.764 -53.258 70.791 -54.143 70.602 -54.418 70.390 -53.813 70.294 -53.000 70.096 -52.346 70.005 -51.555 70.014 -50.918 69.923 -50.379 69.679 -50.599 69.462 -50.665 69.201 -50.566 69.030 -50.610 68.819 -51.011 68.602 -51.148 68.549 -51.973 68.467 -52.604 68.280 -52.852 68.239 -51.923 68.374 -51.363 68.357 -51.071 68.099 -50.995 67.951 -50.588 68.052 -51.571 68.121 -52.286 68.140 -52.775 68.115 -53.148 67.942 -52.918 67.750 -53.538 67.577 -53.445 67.783 -52.758 67.901 -52.071 67.841 -51.582 67.846 -50.780 67.799 -50.599 67.679 -50.918 67.599 -50.385 67.582 -50.989 67.659 -51.670 67.739 -52.412 67.662 -52.962 67.442 -53.670 67.269 -53.549 67.330 -52.764 67.374 -52.049 67.335 -51.357 67.187 -50.808 67.170 -50.709 67.239 -51.407 67.343 -52.049 67.288 -52.769 67.212 -53.495 67.069 -53.670 66.940 -53.275 66.868 -52.549 66.690 -53.005 66.525 -52.912 66.429 -53.599 66.195 -53.390 66.343 -52.692 66.538 -52.159 66.750 -51.670 66.931 -51.093 67.025 -50.429 66.984 -50.363 66.863 -50.819 66.712 -51.577 66.500 -52.093 66.316 -52.659 66.126 -53.181 65.962 -53.176 65.956 -52.500 65.956 -52.093 65.791 -53.033 65.662 -52.775 65.514 -52.462 65.643 -51.863 65.777 -51.209 65.728 -50.896 65.613 -51.802 65.418 -52.275 65.239 -52.275 64.909 -52.110 64.887 -51.841 64.923 -51.571 64.621 -52.071 64.343 -51.846 64.670 -51.324 64.788 -50.896 65.077 -50.797 64.755 -50.187 64.475 -49.890 64.409 -49.879 64.654 -50.489 64.533 -50.643 64.409 -50.566 64.223 -51.159 64.146 -51.484 64.212 -50.720 64.198 -50.368 64.058 -51.258 63.915 -51.379 63.843 -51.187 63.640 -51.412 63.613 -51.011 63.585 -50.863 63.409 -50.995 63.360 -50.720 63.206 -50.835 63.080 -50.374 62.904 -50.203 62.970 -49.967 62.764 -50.126 62.420 -50.170 62.280 -49.736 62.137 -49.495 62.022 -49.374 62.052 -49.104 61.843 -49.220 61.885 -48.951 61.615 -48.978 61.547 -48.484 61.503 -48.516 61.343 -48.654 61.206 -48.297 61.168 -48.000 60.978 -48.038 60.832 -47.962 60.885 -47.522 60.904 -46.830 61.041 -46.280 61.129 -45.786 61.060 -45.429 60.841 -45.846 60.830 -45.489 60.613 -45.637 60.613 -45.308 60.544 -45.192 60.536 -44.846 60.242 -44.978 60.374 -44.648 60.082 -44.819 60.250 -44.121 60.132 -43.500 60.220 -43.176 60.412 -43.473 60.588 -43.797 60.552 -43.066 60.695 -43.000 60.865 -43.165 61.033 -42.852 61.115 -43.198 61.165 -42.885 61.201 -42.879 61.266 -42.813 61.327 -42.868 61.475 -42.604 61.582 -42.681 61.706 -42.500 61.766 -42.582 61.959 -42.335 62.245 -42.363 62.473 -42.544 62.747 -42.703 62.857 -42.181 62.956 -41.791 63.126 -41.852 63.266 -41.610 63.437 -41.593 63.445 -41.368 63.486 -41.115 63.613 -40.901 63.750 -41.209 63.821 -40.615 64.080 -40.813 64.286 -41.297 64.426 -40.555 64.775 -40.819 65.030 -40.956 65.063 -40.341 65.212 -39.934 65.519 -39.907 65.626 -39.341 65.629 -38.648 65.761 -38.242 65.995 -38.159 66.280 -37.912 66.357 -37.582 66.225 -37.412 65.956 -37.703 65.901 -37.088 65.989 -36.379 66.063 -35.885 ; #5 1 68.310 -67.115 68.305 -67.544 68.409 -67.187 68.486 -67.698 68.585 -68.522 68.648 -68.368 68.791 -68.918 68.832 -68.247 68.997 -68.121 69.115 -68.786 69.223 -68.451 69.305 -68.863 69.319 -68.566 69.217 -67.813 69.165 -67.005 69.346 -66.863 69.467 -67.577 69.533 -68.346 69.544 -69.505 69.571 -69.121 69.673 -68.330 69.758 -67.434 69.984 -67.313 70.242 -67.830 70.135 -68.335 69.945 -68.835 69.742 -69.714 69.819 -69.626 70.096 -68.912 70.146 -69.473 69.929 -70.077 69.995 -70.071 70.198 -69.610 70.363 -68.742 70.538 -68.445 70.739 -69.192 70.676 -70.115 70.643 -70.835 70.225 -71.308 70.396 -71.242 70.442 -71.632 70.527 -71.626 70.690 -70.956 70.986 -70.643 70.945 -71.214 70.769 -72.302 71.003 -72.137 71.151 -71.396 71.437 -71.418 71.599 -72.198 71.489 -72.769 71.173 -73.379 71.423 -73.610 71.327 -74.038 71.382 -74.126 71.670 -73.769 71.659 -74.203 71.352 -74.813 71.538 -74.945 71.695 -75.027 71.890 -74.275 72.096 -74.736 71.835 -75.687 72.014 -75.505 71.970 -76.143 72.027 -76.093 72.162 -75.280 72.409 -75.143 72.547 -75.951 72.690 -76.736 72.720 -77.676 72.536 -78.429 72.206 -77.599 72.264 -78.451 71.898 -78.104 72.003 -78.736 72.181 -79.011 72.338 -79.593 72.250 -79.973 72.088 -80.555 72.327 -80.879 72.492 -80.813 72.753 -80.412 73.038 -80.610 73.283 -81.082 73.571 -81.308 73.725 -82.000 73.679 -83.011 73.448 -83.802 73.330 -84.648 73.091 -84.330 73.091 -85.159 72.882 -84.604 72.929 -85.264 72.714 -85.676 72.445 -85.225 72.190 -84.533 72.225 -85.148 72.044 -85.742 71.794 -85.478 71.624 -84.786 71.352 -84.709 71.044 -84.808 71.107 -85.044 71.044 -86.269 71.151 -85.940 71.291 -85.148 71.533 -85.489 71.775 -86.060 72.044 -86.396 72.332 -86.346 72.604 -86.555 72.876 -86.599 73.137 -86.231 73.409 -85.797 73.632 -85.115 73.808 -85.324 73.843 -86.357 73.766 -87.357 73.591 -88.176 73.330 -88.791 73.096 -89.198 72.797 -89.412 72.536 -89.747 72.250 -89.824 72.008 -89.951 71.714 -89.923 71.418 -89.907 71.280 -89.148 71.239 -88.209 71.033 -87.456 70.978 -88.302 71.019 -89.236 70.764 -89.236 70.511 -88.764 70.327 -88.077 70.327 -87.352 70.412 -86.720 70.357 -86.500 70.102 -86.198 70.052 -85.522 70.036 -84.687 69.967 -83.802 69.962 -82.978 69.852 -82.099 70.165 -82.516 70.074 -82.044 69.835 -81.170 70.030 -81.412 70.074 -81.038 69.989 -80.192 69.879 -79.484 69.989 -78.747 70.475 -79.099 70.332 -78.560 70.198 -77.945 69.879 -77.670 69.846 -77.396 69.791 -77.000 69.624 -76.610 69.401 -76.209 69.165 -75.681 69.025 -76.330 68.769 -76.456 68.907 -75.643 68.967 -74.940 68.780 -74.703 68.607 -74.082 68.560 -73.797 68.316 -73.489 68.176 -73.038 67.879 -72.802 67.604 -72.533 67.319 -72.324 67.088 -72.549 66.832 -72.918 66.709 -72.379 66.654 -71.577 66.945 -71.077 66.813 -70.549 66.684 -69.973 66.492 -69.440 66.247 -69.610 66.247 -70.407 66.069 -71.060 66.245 -71.165 66.516 -71.374 66.654 -72.027 66.692 -72.753 66.615 -73.368 66.396 -73.841 66.173 -74.346 65.904 -74.082 65.588 -73.643 65.486 -74.154 65.376 -74.808 65.286 -75.604 65.104 -75.423 64.874 -75.385 64.923 -75.516 65.170 -75.709 65.321 -76.280 65.431 -77.093 65.258 -77.434 65.044 -77.923 64.775 -78.159 64.497 -78.027 64.330 -77.566 64.245 -76.973 64.299 -76.440 64.453 -75.830 64.511 -75.412 64.467 -74.698 64.775 -74.769 64.775 -74.588 64.547 -74.099 64.585 -73.473 64.387 -73.324 64.154 -72.973 63.918 -72.544 63.758 -72.082 63.640 -71.516 63.426 -71.813 63.220 -71.681 63.055 -71.077 62.890 -70.692 62.769 -69.967 62.668 -69.484 62.440 -69.132 62.288 -68.632 62.203 -67.989 62.121 -67.407 62.003 -66.841 61.885 -66.236 62.099 -66.066 62.330 -66.313 62.585 -66.632 62.761 -67.077 62.978 -67.566 63.129 -67.984 63.368 -68.401 63.637 -68.830 63.698 -68.467 63.486 -67.929 63.624 -67.824 63.607 -67.681 63.360 -67.203 63.151 -66.791 63.201 -66.648 63.201 -66.582 63.019 -66.137 62.907 -65.626 62.698 -65.236 62.769 -65.060 62.962 -64.934 63.231 -64.984 63.613 -65.115 63.390 -64.681 63.613 -64.555 63.893 -64.808 64.066 -65.110 64.357 -65.324 64.549 -65.566 64.764 -65.940 64.912 -66.571 65.126 -66.923 65.409 -67.253 65.593 -67.692 65.747 -67.973 66.088 -68.330 66.030 -68.016 65.915 -67.549 66.063 -67.313 66.387 -67.802 66.352 -67.445 66.486 -67.390 66.555 -67.000 66.330 -66.533 66.239 -65.824 66.077 -65.813 65.997 -65.412 66.234 -64.676 66.082 -64.786 65.871 -65.324 65.648 -65.104 65.519 -64.989 65.316 -64.621 65.162 -64.165 65.008 -63.736 65.049 -63.440 65.335 -63.434 65.676 -63.478 65.657 -62.989 65.761 -62.670 66.016 -62.692 66.044 -62.225 66.291 -62.577 66.349 -61.885 66.516 -61.841 66.651 -61.593 66.912 -61.863 66.896 -62.379 66.775 -62.797 66.857 -62.890 66.824 -63.440 66.896 -63.489 67.214 -63.159 67.137 -63.626 67.102 -64.462 67.245 -64.445 67.409 -64.154 67.690 -64.357 67.745 -64.896 67.907 -65.011 67.769 -65.396 67.860 -65.516 67.810 -65.885 68.003 -65.945 67.912 -66.247 68.014 -66.538 68.187 -67.159 ; #6 1 -9.201 141.110 -9.173 141.379 -9.220 141.670 -9.203 141.962 -9.190 142.253 -9.291 142.533 -9.253 142.802 -9.104 143.055 -8.984 143.335 -8.709 143.341 -8.503 143.137 -8.390 142.863 -8.341 142.582 -8.236 142.280 -8.236 142.368 -8.294 142.626 -8.310 142.912 -8.286 143.198 -8.217 143.533 -7.986 143.467 -7.964 143.500 -7.964 143.852 -7.571 143.747 -7.635 143.857 -7.761 144.126 -7.687 144.368 -7.602 144.555 -7.679 144.835 -7.813 145.082 -7.898 145.357 -7.945 145.659 -8.014 145.868 -8.170 146.121 -8.415 146.280 -8.657 146.456 -8.890 146.577 -9.082 146.863 -9.299 146.951 -9.486 147.154 -9.648 147.390 -9.901 147.549 -10.066 147.802 -10.124 148.077 -10.165 148.352 -10.173 148.681 -10.253 148.940 -10.275 149.231 -10.341 149.505 -10.451 149.907 -10.596 150.000 -10.676 150.275 -10.615 150.560 -10.407 150.489 -10.294 150.725 -10.245 150.632 -10.184 150.352 -10.088 150.077 -9.959 149.830 -9.734 149.918 -9.618 149.769 -9.585 149.478 -9.415 149.231 -9.074 149.253 -9.058 148.945 -9.074 148.648 -8.852 148.495 -8.624 148.341 -8.393 148.214 -8.107 148.115 -7.964 147.868 -7.799 147.637 -7.602 147.445 -7.431 147.209 -7.132 147.088 -6.868 146.967 -6.734 147.170 -6.747 147.467 -6.690 147.780 -6.437 147.841 -6.209 147.687 -6.000 147.484 -5.953 147.203 -5.871 146.929 -5.750 146.670 -5.607 146.412 -5.533 146.132 -5.462 145.830 -5.195 145.780 -4.901 145.780 -4.679 145.604 -4.467 145.412 -4.371 145.148 -4.187 144.923 -4.030 144.692 -3.854 144.478 -3.827 144.187 -3.725 143.923 -3.566 143.681 -3.418 143.434 -3.365 143.143 -3.308 142.863 -3.223 142.582 -3.124 142.313 -3.014 142.049 -2.901 141.780 -2.775 141.516 -2.657 141.258 -2.607 140.978 -2.549 140.714 -2.431 140.434 -2.371 140.165 -2.368 139.879 -2.272 139.610 -2.146 139.346 -2.022 139.082 -1.912 138.819 -1.769 138.566 -1.681 138.291 -1.566 138.027 -1.503 137.764 -1.621 137.495 -1.758 137.236 -1.975 137.176 -2.132 137.033 -2.231 136.758 -2.231 136.467 -2.440 136.302 -2.659 136.121 -2.871 135.945 -3.088 135.769 -3.283 135.555 -3.374 135.297 -3.310 135.000 -3.115 134.846 -2.915 134.742 -2.574 134.621 -2.714 134.484 -2.613 134.357 -2.374 134.203 -2.096 134.137 -1.808 134.115 -1.555 134.192 -1.275 134.220 -0.970 134.093 -0.777 134.022 -0.742 133.747 -0.728 133.456 -0.574 133.198 -0.459 132.934 -0.371 132.659 -0.371 132.368 -0.484 132.104 -0.665 131.879 -0.755 131.582 -0.838 131.308 -1.113 131.225 -1.319 131.027 -1.470 131.099 -1.451 131.357 -1.527 131.681 -1.610 131.907 -1.852 131.967 -2.074 132.099 -2.239 132.363 -2.253 132.654 -2.266 132.945 -2.223 133.236 -2.225 133.538 -2.148 133.808 -2.286 133.907 -2.544 133.769 -2.580 133.473 -2.511 133.341 -2.470 133.082 -2.676 132.879 -2.764 132.643 -2.706 132.379 -2.794 132.055 -2.945 132.192 -3.055 132.467 -3.269 132.676 -3.456 132.857 -3.690 132.791 -3.978 132.841 -4.082 133.071 -3.984 133.330 -3.739 133.445 -3.459 133.560 -3.088 133.786 -3.228 133.720 -3.596 133.736 -3.772 133.945 -3.896 134.225 -3.967 134.500 -3.937 134.830 -4.036 134.731 -4.275 134.879 -4.420 135.137 -4.448 135.418 -4.489 135.709 -4.549 135.989 -4.668 136.253 -4.769 136.522 -4.890 136.791 -4.937 137.060 -5.025 137.313 -5.176 137.593 -5.330 137.835 -5.511 138.049 -5.769 138.253 -6.036 138.324 -6.305 138.423 -6.604 138.681 -6.766 138.769 -6.907 139.060 -6.907 139.022 -6.926 138.687 -7.187 139.033 -7.203 138.797 -7.308 138.813 -7.536 139.016 -7.813 138.989 -8.151 138.907 -8.055 139.181 -8.132 139.291 -8.157 139.566 -8.025 140.000 -8.239 140.038 -8.440 140.275 -8.635 140.489 -8.860 140.670 -9.055 140.885 ; #7 1 4.316 117.670 4.255 117.995 4.327 118.286 4.478 118.527 4.717 118.264 4.951 118.236 4.970 118.511 4.984 118.797 5.077 119.077 5.277 119.258 5.420 119.066 5.489 118.835 5.629 118.588 5.799 118.341 5.725 118.055 5.882 118.044 5.978 117.885 5.901 117.626 5.962 117.599 6.231 117.670 6.486 117.654 6.604 117.407 6.863 117.242 6.915 117.066 6.742 116.857 6.912 116.709 6.624 116.577 6.401 116.385 6.223 116.220 5.973 116.088 5.712 115.923 5.555 115.670 5.470 115.467 5.250 115.478 5.033 115.500 4.909 115.231 4.948 115.016 4.874 114.731 4.695 114.500 4.596 114.231 4.500 113.995 4.206 113.890 3.978 113.709 3.783 113.489 3.555 113.319 3.330 113.132 3.135 112.934 3.049 112.659 2.981 112.379 2.909 112.099 2.868 111.813 2.764 111.549 2.511 111.445 2.368 111.324 2.135 111.253 1.838 111.132 1.602 111.115 1.407 111.176 1.522 110.736 1.670 110.473 1.720 110.247 1.725 109.929 1.904 109.698 2.000 109.538 1.819 109.319 1.588 109.148 1.299 109.110 1.074 108.956 0.777 108.890 0.475 108.929 0.261 109.038 0.022 109.209 -0.258 109.126 -0.536 109.187 -0.692 109.368 -0.879 109.418 -0.945 109.698 -1.154 109.907 -1.401 110.049 -1.703 109.989 -1.912 110.016 -2.179 110.115 -2.497 110.203 -2.739 110.214 -2.951 110.330 -2.981 110.637 -2.986 110.868 -3.008 111.159 -2.953 111.440 -2.912 111.670 -2.871 111.758 -3.179 111.824 -3.481 111.918 -3.335 112.247 -3.409 112.544 -3.297 112.808 -3.104 112.989 -3.041 113.121 -3.217 113.357 -3.275 113.615 -3.462 113.758 -3.341 114.022 -3.310 114.231 -3.451 114.473 -3.706 114.593 -4.000 114.615 -4.143 114.742 -4.008 115.016 -3.896 115.280 -3.791 115.555 -3.662 115.819 -3.481 116.011 -3.231 116.159 -3.019 116.165 -2.890 116.264 -2.563 116.390 -2.343 116.577 -2.184 116.467 -2.066 116.390 -1.753 116.368 -1.484 116.582 -1.247 116.753 -1.168 116.802 -1.132 117.060 -0.893 117.269 -0.772 117.516 -0.495 117.538 -0.217 117.467 0.088 117.495 0.363 117.566 0.624 117.692 0.805 117.901 0.951 117.978 1.025 117.995 0.854 118.264 0.827 118.538 0.846 118.824 1.047 118.923 1.253 118.703 1.431 118.456 1.596 118.220 1.777 118.000 2.030 117.852 2.291 118.038 2.547 117.890 2.813 117.709 3.003 117.593 3.245 117.368 3.467 117.319 3.626 117.214 3.679 117.560 3.780 117.742 3.970 117.566 4.137 117.456 ; #8 2 82.582 -76.181 82.824 -77.104 82.901 -78.769 82.764 -79.555 82.717 -80.093 82.657 -81.390 82.451 -82.220 82.179 -81.352 81.945 -79.780 81.959 -80.181 82.137 -82.335 82.223 -83.269 82.423 -84.775 82.308 -85.863 81.986 -85.368 82.000 -86.819 82.027 -88.582 81.742 -90.665 81.533 -90.247 81.519 -88.500 81.418 -89.297 81.176 -89.753 81.052 -88.588 81.190 -85.907 81.041 -86.516 80.931 -88.753 80.681 -87.923 80.810 -86.747 81.027 -85.599 81.140 -83.308 81.077 -83.764 80.967 -85.467 80.703 -86.495 80.552 -85.714 80.681 -83.747 80.692 -82.615 80.632 -81.220 80.810 -79.786 81.102 -79.137 81.352 -77.599 81.264 -77.835 80.992 -78.725 80.896 -77.313 80.824 -77.621 80.692 -79.297 80.599 -78.808 80.552 -79.055 80.470 -80.665 80.368 -82.495 80.154 -82.610 79.909 -81.670 79.684 -80.593 79.610 -81.038 79.747 -81.929 79.997 -82.769 80.220 -83.868 80.299 -85.544 80.176 -86.571 79.920 -86.049 79.684 -85.538 79.442 -84.687 79.124 -84.077 78.962 -84.005 78.942 -82.038 78.734 -82.615 78.813 -83.736 78.882 -85.203 78.755 -86.626 78.511 -87.209 78.190 -87.319 78.190 -86.049 78.407 -84.918 78.275 -84.665 78.107 -84.720 77.876 -85.071 77.635 -84.775 77.555 -83.742 77.931 -82.764 77.797 -82.769 77.500 -83.473 77.360 -84.176 77.412 -85.396 77.643 -85.929 77.860 -86.791 77.786 -88.060 77.511 -87.802 77.283 -87.082 77.146 -87.313 77.058 -88.544 76.821 -89.396 76.525 -89.379 76.582 -88.632 76.467 -87.885 76.484 -86.670 76.338 -85.720 76.418 -84.753 76.566 -83.681 76.591 -82.473 76.508 -81.527 76.247 -80.868 76.264 -79.885 76.467 -78.830 76.615 -78.005 76.890 -77.874 76.915 -78.780 77.110 -79.198 77.179 -80.225 77.231 -81.604 77.456 -81.676 77.440 -81.236 77.299 -80.110 77.335 -78.786 77.563 -77.967 77.887 -78.044 77.959 -76.566 78.135 -76.209 78.255 -75.577 78.473 -76.000 78.549 -75.225 78.813 -75.011 78.942 -76.275 78.893 -77.874 78.992 -78.187 79.124 -77.352 79.173 -76.423 79.093 -74.907 79.234 -75.297 79.297 -77.247 79.431 -76.736 79.431 -75.247 79.503 -73.753 79.791 -73.978 79.791 -73.192 79.780 -71.511 80.096 -71.544 80.368 -70.379 80.481 -69.214 80.728 -68.352 80.942 -67.242 81.176 -66.071 81.404 -64.736 81.495 -65.588 81.365 -67.302 81.176 -69.467 81.264 -69.099 81.442 -67.302 81.599 -68.440 81.599 -67.824 81.676 -65.769 81.797 -64.115 82.000 -62.451 82.236 -61.341 82.481 -62.456 82.687 -63.407 82.824 -64.918 82.703 -67.467 82.824 -66.951 82.962 -67.934 83.041 -70.390 83.025 -71.824 82.854 -73.104 82.948 -74.110 83.025 -76.176 82.871 -76.670 82.599 -75.901 ; #9 -1 43.030 -86.247 43.217 -86.313 43.470 -86.467 43.747 -86.484 44.041 -86.473 44.313 -86.313 44.604 -86.247 44.846 -86.071 45.088 -85.709 44.904 -85.566 44.989 -85.407 45.275 -85.330 45.467 -85.044 45.750 -84.879 45.692 -84.473 45.555 -84.115 45.423 -83.758 45.266 -83.423 45.011 -83.368 44.701 -83.302 44.404 -83.346 44.179 -83.549 43.956 -83.830 43.690 -83.863 43.698 -83.533 43.926 -83.308 44.030 -82.912 43.824 -82.654 43.538 -82.577 43.250 -82.511 43.060 -82.302 43.225 -81.945 43.451 -81.720 43.745 -81.720 44.041 -81.714 44.313 -81.571 44.549 -81.335 44.838 -81.319 45.151 -81.566 45.179 -81.330 44.918 -81.088 44.714 -80.918 44.635 -80.560 44.522 -80.143 44.791 -79.874 44.964 -79.901 45.250 -80.082 45.464 -80.346 45.670 -80.571 45.907 -80.808 45.978 -81.220 46.038 -81.626 46.118 -82.044 46.179 -82.467 46.187 -82.852 46.212 -83.258 46.277 -83.670 46.387 -84.038 46.538 -84.412 46.786 -84.467 46.992 -84.665 47.305 -84.654 47.555 -84.923 47.863 -84.923 47.951 -85.269 47.948 -85.698 48.121 -86.016 48.387 -86.198 48.681 -86.363 48.769 -86.725 48.783 -87.159 48.871 -87.599 48.970 -88.077 48.659 -88.363 48.486 -88.753 48.486 -89.088 48.239 -89.269 48.033 -89.527 47.871 -89.901 47.761 -90.297 47.646 -90.692 47.467 -91.033 47.250 -91.324 47.052 -91.632 46.824 -91.989 46.717 -91.775 46.819 -91.346 46.920 -90.962 46.725 -90.868 46.637 -90.676 46.629 -90.258 46.772 -89.890 46.852 -89.489 46.978 -89.110 47.148 -88.703 46.909 -88.473 46.896 -88.253 46.893 -87.846 46.723 -87.549 46.530 -87.242 46.475 -86.797 46.555 -86.440 46.681 -86.066 46.692 -85.637 46.753 -85.143 46.527 -84.951 46.470 -84.533 46.341 -84.236 46.080 -84.044 45.992 -84.269 45.962 -84.659 45.992 -85.000 46.088 -85.401 45.975 -85.797 45.934 -86.214 45.723 -86.522 45.755 -86.621 45.805 -86.863 45.769 -87.077 45.519 -87.280 45.269 -87.484 45.016 -87.681 44.684 -87.945 44.769 -87.527 44.467 -87.495 44.181 -87.560 43.907 -87.714 43.624 -87.747 43.352 -87.868 43.069 -87.879 42.783 -87.797 42.492 -87.808 42.203 -87.786 41.942 -87.637 41.687 -87.451 41.662 -87.093 41.808 -86.758 42.041 -86.538 42.297 -86.352 42.574 -86.247 42.860 -86.220 ; #10 1 -5.591 120.115 -5.547 120.363 -5.277 120.335 -5.005 120.297 -4.742 120.396 -4.448 120.385 -4.162 120.368 -3.876 120.379 -3.602 120.418 -3.299 120.390 -3.027 120.258 -2.813 120.445 -2.657 120.681 -2.670 120.962 -2.865 121.049 -3.187 121.033 -3.462 120.901 -3.701 121.066 -3.885 121.275 -4.049 121.544 -4.288 121.549 -4.593 121.495 -4.797 121.676 -4.802 122.005 -4.525 122.148 -4.440 122.429 -4.409 122.720 -4.192 122.863 -4.041 122.659 -3.841 122.533 -3.635 122.280 -3.349 122.330 -3.124 122.385 -2.876 122.231 -2.657 122.022 -2.398 121.879 -2.198 121.681 -1.918 121.401 -1.901 121.626 -1.706 121.857 -1.604 122.132 -1.467 122.385 -1.253 122.582 -1.030 122.758 -0.887 122.989 -0.975 123.264 -0.739 123.418 -0.574 123.181 -0.676 122.868 -0.775 122.670 -0.761 122.390 -0.863 122.126 -0.948 121.857 -0.865 121.582 -1.060 121.335 -1.294 121.165 -1.396 120.940 -1.321 120.659 -1.052 120.527 -0.896 120.297 -0.676 120.104 -0.398 120.033 -0.110 120.033 0.159 120.132 0.396 120.297 0.522 120.549 0.459 120.830 0.440 121.110 0.481 121.412 0.503 121.676 0.448 121.951 0.481 122.231 0.492 122.544 0.486 122.797 0.453 123.093 0.310 123.346 0.294 123.637 0.330 123.929 0.379 124.209 0.497 124.478 0.725 124.626 0.937 124.830 1.157 125.016 1.423 125.165 1.665 125.099 1.577 124.868 1.360 124.626 1.187 124.478 1.011 124.253 0.876 123.984 0.854 123.703 0.901 123.423 0.942 123.154 0.874 122.863 0.962 122.588 1.016 122.302 1.055 122.016 1.074 121.736 1.184 121.467 1.264 121.236 1.327 120.934 1.118 120.797 0.885 120.621 0.893 120.346 0.780 120.148 0.549 119.995 0.291 119.835 -0.025 119.764 -0.272 119.780 -0.687 119.791 -0.802 119.599 -1.063 119.445 -1.313 119.319 -1.602 119.313 -1.904 119.319 -2.157 119.165 -2.437 119.104 -2.637 118.885 -2.857 118.819 -3.135 118.813 -3.478 118.912 -3.484 119.176 -3.527 119.451 -3.816 119.505 -4.063 119.610 -4.379 119.610 -4.662 119.538 -4.948 119.495 -5.214 119.385 -5.516 119.434 -5.659 119.643 -5.602 119.934 ; #11 1 5.525 95.220 5.308 95.242 5.044 95.335 4.775 95.473 4.571 95.665 4.360 95.879 4.170 96.099 3.975 96.308 3.772 96.516 3.709 96.808 3.500 97.011 3.266 97.187 3.027 97.346 2.843 97.571 2.563 97.648 2.305 97.753 2.223 98.016 2.060 98.275 1.920 98.522 1.681 98.747 1.420 98.791 1.151 98.896 0.874 98.984 0.602 99.077 0.308 99.159 0.184 99.407 0.044 99.659 -0.203 99.786 -0.429 99.956 -0.648 100.143 -0.879 100.324 -1.159 100.407 -1.401 100.571 -1.659 100.687 -1.909 100.841 -2.192 100.868 -2.456 101.005 -2.657 101.209 -2.868 101.390 -3.118 101.538 -3.324 101.736 -3.492 101.973 -3.670 102.209 -3.937 102.313 -4.140 102.516 -4.313 102.747 -4.500 102.967 -4.662 103.209 -4.841 103.423 -4.975 103.692 -5.168 103.907 -5.393 104.071 -5.602 104.291 -5.852 104.577 -5.604 104.588 -5.574 104.758 -5.742 105.077 -5.577 105.225 -5.599 105.423 -5.802 105.665 -5.637 105.819 -5.349 105.841 -5.063 105.874 -4.775 105.879 -4.486 105.885 -4.206 105.824 -3.909 105.912 -3.646 105.841 -3.363 105.945 -3.126 106.060 -2.926 105.885 -2.695 105.725 -2.440 105.566 -2.365 105.264 -2.341 104.967 -2.588 104.670 -2.398 104.698 -2.124 104.841 -1.959 104.610 -1.758 104.511 -1.470 104.456 -1.187 104.407 -1.049 104.236 -1.019 103.923 -0.951 103.676 -0.761 103.440 -0.505 103.456 -0.308 103.412 -0.173 103.456 -0.022 103.681 0.236 103.742 0.412 103.538 0.489 103.269 0.338 103.016 0.214 102.610 0.277 102.747 0.442 103.016 0.681 102.918 0.736 102.632 0.849 102.379 1.074 102.209 1.343 102.115 1.538 101.896 1.662 101.648 1.772 101.396 2.041 101.275 2.239 101.055 2.041 100.874 2.104 100.681 2.264 100.451 2.585 100.231 2.670 100.022 2.937 99.945 3.148 99.747 3.302 99.505 3.484 99.280 3.635 99.038 3.766 98.769 3.970 98.571 4.113 98.286 4.297 98.258 4.533 98.099 4.761 97.962 4.978 97.786 5.181 97.560 5.184 97.275 5.258 97.000 5.242 96.714 5.220 96.429 5.286 96.143 5.451 95.912 5.599 95.665 5.613 95.379 ; #12 -1 39.223 49.247 39.052 49.044 38.764 48.863 38.459 48.879 38.170 48.890 37.887 48.962 37.637 49.126 37.497 49.445 37.462 49.841 37.368 50.154 37.129 50.368 36.948 50.648 36.797 50.956 36.698 51.291 36.632 51.643 36.591 52.000 36.665 52.352 36.728 52.703 36.805 53.055 36.874 53.407 36.904 53.769 36.909 53.879 37.341 53.912 37.626 53.846 37.918 53.808 38.206 53.852 38.497 53.841 38.777 53.918 39.025 53.819 39.217 53.626 39.299 53.231 39.503 53.165 39.555 53.330 39.602 53.560 39.907 53.440 39.893 52.989 40.102 52.764 40.385 52.720 40.670 52.835 40.904 53.016 40.794 53.423 40.745 53.681 40.662 53.956 40.764 54.302 40.904 54.626 41.140 54.648 41.335 54.324 41.544 54.060 41.830 53.962 42.091 53.797 42.102 53.385 42.016 53.027 41.728 52.846 41.462 52.857 41.258 52.797 41.665 52.533 41.942 52.462 42.209 52.489 42.473 52.648 42.709 52.626 42.843 52.214 42.923 51.846 43.148 51.582 43.266 51.302 43.571 51.220 43.819 51.022 44.080 50.868 44.269 50.610 44.396 50.269 44.618 50.374 44.610 50.808 44.519 51.198 44.599 51.396 44.904 51.027 45.126 51.258 45.354 51.522 45.398 51.901 45.398 52.335 45.352 52.736 45.401 53.027 45.701 52.819 45.953 53.033 46.231 53.137 46.519 53.082 46.791 53.104 46.945 52.780 46.907 52.341 46.879 51.989 46.997 51.648 47.088 51.242 46.984 50.824 46.857 50.484 46.709 50.143 46.549 49.725 46.492 49.357 46.264 49.148 46.093 48.808 45.893 48.593 45.742 48.143 45.670 47.687 45.585 47.478 45.245 47.363 44.978 47.176 44.808 46.978 44.549 46.714 44.352 46.951 44.157 47.236 43.868 47.440 43.681 47.511 43.305 47.516 43.019 47.511 42.769 47.709 42.527 47.896 42.291 48.126 42.041 48.324 41.838 48.577 41.615 48.830 41.382 49.049 41.110 49.181 40.871 49.396 40.643 49.610 40.560 50.000 40.404 50.308 40.308 50.236 40.305 49.835 40.115 49.500 39.835 49.418 39.547 49.324 39.330 49.385 ; #13 1 -21.997 43.275 -22.250 43.275 -22.560 43.313 -22.841 43.396 -23.074 43.582 -23.349 43.681 -23.593 43.725 -23.890 43.681 -24.179 43.692 -24.442 43.780 -24.676 43.956 -24.953 44.071 -25.168 44.352 -25.272 44.566 -25.354 44.874 -25.530 45.143 -25.555 45.445 -25.445 45.736 -25.294 46.011 -25.187 46.308 -25.157 46.632 -25.055 46.929 -24.879 47.148 -24.591 47.264 -24.313 47.368 -24.047 47.484 -23.777 47.604 -23.492 47.670 -23.217 47.764 -22.937 47.841 -22.651 47.890 -22.368 47.973 -22.093 48.066 -21.830 48.181 -21.552 48.280 -21.277 48.368 -20.995 48.445 -20.712 48.522 -20.431 48.604 -20.165 48.720 -19.912 48.808 -19.613 48.890 -19.341 48.995 -19.063 49.082 -18.797 49.198 -18.525 49.308 -18.247 49.396 -17.970 49.445 -17.687 49.511 -17.407 49.451 -17.124 49.516 -16.896 49.687 -16.725 49.791 -16.418 49.852 -16.148 49.791 -15.874 49.714 -15.585 49.659 -15.486 49.868 -15.753 50.000 -15.918 50.214 -15.673 50.390 -15.393 50.484 -15.124 50.429 -14.865 50.291 -14.585 50.214 -14.294 50.192 -14.005 50.159 -13.717 50.115 -13.431 50.027 -13.165 49.951 -12.898 49.852 -12.720 49.659 -12.437 49.538 -12.143 49.275 -12.272 49.082 -12.475 48.852 -12.766 48.923 -13.041 48.868 -13.330 48.786 -13.456 48.522 -13.687 48.308 -13.577 48.071 -13.676 47.907 -14.104 47.984 -14.228 47.863 -14.602 47.868 -14.742 47.676 -15.011 47.516 -14.824 47.440 -14.918 47.297 -15.360 47.093 -15.258 46.923 -15.409 46.654 -15.580 46.434 -15.832 46.390 -15.901 46.335 -15.794 46.082 -15.794 45.808 -15.959 45.588 -16.016 45.302 -16.124 45.005 -16.201 44.747 -16.280 44.467 -16.591 44.451 -16.857 44.330 -17.110 44.170 -17.352 44.022 -17.629 43.984 -17.901 44.038 -18.187 44.055 -18.467 44.110 -18.728 44.242 -18.997 44.264 -19.280 44.374 -19.541 44.473 -19.827 44.456 -20.085 44.418 -20.338 44.264 -20.566 44.110 -20.827 43.940 -21.107 43.846 -21.288 43.626 -21.478 43.478 -21.777 43.396 ; #14 1 41.486 140.989 41.255 140.813 41.201 141.126 40.959 141.181 40.909 140.813 41.170 140.516 41.022 140.324 40.766 140.148 40.566 139.918 40.272 140.005 39.942 139.841 39.695 140.060 39.404 140.022 39.140 139.890 38.860 139.791 38.613 139.599 38.341 139.462 38.074 139.335 37.915 139.033 37.709 138.797 37.456 138.621 37.255 138.368 37.121 138.055 37.000 137.720 36.857 137.418 36.808 137.099 37.104 136.973 37.393 137.258 37.437 137.044 37.286 136.747 37.019 136.742 36.728 136.692 36.489 136.495 36.277 136.236 36.038 136.022 35.734 136.038 35.547 135.769 35.511 135.429 35.643 135.209 35.646 134.824 35.621 134.467 35.525 134.137 35.495 133.780 35.503 133.368 35.541 133.066 35.423 132.720 35.209 132.495 35.014 132.236 34.819 131.978 34.654 131.681 34.467 131.423 34.398 131.110 34.223 130.896 33.986 130.995 33.981 131.363 34.011 131.709 33.863 132.038 33.981 132.176 34.266 132.286 34.261 132.560 34.313 132.995 34.343 133.247 34.462 133.516 34.519 133.918 34.662 134.214 34.758 134.522 34.698 134.857 34.662 135.181 34.577 135.412 34.299 135.165 34.011 135.121 33.761 135.280 33.558 135.467 33.489 135.797 33.692 136.000 33.975 136.214 34.187 136.401 34.283 136.742 34.415 136.868 34.624 136.588 34.898 136.643 34.882 136.890 34.698 137.159 34.635 137.352 34.651 137.698 34.629 138.099 34.813 138.319 35.033 138.676 34.714 138.857 34.915 139.110 35.190 139.170 35.239 139.593 35.538 139.863 35.310 139.874 34.997 139.835 35.022 140.044 35.184 140.346 35.475 140.451 35.668 140.709 35.816 140.786 36.074 140.615 36.354 140.599 36.637 140.692 36.893 140.857 37.146 141.000 37.434 141.033 37.717 141.000 38.000 140.929 38.291 141.071 38.352 141.385 38.437 141.511 38.698 141.527 38.956 141.698 39.203 141.907 39.489 142.005 39.764 141.984 40.052 141.890 40.316 141.775 40.549 141.533 40.819 141.412 41.110 141.407 41.360 141.346 ; #15 1 58.571 -5.022 58.365 -5.066 58.168 -5.286 57.948 -5.242 57.890 -5.368 57.780 -5.714 57.475 -5.698 57.269 -5.577 57.000 -5.698 56.720 -5.896 56.544 -5.747 56.709 -5.297 56.648 -5.247 56.445 -5.418 56.096 -5.604 55.849 -5.593 55.440 -5.681 55.580 -5.489 55.852 -5.390 56.143 -5.170 55.984 -4.978 55.772 -4.879 55.508 -4.698 55.223 -4.901 54.951 -5.088 54.755 -4.879 54.797 -4.335 54.830 -3.885 54.959 -3.297 54.868 -3.319 54.585 -3.571 54.319 -3.423 54.157 -3.066 53.951 -2.940 53.684 -2.995 53.360 -2.978 53.305 -3.291 53.294 -3.791 53.162 -4.225 52.893 -4.599 52.852 -4.352 52.640 -4.055 52.379 -4.121 52.176 -4.440 52.047 -4.868 51.832 -5.187 51.668 -4.934 51.690 -4.313 51.574 -4.049 51.489 -3.687 51.412 -3.264 51.637 -2.654 51.462 -2.808 51.242 -3.077 51.206 -3.533 51.206 -4.011 51.036 -4.341 50.805 -4.588 50.582 -4.879 50.368 -5.148 50.159 -5.566 50.063 -5.385 50.115 -5.060 50.280 -4.753 50.341 -4.269 50.258 -3.835 50.407 -3.527 50.643 -3.335 50.701 -2.841 50.588 -2.423 50.662 -1.973 50.794 -1.489 50.816 -1.104 50.777 -0.775 50.810 -0.264 50.775 0.198 50.876 0.632 51.000 1.016 51.272 1.363 51.431 0.725 51.692 0.890 51.909 1.242 52.099 1.549 52.374 1.703 52.657 1.714 52.874 1.423 52.956 0.973 52.890 0.500 52.912 0.154 53.209 0.324 53.475 0.110 53.679 -0.440 53.665 -0.066 53.901 -0.137 54.168 -0.236 54.429 -0.533 54.588 -0.978 54.742 -1.253 55.025 -1.429 55.302 -1.555 55.585 -1.703 55.805 -2.022 55.973 -2.423 56.005 -2.868 56.003 -3.451 56.052 -3.319 56.223 -2.791 56.387 -3.005 56.440 -2.995 56.574 -2.560 56.810 -2.302 57.085 -2.099 57.352 -1.901 57.596 -1.879 57.668 -2.374 57.679 -2.907 57.687 -3.451 57.596 -4.148 57.797 -4.000 58.038 -3.797 58.236 -3.396 58.549 -3.159 58.599 -3.643 58.533 -4.264 58.547 -4.725 ; #16 1 72.613 -114.538 72.753 -114.220 73.033 -114.005 73.308 -114.313 73.269 -115.214 73.129 -116.077 72.973 -116.929 72.791 -117.637 72.580 -118.291 72.294 -118.341 72.044 -118.824 71.709 -119.005 71.635 -118.214 71.514 -117.973 71.423 -117.423 71.478 -116.462 71.519 -115.505 71.448 -115.747 71.341 -116.297 71.228 -117.137 71.115 -117.984 70.890 -118.253 70.654 -117.604 70.613 -116.780 70.596 -115.951 70.607 -115.055 70.676 -114.198 70.643 -113.368 70.533 -112.571 70.357 -111.747 70.272 -112.099 70.231 -112.819 70.277 -113.709 70.305 -114.544 70.261 -115.401 70.192 -116.231 70.102 -117.044 69.879 -117.330 69.613 -116.857 69.412 -116.423 69.277 -115.654 69.261 -114.857 69.228 -113.896 69.036 -113.621 68.753 -113.549 68.503 -113.126 68.508 -112.352 68.544 -111.456 68.585 -110.819 68.624 -110.022 68.701 -109.247 68.882 -108.577 68.956 -107.841 69.110 -107.176 69.390 -106.758 69.255 -106.308 69.143 -105.687 68.997 -105.071 68.896 -104.363 68.821 -103.555 68.849 -102.775 69.071 -101.989 69.368 -102.209 69.250 -103.000 69.363 -103.071 69.582 -103.335 69.629 -102.835 69.808 -102.214 69.742 -101.390 69.885 -100.912 70.140 -101.247 70.294 -101.896 70.538 -102.857 70.591 -103.407 70.805 -103.984 71.060 -104.473 71.357 -104.390 71.640 -104.456 71.909 -104.808 72.190 -105.033 72.473 -105.242 72.753 -105.412 73.011 -105.857 73.223 -106.582 73.269 -107.577 73.096 -108.159 72.777 -108.066 72.497 -107.890 72.220 -107.753 71.920 -107.429 71.701 -107.681 71.761 -108.170 72.038 -108.368 72.327 -108.610 72.599 -108.879 72.816 -109.478 72.986 -110.264 72.772 -110.181 72.527 -110.110 72.434 -110.956 72.327 -111.555 72.352 -111.709 72.637 -111.324 72.849 -111.885 72.973 -112.846 72.734 -113.533 72.613 -114.165 ; #17 1 21.846 -84.874 21.871 -84.560 21.854 -84.324 21.992 -84.022 22.170 -83.808 22.201 -83.495 22.321 -83.242 22.511 -83.000 22.668 -82.731 22.684 -82.418 22.673 -82.099 22.580 -81.742 22.409 -82.011 22.253 -81.907 22.192 -81.632 22.143 -81.269 22.135 -81.093 22.052 -80.802 22.085 -80.473 21.874 -80.225 21.731 -79.940 21.662 -79.626 21.571 -79.341 21.580 -79.033 21.585 -78.725 21.327 -78.549 21.055 -78.467 20.860 -78.242 20.717 -77.989 20.692 -77.676 20.668 -77.330 20.429 -77.159 20.206 -77.368 19.945 -77.626 19.874 -77.357 19.890 -77.071 19.934 -76.769 19.953 -76.451 19.975 -76.148 19.956 -75.846 19.893 -75.544 19.951 -75.170 19.953 -74.956 20.047 -74.665 20.168 -74.269 20.360 -74.484 20.560 -74.714 20.676 -75.011 20.701 -75.319 20.777 -75.643 20.992 -75.676 21.096 -75.967 21.195 -76.220 21.247 -76.544 21.341 -76.780 21.519 -77.066 21.593 -77.236 21.843 -77.478 21.753 -77.434 21.739 -77.484 21.882 -77.813 22.030 -78.033 22.179 -78.297 22.308 -78.566 22.374 -78.813 22.387 -79.170 22.497 -79.445 22.709 -79.654 22.874 -79.901 22.929 -80.209 23.047 -80.549 23.082 -80.791 23.115 -81.137 23.104 -81.429 23.154 -81.687 23.176 -82.005 23.159 -82.324 23.055 -82.615 23.005 -82.945 22.964 -83.220 22.852 -83.522 22.753 -83.824 22.635 -84.099 22.420 -84.324 22.126 -84.352 22.022 -84.462 21.929 -84.797 ; #18 1 51.541 -55.764 51.544 -56.082 51.404 -56.489 51.201 -56.786 50.970 -56.984 50.673 -57.258 50.451 -57.462 50.179 -57.615 49.909 -57.791 49.544 -57.879 49.387 -58.192 49.121 -58.011 49.066 -58.319 48.698 -58.747 48.591 -59.077 48.489 -58.560 48.294 -58.753 48.096 -59.071 47.868 -59.335 47.602 -59.165 47.615 -58.681 47.687 -58.313 47.659 -57.890 47.618 -57.456 47.574 -57.049 47.593 -56.670 47.703 -56.198 47.838 -55.863 47.742 -55.802 47.552 -55.956 47.497 -55.753 47.599 -55.423 47.659 -55.115 47.618 -54.907 47.407 -55.209 47.173 -55.467 47.038 -55.857 46.879 -55.725 46.948 -55.319 47.159 -55.071 47.423 -54.659 47.462 -54.451 47.775 -54.258 47.786 -54.038 47.473 -53.890 47.245 -53.989 46.953 -54.159 46.860 -53.978 47.096 -53.670 47.033 -53.566 46.761 -53.527 46.695 -53.137 46.973 -52.896 47.228 -52.813 47.610 -52.714 47.492 -53.060 47.610 -53.203 48.016 -53.005 47.934 -53.330 47.629 -53.599 47.799 -53.808 48.074 -53.791 48.239 -53.516 48.505 -53.126 48.525 -53.434 48.442 -53.835 48.574 -53.791 48.761 -53.929 49.000 -53.769 49.253 -53.566 49.434 -53.995 49.409 -54.401 49.363 -54.769 49.291 -55.192 49.418 -55.462 49.475 -55.874 49.621 -56.000 49.885 -55.703 50.033 -56.071 49.923 -56.407 49.673 -56.731 49.758 -56.808 50.025 -56.703 50.319 -56.462 50.541 -56.247 50.805 -56.066 51.033 -55.791 51.236 -55.967 51.343 -55.835 51.497 -55.511 ; #19 1 -39.651 176.934 -39.456 176.929 -39.209 177.093 -39.085 177.429 -39.146 177.802 -39.124 177.929 -38.794 177.956 -38.610 178.198 -38.349 178.330 -38.060 178.363 -37.745 178.484 -37.566 178.170 -37.659 177.824 -37.868 177.588 -37.992 177.214 -37.926 176.901 -37.805 176.566 -37.629 176.126 -37.442 176.005 -37.151 175.901 -36.854 175.802 -36.626 175.560 -36.808 175.489 -37.154 175.533 -37.030 175.275 -36.868 174.841 -36.657 174.775 -36.396 174.780 -36.129 174.654 -35.827 174.473 -35.604 174.516 -35.324 174.297 -35.187 174.071 -35.030 173.791 -34.926 173.434 -34.808 173.159 -34.511 172.940 -34.651 172.885 -34.885 173.093 -35.168 173.159 -35.379 173.434 -35.624 173.467 -35.876 173.681 -36.247 174.033 -36.008 173.945 -36.055 173.984 -36.212 174.330 -36.481 174.357 -36.637 174.302 -36.931 174.473 -36.995 174.775 -37.143 174.720 -37.371 174.747 -37.734 174.874 -38.014 174.841 -38.192 174.747 -38.514 174.643 -38.799 174.577 -38.975 174.302 -39.091 173.962 -39.313 173.775 -39.533 173.989 -39.648 174.330 -39.830 174.626 -39.945 174.984 -40.203 175.247 -40.404 175.220 -40.698 175.126 -40.959 174.929 -41.201 174.714 -41.332 174.868 -41.525 175.209 -41.500 175.533 -41.324 175.841 -41.102 176.077 -40.852 176.253 -40.593 176.451 -40.346 176.670 -40.113 176.868 -39.755 177.016 ; #20 1 18.475 122.203 18.324 122.011 18.335 121.692 18.462 121.440 18.602 121.170 18.596 120.863 18.459 120.604 18.157 120.505 17.874 120.429 17.593 120.368 17.305 120.418 17.011 120.418 16.725 120.313 16.456 120.313 16.159 120.363 16.071 120.170 16.286 119.885 16.019 119.775 15.780 119.896 15.497 119.923 15.225 120.005 14.929 120.060 14.775 120.225 14.492 120.451 14.766 120.593 14.698 120.885 14.456 120.896 14.236 120.643 13.978 120.615 13.865 120.753 13.709 120.995 13.632 121.308 13.816 121.495 13.915 121.780 13.775 122.060 13.585 122.280 13.299 122.560 13.519 122.604 13.849 122.495 13.805 122.725 13.596 122.901 13.412 123.159 13.157 123.286 12.992 123.456 12.887 123.819 12.629 123.912 12.637 124.099 12.981 124.126 13.099 123.846 13.297 123.775 13.577 123.577 13.731 123.824 13.874 123.720 13.981 123.418 13.887 123.220 14.069 123.022 14.288 122.775 14.313 122.505 14.132 122.275 13.951 122.143 14.071 121.846 14.313 121.714 14.624 121.643 14.846 121.621 15.113 121.495 15.368 121.423 15.657 121.582 15.923 121.604 16.146 121.984 16.154 122.115 16.398 122.225 16.679 122.357 16.945 122.467 17.214 122.434 17.412 122.258 17.703 122.154 17.995 122.176 18.261 122.286 ; #21 1 -41.558 174.099 -41.266 174.148 -41.104 174.066 -41.115 173.841 -40.992 173.813 -41.162 173.434 -41.214 173.099 -40.885 172.984 -40.684 172.709 -40.555 172.692 -40.775 172.264 -41.016 172.110 -41.316 172.088 -41.580 171.907 -41.766 171.588 -41.986 171.412 -42.269 171.302 -42.396 171.396 -42.357 171.527 -42.560 171.143 -42.835 171.038 -42.890 170.863 -43.058 170.500 -43.220 170.258 -43.470 169.879 -43.637 169.555 -43.753 169.231 -43.923 169.049 -44.011 168.549 -44.198 168.225 -44.390 167.984 -44.643 167.786 -44.854 167.500 -45.041 167.203 -45.266 167.137 -45.382 167.033 -45.495 166.868 -45.734 166.802 -45.948 166.626 -46.085 166.791 -46.255 167.176 -46.220 167.610 -46.371 167.978 -46.484 168.319 -46.582 168.527 -46.637 168.984 -46.624 169.379 -46.492 169.753 -46.266 170.044 -46.044 170.297 -45.838 170.670 -45.582 170.764 -45.308 170.907 -44.995 171.027 -44.857 170.791 -44.720 171.198 -44.434 171.258 -44.231 171.115 -44.206 171.143 -44.137 171.467 -44.030 171.835 -43.835 172.088 -43.599 171.775 -43.387 171.505 -43.250 171.335 -43.577 171.775 -43.758 172.099 -43.799 172.418 -43.835 172.648 -43.777 173.005 -43.574 172.764 -43.478 172.385 -43.404 172.192 -43.327 172.599 -43.255 172.484 -43.181 172.830 -43.014 173.165 -42.788 173.385 -42.516 173.566 -42.305 173.802 -42.088 173.956 -41.794 174.220 -41.668 174.104 ; #22 1 -7.896 110.033 -8.022 110.297 -8.137 110.560 -8.209 110.846 -8.255 111.132 -8.288 111.423 -8.319 111.709 -8.299 111.989 -8.341 112.286 -8.415 112.571 -8.390 112.852 -8.291 113.126 -8.365 113.407 -8.481 113.670 -8.582 113.934 -8.629 114.220 -8.618 114.456 -8.217 114.396 -7.926 114.451 -7.736 114.291 -7.659 114.011 -7.714 113.720 -7.739 113.434 -7.728 113.170 -7.613 112.901 -7.407 112.791 -7.173 112.676 -6.923 112.538 -6.896 112.236 -6.827 111.967 -6.739 111.692 -6.679 111.429 -6.646 111.148 -6.437 110.945 -6.541 110.687 -6.816 110.577 -6.948 110.346 -6.907 110.071 -6.887 109.775 -6.849 109.489 -6.860 109.198 -6.816 108.923 -6.747 108.637 -6.489 108.500 -6.305 108.264 -6.283 107.984 -6.223 107.720 -6.099 107.456 -5.964 107.214 -6.022 106.984 -6.052 106.709 -6.005 106.429 -5.951 106.137 -6.041 105.923 -6.313 105.830 -6.525 105.676 -6.734 105.451 -6.821 105.352 -6.852 105.714 -6.846 106.005 -6.967 106.280 -7.099 106.473 -7.368 106.478 -7.429 106.780 -7.451 107.071 -7.497 107.368 -7.596 107.637 -7.712 107.901 -7.780 108.187 -7.764 108.473 -7.670 108.758 -7.703 109.033 -7.723 109.335 -7.783 109.604 -7.832 109.830 ; #23 1 53.014 141.890 52.712 141.846 52.442 141.736 52.170 141.665 51.882 141.714 51.651 141.841 51.371 142.121 51.088 142.236 50.808 142.110 50.516 142.071 50.231 142.154 49.942 142.154 49.657 142.148 49.371 142.088 49.082 142.033 48.802 141.912 48.530 141.984 48.261 142.143 47.970 142.159 47.695 142.016 47.404 141.967 47.121 142.044 46.838 141.945 46.555 141.830 46.269 141.890 46.049 142.110 46.426 142.341 46.665 142.626 46.591 143.038 46.473 143.335 46.245 143.495 46.692 143.516 46.791 143.231 47.096 143.044 47.357 142.885 47.560 142.654 47.849 142.544 48.129 142.593 48.412 142.720 48.687 142.857 48.964 142.973 49.214 143.148 49.332 143.495 49.250 144.000 49.058 144.330 48.827 144.593 48.777 144.676 49.077 144.396 49.352 144.247 49.635 144.159 49.912 144.038 50.181 143.879 50.453 143.747 50.739 143.676 51.019 143.582 51.294 143.478 51.577 143.324 51.865 143.214 52.132 143.137 52.407 143.176 52.541 143.280 52.997 143.313 53.302 143.209 53.558 143.049 53.805 142.934 54.118 142.962 54.310 142.632 54.187 142.429 53.885 142.676 53.657 142.648 53.434 142.297 53.376 141.863 53.190 141.835 ; #24 1 9.764 125.423 9.574 125.423 9.294 125.505 9.022 125.456 8.945 125.165 8.929 124.846 8.599 124.753 8.527 124.571 8.503 124.335 8.236 124.198 8.063 123.813 8.198 123.852 8.495 123.808 8.643 123.582 8.621 123.368 8.486 123.088 8.228 122.956 8.118 122.687 8.047 122.412 7.879 122.181 7.607 122.110 7.330 122.016 7.060 121.918 6.964 122.143 7.245 122.286 7.511 122.423 7.736 122.588 7.582 122.819 7.585 123.082 7.489 123.363 7.769 123.511 7.736 123.791 7.599 124.044 7.349 124.198 7.093 124.044 6.816 124.000 6.533 124.049 6.277 124.165 6.113 124.396 5.978 124.654 5.876 124.929 6.016 125.148 5.940 125.242 5.679 125.269 5.659 125.456 5.901 125.626 6.176 125.687 6.453 125.582 6.668 125.412 6.964 125.505 7.242 125.747 7.036 125.945 6.777 126.066 6.418 126.143 6.508 126.220 6.838 126.253 7.014 126.423 7.266 126.577 7.549 126.582 7.794 126.456 8.110 126.429 8.357 126.368 8.585 126.225 8.863 126.302 9.192 126.181 9.385 125.967 9.549 125.786 9.725 125.560 ; #25 1 66.371 -14.824 66.231 -15.401 66.415 -15.841 66.462 -16.396 66.159 -16.681 66.060 -17.374 66.063 -17.967 65.797 -18.104 65.797 -18.198 66.044 -18.544 66.135 -19.011 65.854 -19.484 66.003 -20.110 65.747 -20.302 65.580 -20.615 65.341 -21.044 65.376 -21.242 65.643 -21.511 65.904 -21.401 66.115 -21.714 66.349 -22.247 66.423 -22.907 66.310 -22.692 66.016 -22.648 66.102 -23.236 65.962 -23.571 65.775 -23.516 65.695 -23.687 65.580 -24.132 65.464 -24.110 65.478 -23.467 65.569 -22.791 65.486 -22.143 65.250 -22.385 65.126 -21.989 65.038 -22.253 65.003 -22.912 64.876 -23.698 64.802 -23.396 64.788 -22.610 64.621 -22.308 64.582 -21.835 64.440 -21.753 64.190 -21.852 63.967 -22.484 63.849 -22.011 63.887 -21.275 63.766 -20.599 63.593 -20.264 63.514 -19.676 63.415 -19.016 63.478 -18.291 63.632 -17.901 63.758 -17.527 63.841 -16.885 63.989 -16.313 64.176 -15.802 64.308 -15.220 64.470 -14.577 64.698 -14.346 64.904 -13.923 65.030 -13.813 65.198 -13.731 65.382 -13.736 65.593 -14.192 65.775 -14.632 66.055 -14.896 66.286 -14.852 ; #26 1 19.734 -72.115 19.772 -72.363 19.907 -72.670 19.920 -72.973 19.871 -73.269 19.692 -73.368 19.596 -73.033 19.423 -72.753 19.159 -72.769 18.920 -72.670 18.720 -72.429 18.552 -72.462 18.453 -72.775 18.464 -73.082 18.503 -73.385 18.544 -73.670 18.593 -73.984 18.648 -74.286 18.442 -74.445 18.286 -74.242 18.107 -73.907 18.223 -73.648 18.239 -73.357 18.184 -73.060 18.162 -72.758 18.209 -72.478 18.225 -72.154 18.126 -71.868 17.898 -71.670 17.709 -71.522 17.739 -71.341 17.973 -71.165 18.245 -71.022 18.379 -70.736 18.258 -70.516 18.253 -70.192 18.429 -69.945 18.434 -69.637 18.431 -69.330 18.404 -69.033 18.272 -68.769 18.330 -68.555 18.574 -68.379 18.802 -68.560 18.975 -68.808 19.014 -69.099 19.118 -69.495 19.242 -69.269 19.324 -69.379 19.310 -69.692 19.511 -69.879 19.651 -70.066 19.709 -70.363 19.788 -70.654 19.904 -70.945 19.849 -71.236 19.887 -71.571 19.720 -71.824 ; #27 1 45.511 141.934 45.409 141.731 45.154 141.610 44.876 141.747 44.588 141.780 44.308 141.687 44.019 141.654 43.780 141.429 43.505 141.390 43.239 141.335 43.190 140.989 43.277 140.505 43.014 140.462 42.780 140.220 42.604 139.890 42.294 139.813 42.063 140.044 41.799 140.093 41.492 140.060 41.541 140.379 41.758 140.648 41.747 141.022 41.896 141.033 42.082 140.725 42.212 140.379 42.464 140.363 42.547 140.687 42.374 141.011 42.544 141.401 42.591 141.780 42.445 142.121 42.283 142.445 42.146 142.791 42.036 143.214 42.343 143.374 42.593 143.577 42.805 143.846 42.962 144.176 42.945 144.604 43.027 144.984 43.261 145.538 43.332 145.324 43.624 145.170 43.893 145.126 44.201 145.313 44.190 145.159 43.981 144.868 43.937 144.489 44.080 144.154 44.157 143.747 44.321 143.418 44.508 143.104 44.714 142.819 44.951 142.582 45.184 142.341 45.401 142.077 ; #28 2 76.209 -112.714 76.247 -113.692 76.459 -114.527 76.272 -115.379 76.184 -115.934 75.992 -116.604 75.882 -115.429 75.830 -115.758 75.703 -116.962 75.613 -115.769 75.481 -116.434 75.382 -117.451 75.165 -117.159 75.091 -116.022 75.060 -115.060 75.321 -114.049 75.143 -113.769 75.173 -112.654 75.195 -111.456 75.077 -111.407 74.995 -112.390 74.868 -113.352 74.681 -114.225 74.442 -113.555 74.423 -112.505 74.536 -111.511 74.739 -110.632 74.863 -109.813 74.986 -108.753 74.986 -107.742 74.986 -106.632 75.173 -105.940 75.459 -105.643 75.736 -105.434 75.992 -105.923 75.830 -106.841 75.882 -107.615 76.135 -108.209 76.434 -108.451 76.739 -108.698 76.681 -109.527 76.426 -110.115 76.192 -109.720 75.915 -109.654 75.626 -108.995 75.527 -109.747 75.558 -110.989 75.813 -111.769 76.041 -112.231 ; #29 1 55.313 -7.335 55.154 -7.621 55.162 -8.005 54.951 -8.374 54.764 -8.571 54.593 -8.352 54.335 -8.544 54.255 -8.769 54.258 -9.236 54.209 -9.934 53.951 -9.824 53.788 -9.703 53.525 -10.066 53.363 -9.808 53.209 -9.203 52.964 -9.396 52.659 -9.698 52.618 -9.440 52.692 -8.978 52.632 -8.989 52.566 -9.467 52.379 -9.802 52.168 -10.115 51.868 -10.258 51.821 -9.819 51.695 -9.967 51.687 -9.648 51.569 -9.698 51.503 -9.560 51.530 -9.126 51.621 -8.659 51.810 -8.291 51.904 -7.890 52.071 -7.533 52.173 -7.016 52.223 -6.560 52.431 -6.319 52.717 -6.170 52.995 -6.038 53.313 -6.121 53.566 -6.143 53.846 -6.297 54.038 -6.159 54.214 -5.764 54.440 -5.577 54.712 -5.736 54.945 -5.907 55.179 -6.165 55.148 -6.940 55.308 -7.154 ; #30 2 -72.714 -72.396 -72.670 -71.791 -72.670 -70.813 -72.618 -69.885 -72.459 -69.148 -72.231 -68.516 -71.953 -68.286 -71.665 -68.121 -71.376 -68.203 -71.085 -68.247 -70.799 -68.346 -70.516 -68.511 -70.247 -68.896 -69.978 -69.159 -69.695 -69.346 -69.418 -69.593 -69.184 -70.016 -68.876 -70.187 -68.827 -70.852 -68.945 -71.582 -69.159 -72.137 -69.434 -71.929 -69.690 -71.692 -69.978 -71.775 -70.272 -71.610 -70.486 -72.286 -70.690 -71.945 -70.791 -71.143 -71.080 -70.929 -71.157 -71.890 -71.121 -72.753 -71.316 -72.709 -71.371 -73.231 -71.495 -73.582 -71.544 -74.137 -71.635 -74.791 -71.745 -75.363 -71.995 -75.165 -72.137 -74.341 -71.959 -73.742 -71.915 -73.192 -71.745 -72.516 -71.805 -72.016 -71.989 -71.341 -72.151 -71.621 -72.250 -70.923 -72.357 -70.857 -72.390 -71.791 -72.352 -72.813 -72.585 -72.819 ; #31 1 -54.830 -68.538 -54.849 -68.044 -54.882 -67.549 -54.915 -67.044 -55.011 -66.549 -54.948 -66.049 -54.926 -65.571 -54.769 -65.231 -54.646 -65.429 -54.624 -65.912 -54.489 -66.357 -54.294 -66.725 -54.126 -67.126 -53.934 -67.500 -53.720 -67.791 -53.475 -68.055 -53.162 -68.368 -52.920 -68.330 -52.679 -68.599 -52.626 -68.945 -52.541 -69.363 -52.643 -69.648 -52.810 -70.165 -53.027 -70.346 -53.319 -70.434 -53.418 -70.071 -53.398 -69.489 -53.626 -69.736 -53.794 -70.121 -54.077 -70.016 -54.231 -69.610 -54.376 -69.159 -54.555 -69.231 -54.497 -69.335 -54.409 -69.736 -54.341 -70.137 -54.198 -70.753 -54.434 -70.429 -54.448 -70.753 -54.440 -71.357 -54.508 -71.802 -54.626 -71.670 -54.618 -71.269 -54.720 -70.780 -54.791 -70.297 -54.766 -69.830 -54.887 -69.368 -54.871 -68.863 ; #32 -1 60.915 -114.742 60.981 -114.165 61.115 -113.698 61.374 -113.500 61.437 -112.984 61.533 -112.445 61.755 -112.027 62.005 -111.632 62.223 -111.357 62.374 -110.830 62.415 -110.286 62.511 -110.159 62.519 -110.478 62.706 -110.044 62.698 -110.610 62.585 -111.264 62.525 -111.484 62.777 -110.747 62.819 -110.192 62.753 -109.549 62.739 -109.187 62.931 -109.978 62.923 -110.621 62.794 -111.198 62.569 -111.555 62.324 -111.879 62.124 -112.341 62.038 -112.940 62.038 -113.522 62.228 -113.967 62.374 -114.462 62.508 -115.066 62.665 -115.626 62.632 -115.868 62.412 -115.368 62.162 -115.099 61.882 -114.742 61.755 -115.225 61.624 -115.648 61.354 -115.907 61.242 -116.192 61.255 -116.764 61.206 -117.286 61.206 -117.462 61.036 -116.879 60.948 -116.357 60.849 -115.791 60.857 -115.253 ; #33 2 76.632 -92.082 76.525 -93.159 76.690 -93.264 76.907 -94.005 77.016 -95.165 76.973 -96.489 76.747 -96.571 76.500 -95.813 76.297 -95.005 76.305 -93.610 76.176 -92.791 75.915 -92.330 75.626 -92.115 75.352 -92.423 75.091 -92.176 74.766 -91.885 74.723 -91.027 74.571 -90.055 74.745 -88.841 74.514 -88.192 74.500 -87.060 74.536 -86.280 74.580 -85.330 74.544 -84.681 74.731 -83.407 74.558 -82.698 74.500 -81.731 74.588 -80.566 74.885 -79.973 75.077 -80.099 75.338 -79.566 75.541 -80.192 75.712 -81.187 75.821 -82.253 75.783 -83.495 75.681 -84.555 75.527 -85.626 75.412 -86.352 75.536 -87.423 75.541 -88.599 75.613 -89.418 75.876 -89.692 75.937 -90.621 76.096 -90.956 76.209 -89.978 76.467 -90.857 76.665 -91.368 ; #34 2 79.398 10.885 79.195 11.698 78.912 11.929 78.618 12.093 78.445 12.786 78.236 13.709 78.437 14.489 78.687 14.912 78.695 15.396 78.530 15.945 78.569 16.577 78.341 16.423 78.143 14.918 77.997 13.945 77.769 14.286 77.849 15.747 77.813 16.527 77.615 15.330 77.511 15.720 77.484 14.258 77.187 14.599 77.033 15.703 76.898 16.011 76.673 16.780 77.041 17.286 77.335 17.555 77.563 18.176 77.868 18.429 78.115 18.874 78.418 19.165 78.626 20.154 78.783 21.176 79.071 19.918 79.255 18.934 79.525 18.055 79.835 17.725 79.942 16.396 79.695 15.731 79.409 15.934 79.132 16.225 79.063 16.033 79.379 15.484 79.662 15.093 79.673 14.280 79.525 13.505 79.813 13.077 79.736 11.813 79.588 10.962 ; #35 -1 -4.206 29.181 -4.308 29.225 -4.569 29.148 -4.865 29.099 -5.157 29.132 -5.420 29.258 -5.681 29.346 -5.945 29.220 -6.192 29.297 -6.467 29.429 -6.728 29.533 -6.956 29.714 -7.115 29.945 -7.310 30.148 -7.591 30.214 -7.860 30.319 -8.080 30.522 -8.456 30.544 -8.574 30.780 -8.747 31.060 -8.571 31.165 -8.324 31.044 -8.080 30.918 -7.813 30.775 -7.555 30.626 -7.266 30.571 -7.008 30.527 -6.728 30.368 -6.508 30.165 -6.437 29.901 -6.184 29.731 -5.951 29.874 -5.698 29.896 -5.431 29.775 -5.143 29.802 -4.893 29.637 -4.613 29.632 -4.338 29.599 -4.074 29.473 -3.805 29.357 -3.437 29.275 -3.602 29.143 -3.882 29.110 -4.176 29.088 ; #36 -1 55.692 109.440 55.516 109.231 55.225 109.176 54.962 108.978 54.692 108.797 54.437 108.566 54.170 108.363 53.907 108.154 53.706 107.797 53.470 107.522 53.277 107.159 53.041 106.852 52.794 106.648 52.604 106.308 52.434 105.923 52.195 105.659 51.989 105.341 51.868 104.912 51.788 104.478 51.720 103.912 51.560 104.060 51.481 104.505 51.525 104.945 51.613 105.385 51.723 105.830 51.937 106.137 52.212 106.275 52.352 106.615 52.464 106.967 52.629 107.352 52.734 107.802 52.918 108.165 53.148 108.407 53.316 108.819 53.533 108.786 53.736 108.901 53.731 109.192 53.995 109.418 54.266 109.511 54.558 109.527 54.830 109.670 55.113 109.758 55.398 109.835 55.720 109.769 ; #37 2 74.687 56.440 74.536 55.802 74.280 55.423 74.132 55.330 73.953 54.500 73.706 54.192 73.651 54.852 73.415 54.440 73.363 55.797 73.302 56.687 73.530 57.027 73.747 57.192 73.863 57.841 74.104 57.945 74.288 58.621 74.536 58.808 74.703 59.626 74.929 60.330 75.104 60.758 75.316 61.588 75.505 62.593 75.657 63.643 75.775 64.698 75.915 65.731 76.058 66.758 76.223 67.775 76.401 68.478 76.690 68.885 76.940 68.368 76.956 67.148 76.764 66.121 76.541 65.538 76.376 64.390 76.264 63.181 76.247 62.165 76.184 61.071 76.041 60.385 75.876 59.165 75.665 58.236 75.420 57.560 75.261 56.813 75.052 56.225 74.766 56.319 74.695 56.967 ; #38 -1 65.099 -123.247 65.030 -122.621 65.016 -121.901 65.272 -121.571 65.492 -121.176 65.533 -120.500 65.245 -120.632 64.945 -121.231 64.953 -120.846 65.140 -120.264 65.371 -119.714 65.657 -119.841 65.791 -119.308 65.736 -118.264 66.014 -118.011 66.225 -117.736 66.525 -117.703 66.467 -118.209 66.330 -118.758 66.330 -119.582 66.423 -120.264 66.632 -120.038 66.824 -119.313 66.984 -119.626 66.964 -120.302 66.857 -121.005 66.712 -121.599 66.582 -122.346 66.505 -123.016 66.401 -123.654 66.154 -124.703 66.140 -124.159 66.121 -123.352 66.214 -122.885 66.258 -122.132 66.121 -121.484 65.948 -121.555 65.984 -122.418 65.863 -122.341 65.626 -122.467 65.426 -122.813 65.217 -123.192 ; #39 -1 -2.052 31.676 -2.313 31.698 -2.670 31.846 -2.511 32.060 -2.338 32.264 -2.473 32.538 -2.530 32.758 -2.852 32.797 -2.821 32.923 -2.519 32.896 -2.434 33.110 -2.505 33.390 -2.242 33.687 -2.124 33.330 -1.948 33.407 -1.734 33.593 -1.500 33.780 -1.297 33.912 -1.027 34.066 -0.780 34.093 -0.508 34.154 -0.448 34.423 -0.310 34.731 -0.135 34.670 -0.272 34.357 -0.157 34.143 0.036 33.995 0.223 33.824 0.242 33.582 0.360 33.368 0.258 33.126 0.132 32.901 0.154 32.632 0.033 32.357 -0.060 32.093 -0.247 31.973 -0.519 31.841 -0.797 31.742 -1.055 31.824 -1.374 31.819 -1.626 31.736 -1.912 31.654 ; #40 -1 49.821 31.451 49.679 31.599 49.505 31.951 49.338 32.308 49.162 32.687 49.030 33.082 48.997 33.495 48.841 33.841 48.692 34.220 48.536 34.582 48.429 35.011 48.148 35.121 47.865 35.104 47.599 34.995 47.574 34.544 47.552 34.126 47.335 33.940 47.069 33.692 46.846 33.478 46.717 32.890 46.745 33.077 46.816 33.533 46.984 33.753 47.299 34.071 47.437 34.242 47.500 34.659 47.426 35.093 47.599 35.264 47.882 35.143 48.154 35.154 48.495 35.187 48.503 35.033 48.574 34.604 48.766 34.242 48.904 33.956 49.030 33.505 49.173 33.132 49.431 32.753 49.451 32.390 49.563 31.967 49.706 31.582 ; #41 1 -4.190 152.126 -4.264 151.934 -4.242 151.593 -4.525 151.621 -4.846 151.659 -4.937 151.434 -5.069 151.187 -5.305 151.033 -5.478 150.835 -5.500 150.577 -5.530 150.302 -5.418 150.088 -5.135 150.121 -5.126 150.022 -5.415 149.934 -5.527 149.698 -5.577 149.418 -5.547 149.143 -5.508 148.857 -5.500 148.566 -5.577 148.346 -5.802 148.484 -5.896 148.769 -6.060 149.016 -6.099 149.225 -6.162 149.500 -6.297 149.731 -6.291 150.027 -6.286 150.308 -6.195 150.588 -6.069 150.835 -5.981 151.121 -5.808 151.357 -5.591 151.533 -5.563 151.830 -5.409 152.088 -5.110 152.000 -4.975 152.187 -4.766 152.379 -4.467 152.385 -4.269 152.236 ; #42 -1 8.964 0.231 8.780 0.170 8.478 0.121 8.223 0.154 7.918 0.033 8.118 -0.225 8.220 -0.352 8.277 -0.588 8.522 -0.758 8.657 -0.835 8.942 -1.104 8.780 -1.115 8.714 -1.495 8.714 -1.379 8.629 -1.110 8.497 -0.868 8.223 -0.720 8.085 -0.571 8.022 -0.341 7.791 -0.170 7.604 -0.489 7.588 -0.181 7.478 -0.066 7.247 0.099 6.984 0.082 6.766 -0.038 6.739 -0.297 6.794 -0.571 6.720 -0.560 6.593 -0.291 6.431 -0.011 6.272 0.088 6.297 0.110 6.635 0.236 6.871 0.247 7.143 0.280 7.473 0.275 7.791 0.247 7.995 0.170 8.294 0.214 8.544 0.137 8.819 0.209 ; #43 -1 -9.843 33.923 -10.121 34.027 -10.368 34.203 -10.643 34.203 -10.940 34.242 -11.225 34.242 -11.511 34.291 -11.775 34.242 -12.022 34.093 -12.310 34.060 -12.547 34.187 -12.838 34.286 -13.107 34.341 -13.396 34.346 -13.624 34.538 -13.882 34.571 -14.157 34.615 -14.173 34.808 -14.102 34.951 -14.220 35.192 -13.780 35.044 -13.599 34.857 -13.308 34.819 -13.016 34.780 -12.731 34.797 -12.451 34.720 -12.165 34.747 -11.929 34.907 -11.648 34.962 -11.390 34.863 -11.190 34.687 -10.918 34.632 -10.632 34.626 -10.349 34.577 -10.060 34.522 -9.813 34.374 -9.604 34.176 -9.566 33.978 ; #44 -1 44.821 61.615 45.055 61.819 45.225 61.566 45.511 61.297 45.717 61.055 46.005 61.044 46.255 61.286 46.489 61.473 46.755 61.511 46.596 61.005 46.706 60.588 46.679 60.302 46.500 59.918 46.228 59.912 46.239 59.522 45.918 59.484 45.942 59.286 45.948 58.857 45.720 58.632 45.448 58.511 45.179 58.352 44.901 58.209 44.613 58.236 44.321 58.247 44.058 58.374 43.725 58.423 43.808 58.863 43.786 59.088 43.753 59.451 43.574 59.720 43.462 59.940 43.571 60.313 43.604 60.687 43.742 60.956 43.981 60.813 44.255 61.066 44.533 61.159 44.670 61.330 ; #45 1 74.168 -119.714 74.316 -120.379 74.500 -121.247 74.486 -122.280 74.429 -123.346 74.324 -124.462 74.022 -124.357 73.753 -123.951 73.462 -124.269 73.190 -124.670 72.920 -124.780 72.624 -125.038 72.357 -125.445 72.063 -125.764 71.945 -125.181 71.769 -124.462 71.574 -123.819 71.305 -123.484 71.126 -122.901 71.299 -122.093 71.418 -121.423 71.538 -120.577 71.819 -120.407 72.146 -120.214 72.294 -119.588 72.560 -119.176 72.772 -118.549 72.953 -117.780 73.124 -116.989 73.288 -116.176 73.497 -115.473 73.753 -115.956 73.981 -116.604 74.195 -117.335 74.245 -118.363 74.104 -119.209 ; #46 1 64.951 -83.170 65.121 -83.516 65.258 -84.110 65.349 -84.736 65.547 -85.148 65.816 -85.352 65.838 -85.802 65.574 -86.066 65.288 -86.143 64.995 -86.187 64.728 -86.291 64.440 -86.379 64.140 -86.297 63.940 -86.802 63.659 -87.121 63.629 -86.599 63.701 -85.896 63.533 -85.621 63.236 -85.599 63.157 -85.137 63.330 -84.610 63.582 -84.269 63.772 -83.747 64.049 -83.538 64.063 -83.033 63.863 -82.484 63.670 -82.198 63.577 -81.577 63.508 -80.962 63.714 -80.396 63.901 -80.522 64.058 -80.973 64.030 -81.637 64.146 -81.742 64.448 -81.791 64.690 -82.170 64.813 -82.742 ; #47 1 7.467 79.802 7.168 79.835 6.882 79.857 6.596 79.940 6.324 80.016 6.074 80.165 5.956 80.423 5.973 80.703 6.085 80.978 6.176 81.242 6.327 81.500 6.522 81.714 6.786 81.830 7.069 81.879 7.393 81.835 7.626 81.714 7.827 81.621 8.126 81.440 8.418 81.346 8.585 81.198 8.885 81.038 9.066 80.896 9.308 80.769 9.519 80.544 9.712 80.324 9.736 80.253 9.659 80.319 9.681 80.099 9.500 80.379 9.459 80.110 9.168 80.093 8.907 79.956 8.610 79.918 8.332 79.835 8.126 79.753 7.766 79.775 7.610 79.791 ; #48 1 0.272 128.846 0.451 128.681 0.610 128.462 0.813 128.286 1.000 128.555 1.203 128.709 1.500 128.681 1.514 128.423 1.308 128.170 1.102 128.060 0.868 127.874 0.970 127.687 1.198 127.901 1.440 128.016 1.723 127.967 2.066 127.945 1.997 127.764 1.753 127.593 1.486 127.522 1.168 127.423 0.923 127.533 0.673 127.549 0.401 127.615 0.159 127.692 -0.129 127.681 -0.360 127.813 -0.599 127.978 -0.832 128.275 -0.701 128.225 -0.456 128.071 -0.192 127.962 0.088 127.901 0.396 127.940 0.418 128.220 0.354 128.500 0.261 128.775 ; #49 1 -40.775 147.956 -40.865 147.731 -40.970 147.385 -41.058 146.951 -41.129 146.681 -41.157 146.302 -41.060 145.934 -40.909 145.599 -40.791 145.247 -40.717 144.824 -40.876 144.670 -41.143 144.676 -41.418 144.786 -41.684 144.934 -41.920 145.148 -42.297 145.363 -42.489 145.247 -42.736 145.374 -42.992 145.577 -43.234 145.852 -43.393 146.088 -43.516 146.396 -43.599 146.736 -43.448 146.967 -43.214 147.104 -42.942 147.308 -42.931 147.495 -43.080 147.808 -42.923 147.934 -42.646 147.929 -42.382 148.000 -42.115 148.220 -41.948 148.302 -41.662 148.291 -41.346 148.297 -41.077 148.291 -40.832 148.159 ; #50 -1 46.327 74.027 46.179 73.791 45.934 73.637 45.690 73.478 45.423 73.681 45.104 74.027 45.313 74.121 45.591 74.198 45.794 74.275 46.011 74.429 46.137 74.753 46.409 75.027 46.511 75.363 46.566 75.582 46.525 76.033 46.547 76.401 46.489 76.857 46.473 77.258 46.412 77.703 46.341 78.099 46.352 78.467 46.404 78.918 46.706 79.115 46.706 78.780 46.588 78.352 46.629 77.918 46.637 77.533 46.610 77.011 46.637 76.659 46.728 76.308 46.794 75.912 46.742 75.484 46.794 75.044 46.731 74.643 46.516 74.357 ; #51 2 81.052 -94.110 80.942 -94.956 80.668 -94.412 80.574 -95.269 80.368 -96.082 80.140 -94.995 80.063 -96.242 79.843 -96.330 79.695 -94.896 79.588 -95.049 79.368 -95.286 79.379 -93.692 79.338 -92.099 79.234 -91.115 79.203 -91.082 79.154 -92.643 79.033 -93.879 78.775 -93.522 78.541 -92.522 78.283 -92.236 78.154 -90.956 78.349 -89.973 78.266 -89.209 78.321 -88.654 78.569 -88.313 78.942 -88.055 78.794 -87.835 78.923 -87.027 79.082 -86.176 79.420 -85.440 79.566 -86.676 79.791 -87.154 80.030 -87.473 80.288 -87.665 80.231 -88.516 80.368 -89.165 80.552 -90.093 80.799 -91.110 81.077 -91.758 81.316 -92.780 81.214 -93.725 ; #52 -1 52.981 -98.643 52.791 -98.841 52.549 -98.566 52.313 -98.291 52.066 -98.071 51.978 -97.797 52.033 -97.522 51.835 -97.253 51.593 -97.121 51.541 -96.780 51.269 -96.813 50.975 -96.934 50.676 -96.967 50.484 -96.709 50.720 -96.407 51.091 -96.363 51.324 -96.385 51.574 -96.604 51.832 -96.780 52.104 -96.973 52.363 -97.055 52.657 -97.209 52.934 -97.379 53.203 -97.489 53.464 -97.687 53.736 -97.863 54.003 -97.973 54.269 -97.956 54.302 -98.099 53.997 -98.264 53.794 -98.165 53.813 -98.890 53.505 -99.077 53.223 -99.192 53.060 -98.857 53.055 -98.500 ; #53 1 32.566 131.731 32.819 131.956 33.030 131.945 33.225 131.764 33.374 131.610 33.615 131.599 33.593 131.220 33.797 131.000 33.915 130.852 33.830 130.527 33.629 130.313 33.500 129.989 33.346 129.736 33.132 129.698 32.926 129.808 32.679 129.890 32.786 130.225 33.096 130.297 32.766 130.549 32.544 130.566 32.250 130.418 32.016 130.209 31.720 130.253 31.418 130.231 31.236 130.374 31.272 130.593 31.582 130.566 31.602 130.714 31.299 130.780 31.099 130.824 31.376 131.148 31.541 131.407 31.824 131.467 32.107 131.527 32.352 131.621 ; #54 -1 42.445 -81.709 42.297 -81.896 42.173 -82.258 42.003 -82.566 42.038 -83.005 42.294 -82.989 42.335 -82.538 42.541 -82.555 42.599 -82.797 42.343 -83.000 42.080 -83.192 41.802 -83.368 41.544 -82.934 41.456 -82.780 41.420 -82.456 41.492 -82.066 41.530 -81.687 41.706 -81.368 41.835 -81.027 41.942 -80.659 42.088 -80.236 42.187 -79.962 42.332 -79.621 42.505 -79.308 42.695 -79.022 42.942 -78.896 42.962 -79.033 42.868 -79.429 42.835 -79.813 42.654 -80.242 42.569 -80.385 42.629 -80.764 42.665 -81.148 42.574 -81.511 ; #55 -1 56.206 102.225 56.195 101.907 56.000 101.566 55.830 101.654 55.516 101.863 55.467 102.154 55.184 102.242 55.212 102.319 55.492 102.330 55.690 102.027 55.951 101.973 56.088 102.363 56.104 102.797 55.846 103.027 55.571 103.176 55.291 103.297 55.019 103.214 54.755 103.110 54.456 103.176 54.206 103.011 53.849 103.077 53.723 103.170 53.321 103.374 53.538 103.593 53.723 103.401 53.989 103.170 54.247 103.275 54.475 103.291 54.742 103.159 55.019 103.258 55.299 103.330 55.582 103.231 55.846 103.093 56.179 102.934 56.280 102.473 ; #56 1 50.794 -127.626 50.846 -128.077 50.670 -128.319 50.484 -127.978 50.478 -127.692 50.135 -127.637 50.041 -127.209 49.907 -126.857 49.747 -126.522 49.607 -126.363 49.412 -126.368 49.335 -125.934 49.135 -125.731 48.973 -125.379 49.019 -124.978 49.077 -124.857 48.753 -125.044 48.563 -124.566 48.459 -124.209 48.352 -123.786 48.412 -123.412 48.651 -123.500 48.931 -123.714 49.165 -123.918 49.310 -124.247 49.442 -124.692 49.676 -124.918 49.923 -125.154 50.176 -125.363 50.357 -125.654 50.434 -126.088 50.495 -126.538 50.569 -126.962 50.687 -127.357 ; #57 1 -9.393 125.220 -9.247 125.473 -9.168 125.753 -9.071 126.027 -8.975 126.297 -8.860 126.555 -8.747 126.824 -8.615 127.082 -8.393 127.187 -8.376 126.857 -8.456 126.571 -8.470 126.286 -8.503 126.000 -8.522 125.709 -8.574 125.423 -8.681 125.148 -8.915 124.967 -9.069 124.720 -9.187 124.467 -9.272 124.187 -9.415 123.929 -9.618 123.714 -9.893 123.621 -10.129 123.626 -10.354 123.599 -10.319 123.918 -10.190 124.176 -10.118 124.467 -9.920 124.687 -9.712 124.896 -9.522 125.027 ; #58 -1 54.703 48.962 54.876 49.038 55.069 49.434 55.242 49.813 55.349 50.297 55.426 50.775 55.437 51.242 55.626 51.747 55.720 51.544 55.538 51.357 55.467 50.824 55.442 50.330 55.393 49.852 55.398 49.280 55.198 49.192 54.951 48.885 54.679 48.703 54.475 48.407 54.168 48.456 53.967 48.808 53.706 48.874 53.423 49.077 53.313 48.879 53.280 48.923 53.423 49.571 53.500 49.247 53.739 49.220 54.085 49.500 54.022 49.165 54.082 48.797 54.324 48.538 54.547 48.923 ; #59 2 -80.920 -52.703 -80.871 -51.478 -80.775 -49.775 -80.681 -48.082 -80.585 -46.418 -80.423 -44.945 -80.187 -44.302 -79.975 -43.643 -79.662 -43.352 -79.368 -44.055 -79.102 -43.808 -78.852 -44.978 -78.626 -44.077 -78.321 -44.055 -78.096 -44.940 -77.951 -46.154 -77.959 -47.500 -78.135 -48.626 -78.360 -49.527 -78.618 -50.121 -78.901 -50.467 -79.195 -50.626 -79.484 -50.643 -79.758 -51.181 -80.019 -52.027 -80.209 -53.198 -80.412 -54.335 -80.692 -54.824 -80.907 -53.863 ; #60 1 73.871 -100.055 73.747 -100.637 73.508 -100.995 73.283 -100.423 73.025 -100.319 72.786 -100.566 72.791 -101.363 73.019 -102.066 72.810 -102.681 72.555 -102.247 72.332 -101.632 72.201 -100.852 71.984 -100.275 71.750 -99.720 71.478 -99.341 71.327 -98.720 71.690 -98.269 71.646 -97.505 71.854 -96.725 72.082 -96.593 72.352 -96.555 72.657 -96.742 72.835 -97.209 72.986 -98.137 73.209 -97.945 73.456 -97.396 73.706 -97.049 73.863 -97.764 73.747 -98.868 73.857 -99.648 ; #61 1 71.755 51.418 71.563 51.632 71.514 52.440 71.429 53.368 71.143 53.863 70.852 53.654 70.728 54.522 70.659 55.467 70.643 56.269 70.632 56.984 70.753 57.429 70.978 56.753 71.214 56.220 71.478 55.857 71.755 55.566 72.014 55.385 72.363 55.390 72.585 55.577 72.849 55.885 73.096 56.231 73.321 55.560 73.368 54.621 73.255 53.687 73.000 53.247 72.835 52.676 72.599 52.846 72.294 52.588 72.107 52.088 71.920 51.451 ; #62 -1 48.657 44.555 48.926 44.780 49.184 44.984 49.462 45.104 49.717 45.313 50.008 45.429 50.201 45.753 50.234 46.203 50.302 46.280 50.401 45.890 50.712 45.819 50.953 46.038 51.231 45.901 51.492 46.082 51.695 46.412 51.802 46.681 51.635 46.181 51.404 45.890 51.135 45.841 50.882 45.945 50.648 45.681 50.363 45.764 50.121 45.484 49.852 45.324 49.566 45.093 49.319 44.978 49.055 44.830 48.808 44.610 48.585 44.473 ; #63 1 11.396 119.484 11.214 119.423 10.901 119.346 10.728 119.302 10.464 119.176 10.308 118.978 10.093 118.775 9.868 118.593 9.654 118.385 9.434 118.192 9.255 117.973 9.091 117.731 8.890 117.522 8.522 117.280 8.558 117.511 8.706 117.747 8.885 117.984 9.113 118.170 9.258 118.429 9.481 118.615 9.734 118.736 9.956 118.868 10.060 119.159 10.294 119.335 10.451 119.621 10.714 119.610 10.989 119.527 11.272 119.538 ; #64 -1 61.104 27.901 61.085 28.181 61.310 28.571 61.574 28.709 61.624 29.121 61.799 29.593 62.088 29.692 62.448 29.610 62.245 29.258 62.231 28.791 62.261 28.198 62.593 27.896 62.481 28.484 62.643 28.330 62.948 28.209 63.016 27.714 63.181 27.324 63.464 27.165 63.423 27.137 63.126 27.214 62.860 27.571 62.549 27.495 62.448 27.533 62.286 27.885 62.077 28.264 61.918 28.698 61.788 28.505 61.591 28.187 61.629 27.923 61.637 27.533 61.442 27.319 61.220 27.813 ; #65 1 25.099 121.198 24.964 120.995 24.712 120.830 24.489 120.637 24.236 120.484 23.984 120.330 23.725 120.170 23.429 120.132 23.118 120.088 22.879 120.181 22.582 120.297 22.404 120.511 22.044 120.753 22.277 120.885 22.555 120.978 22.786 121.159 23.030 121.330 23.291 121.434 23.577 121.511 23.863 121.582 24.143 121.654 24.412 121.797 24.670 121.830 25.000 121.901 25.198 121.670 25.187 121.412 ; #66 -1 54.723 -64.407 54.503 -64.390 54.214 -64.418 54.198 -64.885 54.541 -65.165 54.437 -65.187 54.096 -65.011 54.014 -65.330 54.203 -65.769 54.486 -66.198 54.662 -66.313 54.962 -66.462 54.863 -66.522 54.593 -66.577 54.283 -66.445 54.387 -66.374 54.363 -66.148 54.132 -65.780 53.945 -65.445 53.569 -65.302 53.703 -65.231 53.860 -65.044 54.047 -64.604 53.953 -64.170 53.915 -63.654 54.033 -63.280 54.104 -63.473 54.151 -63.846 54.363 -64.159 54.626 -64.330 ; #67 2 74.846 140.357 74.942 141.418 74.907 142.346 74.995 143.220 75.286 142.341 75.596 142.165 75.618 142.753 75.286 142.670 75.091 143.363 75.099 144.412 75.360 144.808 75.613 144.995 75.813 143.813 75.860 142.725 76.071 141.846 76.049 141.275 75.758 140.929 75.712 140.500 75.931 139.786 76.143 138.742 76.041 137.901 75.783 137.412 75.536 137.165 75.277 137.077 74.981 137.676 74.761 138.357 74.775 139.379 74.920 139.819 ; #68 1 -20.624 164.879 -20.431 164.643 -20.283 164.363 -20.181 164.115 -20.228 164.044 -20.470 164.187 -20.725 164.368 -20.934 164.593 -21.115 164.786 -21.349 165.011 -21.527 165.236 -21.665 165.500 -21.797 165.764 -21.964 166.060 -22.148 166.264 -22.269 166.522 -22.357 166.857 -22.184 166.984 -21.986 166.742 -21.813 166.516 -21.637 166.291 -21.467 166.000 -21.346 165.791 -21.162 165.538 -20.926 165.341 -20.750 165.132 ; #69 -1 44.420 -75.923 44.316 -76.247 44.220 -76.615 44.140 -77.187 44.041 -76.995 43.918 -77.214 44.000 -77.604 43.984 -77.978 43.931 -78.368 43.882 -78.764 43.786 -79.126 43.621 -79.462 43.374 -79.703 43.206 -79.495 43.258 -79.115 43.343 -78.742 43.385 -78.346 43.368 -77.951 43.283 -77.566 43.288 -77.143 43.330 -76.797 43.492 -76.456 43.659 -76.214 43.981 -76.198 44.192 -76.220 44.385 -75.874 ; #70 1 -0.261 -48.445 -0.236 -48.648 -0.192 -48.934 -0.154 -49.220 -0.231 -49.473 -0.209 -49.780 -0.148 -50.066 -0.132 -50.352 -0.247 -50.610 -0.588 -50.676 -0.794 -50.775 -1.055 -50.632 -1.151 -50.687 -1.418 -50.786 -1.676 -50.626 -1.821 -50.434 -1.673 -50.286 -1.673 -50.220 -1.734 -49.984 -1.714 -49.714 -1.566 -49.467 -1.525 -49.181 -1.393 -48.918 -1.201 -48.819 -0.975 -48.610 -0.701 -48.511 -0.404 -48.407 ; #71 1 -2.879 128.159 -3.022 128.066 -3.354 127.912 -3.203 128.099 -3.266 128.291 -3.437 128.544 -3.277 128.852 -3.368 129.104 -3.431 129.390 -3.346 129.593 -3.385 129.918 -3.544 130.159 -3.657 130.423 -3.816 130.720 -3.629 130.846 -3.393 130.714 -3.143 130.555 -2.995 130.308 -2.978 130.005 -2.874 129.753 -2.808 129.462 -2.909 129.159 -2.846 128.907 -2.852 128.615 -2.860 128.324 ; #72 1 -8.269 120.269 -8.357 120.132 -8.481 119.890 -8.780 119.868 -8.799 120.159 -8.805 120.440 -8.843 120.742 -8.926 121.011 -8.874 121.324 -8.849 121.599 -8.846 121.868 -8.750 122.148 -8.725 122.445 -8.602 122.753 -8.250 122.890 -8.313 122.819 -8.464 122.555 -8.618 122.335 -8.503 122.066 -8.495 121.802 -8.549 121.538 -8.481 121.258 -8.371 120.989 -8.294 120.687 -8.266 120.423 ; #73 1 38.280 15.588 38.228 15.308 38.157 14.995 38.099 14.648 38.022 14.291 38.011 13.934 38.047 13.582 38.159 13.231 38.096 12.835 38.016 12.549 37.742 12.489 37.571 12.775 37.484 13.121 37.319 13.423 37.173 13.731 37.096 14.066 36.956 14.368 36.758 14.610 36.692 14.967 36.827 15.132 37.110 15.258 37.354 15.137 37.635 15.181 37.890 15.330 38.143 15.533 ; #74 -1 62.893 34.527 62.610 34.802 62.582 35.137 62.354 35.527 62.148 35.187 62.374 34.676 62.179 34.665 62.162 34.429 62.431 34.110 62.382 34.060 62.124 34.352 61.841 34.473 61.599 34.753 61.445 35.253 61.148 35.577 61.148 35.055 61.041 35.060 60.923 35.747 61.085 36.203 61.308 36.407 61.566 36.165 61.841 35.901 62.104 35.731 62.412 35.802 62.618 35.456 62.788 34.918 ; #75 1 -2.676 150.819 -2.786 150.912 -2.901 151.176 -3.063 151.418 -3.225 151.654 -3.407 151.885 -3.505 152.154 -3.692 152.363 -3.918 152.544 -4.181 152.670 -4.470 152.692 -4.750 152.835 -4.651 153.033 -4.376 153.099 -4.121 153.022 -3.929 152.824 -3.780 152.577 -3.588 152.385 -3.390 152.154 -3.217 151.934 -3.080 151.687 -2.926 151.434 -2.813 151.176 -2.651 150.934 ; #76 1 -8.379 117.209 -8.431 117.077 -8.602 116.830 -8.912 116.780 -9.077 116.967 -9.049 117.247 -9.005 117.538 -8.926 117.819 -8.860 118.093 -8.706 118.335 -8.764 118.429 -8.802 118.775 -8.676 119.055 -8.404 119.011 -8.409 118.742 -8.319 118.621 -8.316 118.324 -8.137 118.088 -8.179 117.791 -8.420 117.923 -8.541 118.187 -8.665 118.137 -8.690 117.846 -8.495 117.615 -8.431 117.368 ; #77 1 19.909 109.544 19.874 109.401 19.750 109.220 19.541 108.973 19.365 108.720 19.132 108.643 18.835 108.654 18.544 108.725 18.385 108.995 18.299 109.264 18.234 109.604 18.401 109.907 18.486 110.088 18.684 110.357 18.865 110.495 19.162 110.566 19.500 110.780 19.648 110.967 19.940 110.923 20.038 110.621 20.016 110.363 19.970 110.038 19.973 109.753 ; #78 1 73.959 -95.269 73.775 -94.989 73.706 -95.308 73.503 -95.637 73.184 -95.599 72.896 -95.654 72.637 -95.407 72.363 -95.181 72.077 -95.011 72.063 -94.115 72.371 -93.648 72.695 -93.918 72.777 -93.214 72.753 -92.214 73.000 -91.648 73.255 -91.357 73.530 -90.885 73.808 -90.368 73.967 -90.797 73.995 -91.868 74.071 -92.604 74.140 -93.648 74.085 -94.621 ; #79 -1 23.838 32.846 23.596 32.758 23.478 32.802 23.269 32.808 22.997 32.626 22.750 32.489 22.725 32.236 22.687 31.962 22.522 31.736 22.266 31.522 22.041 31.352 21.780 31.203 21.659 31.170 22.000 31.390 22.242 31.604 22.393 31.824 22.610 32.005 22.610 32.291 22.777 32.560 22.975 32.747 23.036 32.940 23.338 32.967 23.613 32.962 23.890 32.901 ; #80 2 76.591 -100.560 76.360 -100.357 76.058 -99.923 76.104 -100.566 76.360 -101.593 76.184 -101.791 75.882 -101.352 75.830 -101.709 75.703 -102.412 75.541 -102.335 75.604 -101.110 75.681 -99.582 75.549 -99.945 75.330 -100.434 75.052 -100.225 75.025 -99.198 75.104 -98.066 75.376 -97.841 75.541 -97.396 75.797 -97.676 76.121 -97.566 76.409 -97.753 76.558 -98.753 76.599 -99.747 ; #81 1 41.212 9.176 41.060 8.962 40.885 8.665 40.865 8.258 40.607 8.214 40.357 8.418 40.074 8.434 39.799 8.489 39.508 8.423 39.184 8.418 39.008 8.489 38.904 8.786 39.159 9.055 39.168 9.368 39.258 9.588 39.544 9.643 39.838 9.687 40.113 9.676 40.379 9.731 40.640 9.753 40.926 9.610 41.154 9.418 ; #82 1 34.181 134.615 34.253 134.374 34.357 134.082 34.264 133.725 34.082 133.593 33.953 133.291 34.036 132.934 33.805 132.703 33.591 132.489 33.412 132.165 33.412 132.253 33.258 132.445 32.992 132.500 32.783 132.813 32.942 133.027 33.184 133.214 33.396 133.390 33.503 133.720 33.354 134.110 33.566 134.346 33.750 134.610 33.920 134.659 ; #83 -1 63.091 25.577 62.953 25.830 62.673 25.769 62.407 25.868 62.137 25.643 61.893 25.412 61.646 25.308 61.357 25.308 61.099 25.456 61.176 26.016 61.275 25.753 61.511 25.621 61.799 25.665 62.060 25.824 62.387 26.253 62.492 26.736 62.723 26.967 62.929 26.830 62.739 26.566 62.519 26.225 62.500 25.962 62.728 26.110 62.964 26.044 ; #84 -1 58.580 -110.973 58.670 -110.473 58.918 -110.132 59.049 -109.637 59.107 -109.104 59.129 -108.538 59.203 -107.962 59.310 -107.533 59.272 -106.918 59.261 -106.291 59.283 -106.423 59.324 -106.956 59.385 -107.511 59.445 -108.082 59.415 -108.615 59.497 -108.962 59.577 -109.489 59.379 -109.868 59.170 -110.302 58.981 -110.692 58.764 -111.115 ; #85 2 77.335 -118.901 77.179 -119.505 76.940 -120.176 76.706 -120.907 76.475 -121.654 76.297 -122.637 76.063 -122.577 76.041 -121.099 75.945 -120.522 75.907 -119.835 76.192 -119.418 76.442 -118.720 76.706 -118.214 76.624 -117.901 76.338 -117.670 76.484 -116.896 76.706 -116.077 76.973 -116.104 77.247 -115.808 77.475 -116.071 77.404 -116.951 77.360 -117.973 ; #86 -1 47.723 84.297 47.868 84.407 48.063 84.137 48.291 83.736 48.459 83.637 48.753 83.489 48.962 83.742 49.129 84.253 49.330 84.071 49.585 83.830 49.607 83.577 49.456 83.692 49.294 84.060 49.091 84.011 48.964 83.599 48.714 83.429 48.423 83.467 48.239 83.187 48.077 83.297 47.970 83.698 47.810 84.060 ; #87 1 46.923 -60.423 46.953 -60.637 46.692 -60.951 46.464 -61.104 46.214 -61.346 45.962 -61.511 45.673 -61.412 45.582 -61.115 45.599 -60.720 45.690 -60.308 45.874 -60.000 46.113 -59.907 46.195 -60.368 45.973 -60.582 45.742 -60.725 45.777 -60.989 45.981 -60.923 46.214 -60.560 46.434 -60.462 46.698 -60.346 ; #88 -1 13.055 15.110 13.126 14.912 13.247 14.648 13.201 14.363 13.354 14.187 13.376 13.995 13.481 13.797 13.769 13.830 13.953 13.599 13.830 13.308 13.527 13.368 13.280 13.511 13.110 13.736 12.973 13.835 12.731 13.852 12.508 14.088 12.635 14.286 12.808 14.527 12.890 14.775 12.945 15.082 ; #89 1 35.302 26.297 35.223 26.126 35.220 25.769 35.316 25.478 35.363 25.121 35.412 24.791 35.371 24.412 35.516 24.126 35.577 23.725 35.434 23.560 35.245 23.676 35.209 24.044 35.168 24.390 35.025 24.714 34.940 25.011 34.978 25.357 35.005 25.709 35.019 26.066 35.179 26.286 ; #90 2 80.321 24.500 80.220 23.659 80.368 22.940 80.129 22.374 80.209 21.495 80.390 20.286 80.368 19.698 80.209 19.027 80.030 18.390 79.769 18.786 79.769 21.280 79.610 20.440 79.420 20.709 79.368 22.379 79.214 23.687 79.357 25.055 79.566 25.951 79.813 26.852 80.096 26.956 80.231 25.390 ; #91 -1 46.690 -100.769 46.525 -100.621 46.231 -100.610 45.970 -100.555 45.687 -100.484 45.429 -100.473 45.332 -100.462 45.096 -100.374 44.863 -100.588 44.786 -100.995 44.745 -100.962 44.541 -100.582 44.668 -100.566 44.934 -100.374 45.168 -100.269 45.467 -100.341 45.728 -100.346 45.975 -100.467 46.255 -100.560 46.563 -100.577 ; #92 1 10.909 123.516 10.956 123.346 10.920 123.066 10.695 122.945 10.431 122.846 10.118 122.835 9.975 122.588 9.772 122.418 9.522 122.533 9.354 122.780 9.113 122.962 9.124 123.214 9.382 123.275 9.629 123.159 9.934 123.198 10.203 123.319 10.470 123.423 10.742 123.544 ; #93 -1 74.571 103.137 74.687 104.115 74.783 105.203 74.854 105.269 74.951 104.198 74.681 103.302 74.637 102.269 74.659 101.198 74.885 100.571 75.008 100.302 74.602 100.418 74.415 99.758 74.357 99.643 74.280 100.670 74.000 101.044 73.926 101.374 74.266 101.143 74.409 101.203 74.352 102.044 74.508 102.527 ; #94 1 -1.500 105.868 -1.657 105.758 -1.637 105.632 -1.668 105.396 -1.959 105.214 -2.115 105.385 -2.124 105.676 -2.349 105.835 -2.599 105.918 -2.830 106.044 -2.934 106.324 -3.074 106.571 -2.973 106.670 -2.643 106.731 -2.516 106.577 -2.407 106.313 -2.135 106.192 -1.846 106.137 -1.588 105.995 ; #95 -1 56.703 -124.791 56.505 -124.582 56.146 -124.341 55.997 -124.170 55.805 -123.868 55.596 -123.500 55.288 -123.225 55.360 -123.198 55.599 -123.440 55.843 -123.725 56.014 -123.555 56.027 -123.033 56.071 -122.434 56.129 -122.555 56.055 -123.060 56.030 -123.527 56.165 -124.022 56.346 -124.346 56.596 -124.599 ; #96 2 -72.201 -102.258 -72.245 -101.544 -72.294 -100.626 -72.390 -99.588 -72.508 -98.830 -72.516 -97.819 -72.560 -96.912 -72.473 -96.104 -72.258 -96.104 -72.201 -96.747 -72.044 -96.604 -71.879 -96.951 -72.063 -97.445 -72.058 -98.082 -71.865 -98.621 -71.995 -99.060 -72.058 -99.566 -71.995 -100.308 -71.970 -101.225 -72.063 -102.247 ; #97 -1 4.599 36.038 4.365 35.918 4.074 35.896 3.794 35.846 3.516 35.912 3.261 36.044 3.016 36.176 2.805 36.385 2.495 36.571 2.695 36.698 2.901 36.582 3.096 36.368 3.349 36.242 3.646 36.225 3.929 36.209 4.220 36.220 4.514 36.198 ; #98 -1 61.720 30.780 61.505 30.407 61.255 30.016 61.036 30.203 60.794 30.500 60.525 30.720 60.269 30.956 59.975 31.253 60.154 31.643 60.190 32.176 60.288 32.599 60.536 32.775 60.821 32.786 61.077 32.533 61.275 32.060 61.451 31.610 61.643 31.192 ; #99 2 79.357 -103.819 79.327 -104.780 79.143 -105.538 78.923 -104.549 78.714 -103.725 78.541 -104.055 78.407 -104.863 78.283 -103.824 78.302 -102.571 78.181 -101.214 77.923 -100.626 77.849 -99.462 78.115 -99.165 78.387 -99.714 78.657 -99.896 78.863 -100.940 79.003 -102.324 79.255 -103.132 ; #100 -1 49.393 43.648 49.170 43.841 48.942 43.753 48.717 43.484 48.492 43.143 48.231 42.951 47.997 42.835 47.909 42.434 47.712 42.209 47.626 42.478 47.764 42.945 47.907 43.099 48.170 43.176 48.445 43.445 48.670 43.604 48.918 43.769 49.159 43.907 49.379 43.670 ; #101 1 35.684 34.588 35.626 34.418 35.500 34.110 35.393 33.780 35.335 33.434 35.346 33.033 35.176 32.780 35.080 32.401 34.863 32.357 34.679 32.604 34.626 32.962 34.725 33.313 34.860 33.599 34.973 33.934 35.187 33.951 35.409 34.159 35.582 34.451 ; #102 1 12.571 124.291 12.412 124.324 12.154 124.445 11.981 124.698 11.799 124.907 11.591 124.934 11.415 124.951 11.203 125.170 11.129 125.588 11.363 125.582 11.668 125.478 11.940 125.473 12.214 125.451 12.434 125.291 12.560 125.016 12.519 124.747 12.538 124.445 ; #103 -1 -17.912 27.104 -17.698 27.269 -17.516 27.500 -17.258 27.676 -17.091 27.929 -16.931 28.104 -16.813 28.396 -16.673 28.808 -16.525 28.571 -16.613 28.275 -16.799 28.044 -16.929 27.769 -17.121 27.593 -17.385 27.390 -17.607 27.264 -17.846 27.093 ; #104 -1 59.234 56.209 58.997 55.962 58.783 56.082 58.602 55.621 58.582 55.632 58.533 56.088 58.245 56.319 57.890 56.742 58.129 56.830 58.247 56.555 58.555 56.264 58.854 56.456 59.126 56.280 59.346 56.632 59.624 56.610 59.750 56.571 59.374 56.495 ; #105 -1 56.291 -103.242 56.415 -103.005 56.591 -102.544 56.799 -102.297 57.063 -102.016 57.352 -102.000 57.786 -101.709 58.016 -101.901 57.959 -102.198 57.709 -102.588 57.401 -102.863 57.168 -102.709 56.772 -102.687 56.591 -102.962 56.745 -103.077 56.651 -103.165 56.445 -103.275 ; #106 1 18.214 -78.291 18.146 -78.049 17.948 -77.824 17.852 -77.555 17.780 -77.214 17.909 -76.896 17.904 -76.654 17.882 -76.324 18.060 -76.297 18.203 -76.538 18.321 -76.813 18.412 -77.093 18.464 -77.396 18.495 -77.692 18.467 -77.989 18.382 -78.275 ; #107 1 11.865 121.923 11.703 122.027 11.423 122.066 11.135 122.049 10.849 121.967 10.552 121.962 10.522 122.077 10.657 122.330 10.739 122.610 10.937 122.813 11.121 123.033 11.453 123.143 11.505 122.929 11.563 122.665 11.687 122.407 11.821 122.148 ; #108 1 -9.558 118.984 -9.736 119.187 -9.769 119.473 -9.863 119.736 -10.025 119.978 -10.217 120.192 -10.266 120.484 -10.148 120.758 -9.920 120.725 -9.701 120.522 -9.582 120.264 -9.379 120.016 -9.365 119.758 -9.368 119.467 -9.393 119.176 ; #109 2 79.379 99.676 79.684 99.857 79.953 99.533 79.953 98.407 79.865 97.681 80.129 96.962 80.063 95.291 79.854 94.352 79.566 93.324 79.473 93.863 79.124 94.835 79.011 96.126 78.852 97.456 78.802 98.824 79.003 99.780 79.234 99.308 ; #110 -1 54.643 90.956 54.423 91.220 54.151 91.434 53.871 91.445 53.898 91.604 54.047 91.599 54.360 91.495 54.596 91.110 54.865 90.995 55.041 91.319 55.104 91.786 55.327 92.396 55.291 92.143 55.162 91.720 55.074 91.242 54.882 90.940 ; #111 1 69.885 -97.973 69.742 -98.247 69.484 -98.357 69.228 -98.709 69.058 -99.407 68.871 -98.973 68.758 -98.275 68.571 -97.429 68.497 -96.758 68.571 -96.066 68.739 -95.522 68.887 -95.637 69.132 -96.104 69.379 -96.440 69.596 -97.143 69.764 -97.555 ; #112 1 13.547 92.995 13.360 92.874 13.077 92.830 12.777 92.769 12.511 92.720 12.225 92.725 11.920 92.593 11.621 92.643 11.687 92.742 11.989 92.769 12.283 92.879 12.511 92.956 12.871 92.940 13.082 93.000 13.368 93.038 ; #113 2 77.997 100.104 78.162 101.302 78.209 102.665 78.302 104.110 78.453 105.154 78.764 105.011 78.951 104.302 79.093 103.368 78.981 102.626 79.327 102.247 79.063 101.198 78.802 100.780 78.549 100.192 78.275 99.802 78.041 99.396 ; #114 1 11.253 124.060 11.129 123.962 10.854 123.890 10.596 123.753 10.338 123.621 10.080 123.467 9.835 123.379 9.533 123.330 9.525 123.445 9.788 123.566 10.060 123.676 10.277 123.885 10.495 124.033 10.786 124.038 11.071 124.038 ; #115 -1 53.148 -100.544 53.104 -100.896 52.915 -100.984 52.879 -100.648 52.758 -100.280 52.580 -100.027 52.305 -100.143 51.915 -100.038 51.692 -99.813 51.813 -99.725 52.096 -99.802 52.363 -99.747 52.646 -99.670 52.912 -99.775 53.080 -100.220 ; #116 1 -5.558 154.736 -5.835 154.731 -6.071 154.885 -6.261 155.093 -6.489 155.214 -6.723 155.346 -6.854 155.610 -6.758 155.896 -6.475 155.874 -6.250 155.659 -6.099 155.445 -5.868 155.247 -5.610 155.077 -5.500 154.830 ; #117 1 56.349 -133.599 56.212 -133.495 55.956 -133.220 55.668 -133.192 55.376 -133.071 55.220 -132.802 55.005 -132.500 54.775 -132.236 54.901 -132.005 55.151 -132.099 55.464 -132.385 55.648 -132.390 55.912 -132.626 56.104 -133.016 56.310 -133.313 ; #118 1 72.907 122.874 72.797 123.769 72.662 124.615 72.478 125.368 72.409 126.165 72.747 126.319 73.019 126.555 73.321 126.456 73.484 125.896 73.646 125.055 73.712 124.066 73.544 123.401 73.176 123.484 72.981 122.923 ; #119 1 46.984 -64.104 46.758 -64.346 46.563 -64.154 46.376 -63.852 46.217 -63.549 46.223 -63.126 46.060 -62.896 46.110 -62.533 46.360 -62.253 46.459 -62.566 46.429 -62.929 46.473 -63.363 46.503 -63.753 46.632 -63.918 46.885 -64.016 ; #120 -1 -21.495 -45.544 -21.374 -45.747 -21.104 -45.879 -20.835 -46.049 -20.745 -45.868 -20.967 -45.593 -21.069 -45.330 -20.995 -45.412 -20.717 -45.610 -20.637 -45.780 -20.670 -46.121 -20.827 -46.148 -21.069 -46.055 -21.327 -46.071 -21.374 -45.945 -21.473 -45.687 ; #121 -1 51.786 -99.170 51.709 -99.357 51.574 -99.363 51.302 -99.022 51.088 -98.901 50.841 -98.791 50.569 -98.610 50.272 -98.495 50.261 -98.093 50.492 -98.011 50.731 -98.269 50.912 -98.643 51.154 -98.654 51.511 -98.857 51.651 -99.060 ; #122 1 49.863 -63.698 49.890 -64.280 49.739 -64.154 49.591 -63.764 49.379 -63.484 49.236 -63.077 49.148 -62.654 49.080 -62.225 49.168 -61.791 49.396 -62.099 49.552 -62.473 49.698 -62.857 49.802 -63.280 ; #123 1 -49.602 70.192 -49.453 69.852 -49.374 70.159 -49.354 70.434 -49.110 70.341 -49.239 69.813 -49.129 69.500 -49.069 69.187 -48.813 69.027 -49.014 68.819 -49.275 68.846 -49.602 68.824 -49.585 69.148 -49.585 69.615 -49.648 69.879 ; #124 1 13.467 120.324 13.335 120.456 13.124 120.670 12.849 120.780 12.607 120.901 12.338 121.066 12.280 121.297 12.481 121.456 12.758 121.505 13.069 121.495 13.294 121.341 13.440 121.071 13.486 120.813 13.508 120.511 ; #125 1 73.692 -80.813 73.470 -80.841 73.228 -80.401 72.973 -80.082 72.772 -79.445 72.857 -78.500 72.876 -77.544 72.830 -76.544 73.011 -76.269 73.269 -76.747 73.503 -77.313 73.646 -78.231 73.646 -79.269 73.734 -80.253 ; #126 1 -43.371 -73.791 -43.168 -73.670 -42.937 -73.582 -42.690 -73.681 -42.478 -73.720 -42.231 -73.456 -41.912 -73.538 -41.841 -73.896 -42.030 -74.055 -42.310 -74.170 -42.596 -74.176 -42.893 -74.209 -43.179 -74.341 -43.349 -74.082 ; #127 2 -80.810 -61.588 -80.599 -60.582 -80.321 -60.253 -80.030 -60.198 -79.725 -60.264 -79.706 -61.319 -79.997 -61.725 -80.231 -62.478 -80.288 -64.170 -80.187 -66.407 -80.448 -66.022 -80.481 -64.330 -80.703 -63.055 ; #128 1 57.827 -153.253 57.772 -153.604 57.519 -153.775 57.596 -154.093 57.519 -154.560 57.275 -154.676 56.973 -154.423 57.022 -154.269 57.080 -154.027 56.912 -153.918 56.989 -153.648 57.217 -153.264 57.396 -152.852 57.464 -152.467 57.687 -152.385 57.843 -152.676 57.915 -152.973 ; #129 -1 48.135 -103.192 48.104 -103.588 48.055 -103.604 48.099 -103.176 48.080 -102.758 47.846 -102.560 47.604 -102.302 47.489 -101.868 47.563 -101.308 47.593 -101.500 47.563 -101.907 47.819 -102.275 47.912 -102.571 48.140 -102.786 ; #130 1 -17.005 178.742 -16.901 178.929 -16.755 179.154 -16.788 179.407 -16.659 179.841 -16.695 179.604 -16.571 179.599 -16.247 179.901 -16.231 179.665 -16.349 179.412 -16.434 179.132 -16.558 178.857 -16.684 178.577 -16.863 178.621 ; #131 1 -7.385 138.544 -7.420 138.368 -7.549 138.110 -7.772 137.929 -8.027 137.791 -8.308 137.670 -8.390 137.802 -8.390 138.093 -8.393 138.385 -8.223 138.632 -8.041 138.857 -7.780 138.978 -7.536 138.962 -7.374 138.703 ; #132 1 20.236 -155.874 20.022 -155.857 19.750 -156.000 19.456 -155.918 19.162 -155.896 18.995 -155.670 19.176 -155.429 19.294 -155.159 19.456 -154.874 19.695 -154.989 19.931 -155.148 20.085 -155.412 20.198 -155.692 ; #133 1 42.997 9.374 42.783 9.291 42.640 8.951 42.437 8.643 42.159 8.637 41.868 8.703 41.626 8.835 41.470 9.187 41.720 9.374 42.014 9.467 42.297 9.549 42.591 9.489 42.871 9.467 ; #134 1 54.132 -131.681 54.014 -132.022 53.805 -132.247 53.679 -132.379 54.027 -132.429 54.143 -132.830 54.008 -133.088 53.706 -132.995 53.440 -132.681 53.250 -132.588 53.203 -132.187 53.431 -131.923 53.714 -131.885 53.981 -131.714 ; #135 -1 -15.376 -69.544 -15.297 -69.714 -15.538 -69.857 -15.725 -69.989 -15.876 -69.819 -15.995 -69.560 -16.190 -69.407 -16.162 -69.115 -16.385 -68.962 -16.327 -68.692 -16.096 -68.830 -15.890 -68.978 -15.681 -69.198 -15.489 -69.407 ; #136 1 11.442 124.330 11.190 124.401 10.948 124.511 10.821 124.758 10.541 124.764 10.165 124.901 10.286 125.126 10.508 125.192 10.775 125.049 11.069 125.044 11.335 124.962 11.338 124.709 11.437 124.467 ; #137 1 18.247 -67.198 17.986 -67.121 17.967 -66.797 17.967 -66.489 17.945 -66.192 18.016 -65.890 18.277 -65.676 18.445 -65.967 18.462 -66.209 18.486 -66.522 18.489 -66.835 18.464 -67.137 ; #138 1 -18.255 178.071 -18.176 178.264 -18.115 178.538 -17.923 178.637 -17.648 178.544 -17.440 178.308 -17.354 178.093 -17.420 177.764 -17.533 177.516 -17.764 177.374 -18.030 177.302 -18.170 177.555 -18.247 177.857 ; #139 -1 -15.657 30.780 -15.695 30.945 -15.761 31.231 -15.717 31.533 -15.717 31.835 -15.681 32.132 -15.593 32.522 -15.544 32.390 -15.588 32.093 -15.610 31.808 -15.618 31.495 -15.668 31.209 -15.646 30.912 ; #140 1 -50.033 -74.703 -49.909 -74.511 -49.662 -74.511 -49.343 -74.456 -49.033 -74.489 -48.766 -74.643 -48.879 -74.945 -49.206 -74.923 -49.374 -75.275 -49.723 -75.148 -49.500 -74.863 -49.632 -74.824 -49.918 -74.802 ; #141 1 45.503 148.681 45.349 148.418 45.324 148.016 45.209 147.802 45.016 147.505 44.783 147.181 44.541 146.945 44.505 147.077 44.703 147.368 44.920 147.659 45.063 148.016 45.231 148.352 45.374 148.758 ; #142 -1 11.360 4.137 11.209 4.313 11.066 4.566 10.810 4.687 10.593 4.522 10.335 4.440 10.019 4.533 10.091 4.599 10.360 4.659 10.624 4.681 10.918 4.703 11.143 4.505 11.272 4.247 ; #143 -1 54.217 -100.269 53.953 -100.341 53.717 -100.363 53.500 -100.698 53.280 -100.484 53.118 -100.088 53.118 -99.610 53.217 -99.396 53.283 -99.681 53.376 -99.940 53.659 -100.088 53.901 -99.725 53.904 -99.978 54.121 -100.038 ; #144 -1 51.335 -73.005 51.266 -73.319 51.071 -73.676 50.882 -73.901 50.495 -73.989 50.181 -73.995 50.324 -73.830 50.547 -73.797 50.805 -73.610 51.069 -73.280 50.912 -73.335 50.978 -73.159 51.176 -72.830 51.206 -72.907 51.258 -72.951 ; #145 1 58.327 -134.934 58.110 -134.791 57.805 -134.709 57.462 -134.473 57.165 -134.495 57.310 -134.066 57.508 -133.967 57.937 -134.225 57.725 -133.951 57.843 -133.945 58.107 -134.209 58.231 -134.692 ; #146 1 70.283 -54.544 70.014 -54.615 69.764 -54.736 69.582 -54.560 69.522 -53.714 69.423 -53.940 69.272 -53.725 69.341 -52.951 69.473 -52.220 69.706 -51.967 69.918 -52.621 70.140 -53.148 70.277 -53.901 ; #147 -1 12.085 -85.846 11.893 -85.912 11.629 -85.857 11.354 -85.720 11.195 -85.484 11.104 -85.203 11.055 -84.901 11.261 -84.813 11.492 -84.973 11.712 -85.170 11.885 -85.407 12.049 -85.637 ; #148 -1 1.063 30.604 1.266 30.769 1.495 30.956 1.637 31.203 1.871 31.368 2.253 31.412 2.184 31.275 1.992 31.060 1.819 30.830 1.618 30.621 1.387 30.445 1.159 30.484 ; #149 2 81.201 95.060 81.005 93.462 80.764 92.885 80.459 92.330 80.310 92.110 80.187 92.692 80.074 94.346 80.198 95.863 80.332 97.187 80.657 97.440 80.871 97.302 81.115 96.341 81.277 95.775 ; #150 -1 59.115 38.132 59.022 37.632 58.854 37.918 58.624 37.890 58.720 37.313 58.613 37.374 58.376 37.769 58.143 38.242 58.154 38.648 58.398 38.956 58.610 38.632 58.838 38.280 ; #151 1 -7.637 158.527 -7.854 158.720 -8.030 158.945 -8.173 159.203 -8.302 159.462 -8.478 159.775 -8.357 159.797 -8.146 159.588 -7.989 159.346 -7.876 159.082 -7.701 158.846 -7.577 158.610 ; #152 1 68.157 -75.022 68.253 -75.335 68.321 -76.093 68.203 -76.758 67.942 -77.115 67.662 -77.280 67.385 -77.154 67.236 -76.615 67.280 -75.863 67.440 -75.253 67.714 -75.060 68.003 -75.088 ; #153 -1 -33.582 -53.516 -33.448 -53.456 -33.140 -53.363 -32.934 -53.159 -32.846 -52.967 -32.788 -52.703 -32.363 -52.692 -32.500 -52.951 -32.714 -53.225 -32.931 -53.385 -33.148 -53.604 -33.448 -53.566 ; #154 -1 49.984 -94.593 49.813 -94.610 49.571 -94.907 49.321 -94.978 49.099 -95.225 48.926 -95.115 48.896 -94.681 49.124 -94.225 49.332 -94.593 49.368 -94.187 49.591 -94.308 49.821 -94.495 ; #155 2 -79.791 -158.714 -79.525 -158.885 -79.275 -159.687 -79.041 -160.621 -78.802 -161.489 -78.794 -162.824 -79.063 -163.632 -79.349 -163.593 -79.588 -162.720 -79.769 -161.473 -79.854 -159.940 ; #156 2 -73.857 -118.742 -73.788 -119.676 -73.761 -120.703 -73.673 -121.687 -73.651 -122.808 -73.898 -122.588 -74.203 -122.527 -74.365 -122.005 -74.288 -120.984 -74.203 -119.984 -74.085 -119.055 ; #157 1 58.255 -135.830 58.154 -136.198 57.934 -136.264 57.679 -136.121 57.459 -135.819 57.629 -135.676 57.662 -135.527 57.489 -135.038 57.646 -134.885 57.852 -135.511 57.808 -135.198 57.940 -135.027 58.063 -135.445 58.077 -135.654 ; #158 1 -0.027 -91.500 -0.291 -91.335 -0.588 -91.176 -0.788 -91.423 -0.995 -91.379 -1.003 -91.088 -0.838 -90.852 -0.580 -90.934 -0.335 -91.066 -0.096 -91.209 0.107 -91.363 ; #159 1 -3.192 126.038 -3.462 126.088 -3.651 126.291 -3.780 126.555 -3.794 126.830 -3.681 127.093 -3.467 127.236 -3.272 127.077 -3.096 126.841 -3.069 126.549 -3.129 126.258 ; #160 1 70.863 179.187 70.956 -179.951 70.945 -179.093 71.025 -178.198 71.228 -177.610 71.473 -178.187 71.574 -179.016 71.538 -179.923 71.363 179.346 71.137 178.764 70.898 178.736 ; #161 1 38.904 23.033 38.742 23.335 38.519 23.593 38.387 23.907 38.223 24.148 38.025 24.445 38.176 24.385 38.418 24.209 38.651 24.049 38.747 23.681 38.929 23.412 ; #162 1 41.049 -71.989 41.030 -72.390 40.986 -72.703 40.956 -73.093 40.923 -73.445 40.698 -73.841 40.626 -73.582 40.720 -73.165 40.786 -72.764 40.868 -72.440 40.989 -72.077 ; #163 1 63.049 -169.527 63.206 -169.016 63.341 -169.231 63.440 -169.769 63.621 -170.198 63.615 -170.890 63.670 -171.500 63.555 -171.813 63.360 -171.467 63.379 -170.698 63.258 -170.258 63.080 -169.830 ; #164 1 -54.876 -36.016 -54.755 -35.934 -54.486 -36.077 -54.275 -36.456 -54.115 -36.813 -54.044 -37.280 -54.003 -37.819 -54.093 -37.720 -54.206 -37.330 -54.368 -36.912 -54.538 -36.527 -54.783 -36.225 ; #165 1 -52.223 -59.478 -52.102 -59.143 -51.962 -58.775 -51.830 -58.302 -51.712 -57.896 -51.522 -57.929 -51.522 -58.242 -51.431 -58.440 -51.324 -58.830 -51.607 -59.055 -51.780 -59.313 -51.997 -59.577 ; #166 -1 25.437 -97.500 25.291 -97.659 24.992 -97.692 24.739 -97.692 24.470 -97.769 24.016 -97.747 24.154 -97.725 24.445 -97.681 24.728 -97.615 25.008 -97.538 25.291 -97.445 ; #167 -1 42.714 77.929 42.679 77.626 42.654 77.236 42.588 76.857 42.420 76.379 42.250 76.703 42.168 77.060 42.176 77.467 42.332 77.813 42.621 78.154 ; #168 1 -4.404 123.016 -4.580 122.874 -4.871 122.835 -5.148 122.775 -5.412 122.637 -5.648 122.703 -5.527 122.890 -5.379 123.099 -5.195 123.077 -5.036 122.978 -4.772 123.132 -4.525 123.143 ; #169 2 -79.588 -71.659 -79.599 -70.698 -79.349 -69.797 -79.082 -69.137 -78.843 -68.280 -78.560 -67.495 -78.511 -68.407 -78.695 -69.571 -78.893 -70.676 -79.132 -71.538 -79.409 -71.824 ; #170 1 56.088 12.423 55.865 12.022 55.860 11.654 55.717 11.115 55.437 11.143 55.225 11.330 55.060 11.830 55.179 12.165 55.423 12.280 55.648 12.484 55.931 12.549 ; #171 1 -54.945 -68.489 -54.973 -68.857 -55.049 -69.407 -55.190 -69.769 -55.418 -69.401 -55.261 -69.352 -55.209 -69.099 -55.390 -68.841 -55.555 -68.242 -55.319 -68.423 -55.124 -68.791 -55.085 -68.516 ; #172 2 75.459 146.302 75.179 146.352 74.986 147.302 74.819 148.187 74.766 149.286 74.876 150.341 75.126 150.555 75.255 149.440 75.316 148.495 75.390 147.412 75.467 146.698 ; #173 1 72.522 126.698 72.714 127.478 72.868 128.291 73.104 128.923 73.316 128.275 73.489 127.588 73.423 126.775 73.129 126.709 72.857 126.412 72.560 126.357 72.409 126.478 ; #174 1 -8.176 114.467 -8.371 114.626 -8.470 114.907 -8.745 115.165 -8.602 115.385 -8.409 115.637 -8.170 115.473 -8.091 115.187 -8.184 114.907 -8.126 114.615 ; #175 -1 53.901 81.236 53.981 81.346 54.217 81.725 54.379 82.121 54.541 82.533 54.723 83.066 54.799 82.901 54.618 82.456 54.409 82.088 54.247 81.703 54.041 81.341 ; #176 1 -8.343 160.654 -8.527 160.670 -8.805 160.720 -9.080 160.830 -9.286 161.027 -9.522 161.291 -9.382 161.302 -9.140 161.225 -8.904 161.071 -8.659 160.962 -8.407 160.824 ; #177 -1 59.343 13.852 59.352 13.335 59.063 13.137 58.962 12.654 58.766 12.495 58.492 12.445 58.418 12.615 58.560 13.099 58.679 13.632 58.890 13.962 59.129 14.033 ; #178 2 -74.071 -123.797 -73.794 -124.121 -73.665 -124.907 -73.423 -125.560 -73.250 -126.346 -73.354 -127.220 -73.610 -127.005 -73.780 -126.214 -73.995 -125.505 -74.132 -124.593 ; #179 1 -9.305 159.632 -9.516 159.626 -9.745 159.791 -9.821 160.077 -9.852 160.374 -9.863 160.714 -9.613 160.626 -9.448 160.374 -9.429 160.077 -9.332 159.824 ; #180 1 -6.898 112.907 -7.033 112.747 -7.181 112.885 -7.203 113.154 -7.212 113.495 -7.118 113.736 -7.027 113.984 -6.887 113.956 -6.890 113.665 -6.890 113.374 -6.887 113.082 ; #181 -1 -46.926 -72.808 -46.725 -72.511 -46.563 -72.176 -46.516 -71.764 -46.580 -71.330 -46.451 -71.319 -46.338 -71.769 -46.484 -72.115 -46.563 -72.555 -46.626 -72.698 -46.879 -72.846 ; #182 1 -52.118 -60.857 -52.165 -60.538 -51.992 -60.121 -51.830 -59.747 -51.484 -59.418 -51.423 -59.890 -51.437 -60.423 -51.687 -60.352 -51.879 -60.440 -52.003 -60.802 ; #183 2 75.613 -95.110 75.437 -95.830 75.234 -96.220 74.964 -96.264 74.783 -95.473 74.643 -94.544 74.731 -93.555 75.030 -93.495 75.316 -93.687 75.558 -94.346 ; #184 1 -11.885 131.027 -11.742 131.242 -11.516 131.467 -11.261 131.363 -11.330 131.126 -11.368 130.797 -11.291 130.522 -11.442 130.429 -11.692 130.571 -11.852 130.819 ; #185 -1 56.885 54.242 57.027 54.725 57.225 55.121 57.349 55.533 57.665 55.434 57.723 55.313 57.396 55.363 57.264 54.978 57.091 54.654 56.951 54.176 56.799 54.093 ; #186 -1 46.137 33.791 46.027 34.099 45.898 34.478 45.783 34.747 45.401 35.192 45.574 35.099 45.827 34.879 46.077 34.604 46.181 34.236 46.201 33.901 ; #187 1 10.821 -61.082 10.799 -61.247 10.692 -61.527 10.341 -61.484 10.132 -61.775 10.069 -61.665 10.071 -61.368 10.132 -61.071 10.396 -61.011 10.742 -60.989 ; #188 1 57.448 -135.165 57.440 -135.456 57.201 -135.412 56.920 -135.275 56.670 -135.033 56.302 -134.780 56.503 -134.632 56.769 -134.643 57.052 -134.764 57.316 -134.940 ; #189 -1 51.788 -68.434 51.690 -68.780 51.761 -69.143 51.643 -69.214 51.354 -69.148 51.118 -68.907 50.832 -68.742 50.857 -68.692 51.107 -68.456 51.341 -68.242 51.621 -68.242 ; #190 1 -1.640 135.473 -1.712 135.692 -1.797 135.967 -1.876 136.247 -1.827 136.687 -1.728 136.495 -1.673 136.214 -1.643 135.929 -1.618 135.637 ; #191 -1 38.203 45.137 38.008 45.121 37.766 45.198 37.484 45.286 37.187 45.445 37.335 45.775 37.618 45.747 37.802 45.500 38.096 45.473 ; #192 1 26.893 -77.830 26.816 -77.527 26.621 -77.302 26.412 -77.209 26.041 -77.275 26.137 -77.176 26.393 -77.055 26.648 -77.258 26.843 -77.495 26.915 -77.797 ; #193 2 -67.593 -69.198 -67.720 -68.764 -67.503 -68.148 -67.255 -67.912 -67.014 -67.857 -66.728 -67.731 -66.670 -67.973 -66.901 -68.418 -67.165 -68.698 -67.423 -69.022 ; #194 1 73.761 140.879 73.503 140.368 73.409 140.121 73.363 141.330 73.269 142.264 73.275 143.313 73.563 143.308 73.788 142.621 73.890 141.676 ; #195 1 53.220 -131.918 53.143 -132.341 52.986 -132.291 52.769 -132.055 52.544 -131.802 52.247 -131.280 52.385 -131.346 52.599 -131.659 52.854 -131.802 53.063 -131.775 ; #196 1 62.953 -82.445 62.885 -83.055 62.786 -83.511 62.525 -83.808 62.239 -83.676 62.228 -83.066 62.404 -82.577 62.615 -82.165 62.876 -81.962 ; #197 -1 47.500 -107.962 47.604 -107.632 47.659 -107.198 47.690 -106.813 47.714 -106.368 47.901 -106.390 47.786 -106.813 47.701 -107.170 47.670 -107.571 47.558 -107.912 ; #198 2 78.714 -98.258 78.453 -98.187 78.154 -97.456 77.896 -97.159 77.876 -96.341 78.060 -95.115 78.368 -95.110 78.569 -96.121 78.764 -97.269 ; #199 -1 8.074 -5.538 7.865 -5.681 7.635 -5.731 7.330 -5.775 7.074 -5.500 7.385 -5.401 7.363 -5.538 7.434 -5.632 7.734 -5.582 7.956 -5.544 ; #200 1 -36.060 137.516 -35.857 137.896 -35.706 137.665 -35.602 137.423 -35.662 137.077 -35.736 136.720 -35.948 136.615 -36.044 136.907 -36.016 137.269 ; #201 2 78.162 23.005 78.154 21.357 77.896 21.440 77.536 21.187 77.423 22.555 77.467 23.665 77.750 24.505 77.904 23.692 ; #202 -1 38.484 42.324 38.481 42.527 38.423 42.885 38.379 43.192 38.632 43.203 38.887 43.489 38.931 43.231 38.805 43.038 38.777 42.659 38.610 42.412 ; #203 -1 37.901 -110.374 37.777 -110.462 37.525 -110.698 37.297 -110.846 37.071 -111.308 37.058 -111.132 37.214 -110.769 37.492 -110.637 37.747 -110.429 ; #204 1 -6.654 156.456 -6.813 156.555 -7.011 156.764 -7.228 156.967 -7.357 157.352 -7.220 157.258 -6.986 157.093 -6.816 156.863 -6.662 156.615 ; #205 1 1.038 97.879 1.225 97.670 1.464 97.445 1.426 97.192 1.316 97.181 1.069 97.352 0.882 97.527 0.618 97.742 0.794 97.896 ; #206 1 -10.258 161.291 -10.382 161.440 -10.596 161.610 -10.745 161.852 -10.816 162.242 -10.602 162.214 -10.456 161.995 -10.379 161.714 -10.239 161.451 ; #207 1 55.038 -163.610 54.989 -164.022 54.871 -164.451 54.629 -164.813 54.423 -164.720 54.536 -164.280 54.626 -163.830 54.692 -163.269 54.841 -163.368 ; #208 1 12.475 123.253 12.099 123.225 12.157 123.440 12.014 123.687 11.824 123.956 11.953 124.027 12.187 123.852 12.363 123.632 12.503 123.374 ; #209 2 78.107 -110.038 78.080 -111.005 77.997 -112.297 77.797 -113.203 77.492 -112.912 77.360 -111.808 77.484 -110.505 77.758 -110.423 77.970 -109.940 ; #210 -1 13.231 103.703 13.030 103.753 12.841 103.945 12.684 104.154 12.475 104.505 12.604 104.473 12.791 104.247 13.047 104.088 13.223 103.874 ; #211 1 -14.860 166.736 -14.775 166.566 -15.140 166.621 -15.437 166.659 -15.610 166.863 -15.495 167.170 -15.209 167.137 -15.047 166.945 -15.008 166.769 ; #212 1 12.516 53.346 12.407 53.500 12.316 53.775 12.346 54.071 12.495 54.412 12.635 54.280 12.659 54.000 12.651 53.720 12.632 53.445 ; #213 -1 59.788 -153.890 59.788 -154.181 59.747 -154.758 59.643 -155.275 59.547 -155.802 59.338 -155.670 59.418 -155.088 59.522 -154.604 59.701 -154.137 ; #214 1 68.992 -135.808 68.934 -135.209 68.808 -134.511 68.882 -134.522 69.132 -134.434 69.445 -133.929 69.577 -134.385 69.385 -135.170 69.217 -135.703 ; #215 -1 41.676 -112.764 41.571 -112.912 41.288 -112.863 41.041 -112.654 40.797 -112.396 40.931 -112.159 41.093 -112.176 41.280 -112.462 41.516 -112.714 ; #216 1 57.346 17.055 57.179 16.918 56.912 16.703 56.657 16.473 56.343 16.412 56.385 16.571 56.657 16.709 56.937 16.879 57.206 17.044 ; #217 1 68.956 48.253 68.758 48.676 68.827 49.445 69.052 50.071 69.250 50.132 69.440 49.505 69.462 48.758 69.223 48.297 ; #218 1 73.582 -104.566 73.720 -105.170 73.720 -106.214 73.516 -106.813 73.269 -106.170 72.967 -105.467 73.110 -104.890 73.390 -104.577 ; #219 1 -8.261 116.264 -8.442 116.093 -8.755 115.973 -8.885 116.088 -8.887 116.456 -8.687 116.599 -8.404 116.698 -8.236 116.484 ; #220 -1 50.203 -88.368 50.203 -88.714 49.896 -88.956 49.670 -88.989 49.538 -88.714 49.451 -88.357 49.596 -88.143 49.926 -88.121 50.159 -88.225 ; #221 -1 36.497 -114.368 36.154 -114.626 36.080 -114.374 36.104 -114.027 35.934 -113.725 35.962 -113.720 36.151 -114.022 36.132 -114.313 36.423 -114.341 ; #222 2 -71.184 -76.148 -71.102 -75.319 -71.014 -74.473 -70.838 -73.742 -70.659 -74.159 -70.758 -74.874 -70.879 -75.764 -71.033 -76.495 ; #223 1 -1.069 -51.676 -1.335 -51.846 -1.316 -51.599 -1.102 -51.374 -0.890 -51.236 -0.599 -51.286 -0.632 -51.516 -0.879 -51.659 ; #224 1 -1.681 99.253 -1.453 99.154 -1.201 99.033 -0.967 98.868 -1.077 98.637 -1.343 98.676 -1.588 98.835 -1.766 99.060 ; #225 1 71.049 -25.813 70.937 -26.374 70.827 -27.187 70.549 -27.901 70.486 -27.247 70.544 -26.368 70.659 -25.527 70.920 -25.505 ; #226 -1 37.187 100.214 37.190 99.907 36.956 99.736 36.728 99.857 36.637 100.198 36.602 100.577 36.830 100.665 37.063 100.407 ; #227 -1 61.382 -117.703 61.519 -118.104 61.371 -118.505 61.250 -119.066 61.294 -119.714 61.258 -119.659 61.223 -119.071 61.319 -118.495 61.393 -117.967 ; #228 1 -2.588 107.665 -2.821 107.604 -3.115 107.621 -3.140 107.885 -3.151 108.137 -2.874 108.258 -2.643 108.110 -2.560 107.846 ; #229 -1 63.027 -102.110 62.885 -101.901 62.769 -101.396 62.860 -101.000 63.176 -101.011 63.401 -100.703 63.478 -101.005 63.401 -101.522 63.143 -102.033 ; #230 1 53.970 -166.346 53.934 -166.621 53.764 -166.929 53.558 -167.099 53.365 -167.582 53.313 -167.423 53.442 -166.945 53.629 -166.538 53.852 -166.363 ; #231 -1 32.934 118.115 32.937 118.330 33.115 118.637 33.456 118.637 33.343 118.335 33.099 118.385 33.115 118.225 33.124 118.027 33.113 117.907 32.997 118.154 ; #232 -1 51.448 100.412 51.269 100.319 50.959 100.275 50.596 100.214 50.629 100.440 50.904 100.604 51.184 100.742 51.505 100.637 ; #233 -1 64.621 -70.440 64.797 -70.495 65.071 -70.835 65.302 -71.500 65.154 -71.610 64.882 -71.791 64.648 -71.643 64.712 -71.088 64.657 -70.648 ; #234 1 -0.008 130.813 -0.047 130.670 -0.154 130.352 -0.321 130.484 -0.272 130.742 -0.302 130.912 -0.341 131.214 -0.151 131.231 -0.041 130.973 ; #235 -1 43.973 -99.352 43.794 -99.401 43.552 -99.346 43.335 -99.088 43.118 -98.747 43.162 -98.769 43.352 -99.071 43.569 -99.319 43.810 -99.368 ; #236 1 -5.478 134.495 -5.687 134.341 -5.959 134.330 -6.201 134.346 -6.316 134.632 -6.041 134.703 -5.794 134.731 -5.519 134.643 ; #237 1 60.396 -166.176 60.335 -166.566 60.173 -167.192 59.967 -166.951 59.827 -166.291 59.890 -165.830 60.058 -165.648 60.319 -165.868 ; #238 1 -52.775 -74.681 -52.975 -74.462 -53.080 -74.099 -53.206 -73.659 -53.338 -73.324 -53.231 -73.374 -53.099 -73.676 -52.967 -74.115 -52.835 -74.484 ; #239 1 45.898 -81.681 45.874 -81.890 45.912 -82.379 45.898 -82.918 45.783 -82.731 45.676 -82.341 45.599 -81.907 45.753 -81.659 ; #240 1 -1.690 124.385 -1.907 124.374 -1.984 124.621 -1.920 124.907 -1.846 125.236 -1.739 125.137 -1.684 124.846 -1.643 124.555 ; #241 1 -7.176 131.549 -7.379 131.379 -7.635 131.198 -7.838 131.126 -7.975 131.280 -7.772 131.478 -7.530 131.654 -7.231 131.676 ; #242 1 -53.775 -72.203 -53.657 -72.473 -53.552 -72.841 -53.459 -73.126 -53.648 -73.308 -53.923 -73.242 -53.876 -72.923 -54.030 -72.852 -54.058 -72.582 -53.898 -72.319 ; #243 1 25.118 -78.187 24.887 -78.209 24.629 -78.297 24.393 -78.110 24.396 -77.857 24.626 -77.742 24.885 -77.890 25.135 -78.044 ; #244 -1 45.195 132.780 45.288 132.588 45.313 132.187 45.102 132.033 44.816 132.082 44.604 132.313 44.772 132.632 45.044 132.808 ; #245 1 72.434 127.159 72.313 127.962 72.121 128.703 72.201 129.396 72.445 129.088 72.566 128.203 72.593 127.319 72.484 126.720 ; #246 2 80.096 47.978 80.220 48.775 80.423 49.626 80.610 51.198 80.799 50.187 80.574 49.049 80.401 47.731 80.209 47.385 ; #247 1 69.896 59.049 69.797 59.533 69.712 60.203 69.940 60.368 70.154 59.775 70.396 59.176 70.277 58.610 70.025 58.698 ; #248 1 -0.728 135.434 -0.860 135.687 -1.088 135.841 -1.151 136.203 -0.937 136.099 -0.750 135.868 -0.692 135.604 ; #249 -1 58.841 14.929 58.687 14.665 58.434 14.418 57.986 14.220 58.162 14.549 58.429 14.791 58.670 14.918 ; #250 1 25.451 -76.692 25.308 -76.396 25.082 -76.187 24.802 -76.231 24.791 -76.159 25.085 -76.143 25.308 -76.357 25.475 -76.632 ; #251 1 57.887 18.835 57.791 18.484 57.536 18.170 57.091 18.247 57.236 18.615 57.473 18.824 57.769 18.934 ; #252 1 -7.876 125.863 -7.904 126.143 -7.915 126.445 -7.755 126.725 -7.621 126.665 -7.651 126.396 -7.698 126.110 ; #253 1 -25.670 153.099 -25.387 153.198 -25.118 153.324 -24.838 153.291 -24.841 153.203 -25.135 153.115 -25.374 153.033 -25.657 152.984 ; #254 1 39.959 3.148 39.904 2.929 39.621 2.522 39.429 2.797 39.354 3.148 39.629 3.407 39.838 3.209 ; #255 1 10.137 124.346 10.060 124.104 9.863 123.868 9.646 123.923 9.604 124.225 9.736 124.511 9.981 124.549 ; #256 1 72.835 -23.286 72.857 -24.033 72.643 -24.335 72.445 -23.830 72.225 -22.533 72.445 -22.319 72.690 -22.813 ; #257 -1 57.371 42.824 57.124 43.016 56.835 43.159 56.745 43.280 57.085 43.209 57.387 43.297 57.549 43.352 57.445 42.846 ; #258 2 -72.915 -74.412 -72.901 -75.335 -73.143 -75.852 -73.409 -75.659 -73.591 -74.714 -73.401 -74.429 -73.118 -74.275 ; #259 2 -73.124 -78.775 -72.934 -77.901 -72.709 -77.522 -72.527 -77.901 -72.464 -79.016 -72.676 -78.995 -72.959 -79.225 ; #260 1 62.387 -79.791 62.203 -80.170 61.909 -80.269 61.662 -79.951 61.755 -79.582 62.014 -79.352 62.297 -79.357 ; #261 1 27.195 -97.385 27.027 -97.396 26.739 -97.357 26.302 -97.220 26.475 -97.253 26.753 -97.341 27.038 -97.379 ; #262 1 -4.635 122.648 -4.739 122.456 -4.970 122.368 -5.255 122.308 -5.363 122.467 -5.272 122.626 -5.011 122.709 -4.755 122.742 ; #263 1 73.415 -24.813 73.242 -25.489 73.077 -24.863 73.104 -23.467 73.269 -24.429 73.255 -23.725 73.368 -23.951 ; #264 -1 50.668 92.863 50.552 92.615 50.371 92.302 50.080 92.456 50.038 92.846 50.291 93.225 50.555 92.995 ; #265 -1 1.365 32.703 1.376 32.885 1.294 33.209 1.429 33.231 1.651 33.363 1.646 33.203 1.560 32.912 1.505 32.637 ; #266 1 44.459 146.082 44.266 145.923 43.857 145.571 43.981 145.808 44.209 146.077 44.352 146.434 44.445 146.352 ; #267 1 56.390 -79.401 56.264 -79.577 55.962 -79.747 56.011 -79.291 56.228 -79.066 56.019 -79.132 56.115 -79.055 56.385 -78.978 ; #268 -1 63.835 34.324 63.646 34.341 63.415 34.659 63.047 34.879 63.137 34.945 63.407 35.093 63.530 35.060 63.772 34.659 ; #269 1 58.571 163.582 58.783 164.104 58.940 164.604 59.157 164.423 58.989 163.819 58.701 163.632 58.571 163.429 ; #270 1 53.527 -167.896 53.508 -168.231 53.280 -168.489 52.956 -168.912 52.978 -168.665 53.190 -168.308 53.376 -167.923 ; #271 -1 52.810 5.159 52.580 5.110 52.332 5.159 52.343 5.637 52.577 5.786 52.835 5.549 53.022 5.401 ; #272 -1 49.324 117.654 49.154 117.412 48.929 117.110 48.681 117.082 48.640 117.275 48.854 117.544 49.041 117.857 49.157 117.802 ; #273 1 58.604 22.846 58.566 22.390 58.401 21.956 58.052 22.077 58.099 22.253 58.245 22.648 58.451 23.137 ; #274 -1 11.621 37.352 11.755 37.445 12.008 37.560 12.264 37.429 12.214 37.121 11.920 37.033 11.753 37.258 ; #275 2 -77.670 167.703 -77.615 168.989 -77.412 168.951 -77.360 167.571 -77.283 166.610 -77.643 166.555 -77.805 166.835 ; #276 -1 -50.632 -72.940 -50.429 -72.890 -50.245 -72.297 -50.179 -72.604 -50.077 -73.143 -50.250 -73.137 -50.514 -73.000 ; #277 2 78.734 -110.775 78.588 -111.698 78.398 -113.016 78.321 -112.308 78.321 -110.995 78.379 -109.516 78.648 -109.885 ; #278 1 26.673 -78.962 26.536 -78.775 26.580 -78.467 26.673 -78.038 26.712 -78.181 26.723 -78.544 26.615 -78.813 ; #279 1 26.964 56.286 26.978 56.110 26.879 55.791 26.648 55.418 26.637 55.582 26.714 55.896 26.865 56.159 ; #280 -1 60.442 -133.231 60.308 -133.066 60.104 -132.665 59.750 -132.242 59.882 -132.280 60.115 -132.599 60.319 -133.022 ; #281 1 2.398 96.473 2.530 96.352 2.698 96.121 2.865 95.835 2.681 95.808 2.555 96.071 2.390 96.330 ; #282 1 53.209 -81.269 53.190 -81.714 53.003 -81.918 52.860 -81.429 52.780 -80.841 53.069 -80.940 ; #283 -1 36.986 -88.253 36.808 -88.159 36.525 -88.077 36.173 -88.016 36.283 -87.951 36.563 -88.033 36.838 -88.132 ; #284 -1 15.967 -3.896 15.901 -4.060 15.739 -4.275 15.495 -4.280 15.332 -4.170 15.750 -4.253 15.890 -4.038 ; #285 1 -1.852 125.385 -1.929 125.571 -1.918 125.868 -1.865 126.209 -1.805 126.132 -1.799 125.841 -1.805 125.544 ; #286 1 68.269 15.066 68.393 15.582 68.497 16.154 68.775 16.407 68.665 15.995 68.797 15.797 68.659 15.484 68.423 15.187 ; #287 1 -6.187 134.099 -6.415 134.137 -6.651 134.077 -6.868 134.192 -6.703 134.418 -6.478 134.440 -6.272 134.231 ; #288 1 -14.220 136.335 -14.234 136.489 -14.280 136.797 -14.159 136.835 -13.904 136.835 -13.758 136.742 -13.797 136.527 -14.069 136.412 ; #289 1 45.632 149.626 45.827 150.000 46.030 150.291 46.165 150.341 45.959 149.896 45.764 149.599 45.615 149.484 ; #290 1 -2.005 147.407 -2.008 147.242 -1.962 146.962 -2.080 146.621 -2.162 146.758 -2.184 147.071 -2.066 147.346 ; #291 1 -16.519 167.440 -16.538 167.615 -16.398 167.769 -16.176 167.522 -15.959 167.313 -16.096 167.220 -16.313 167.385 ; #292 1 26.832 128.236 26.684 128.038 26.536 127.874 26.209 127.703 26.299 127.835 26.508 128.027 26.712 128.275 ; #293 -1 -48.885 -72.934 -49.044 -72.489 -48.901 -72.440 -48.566 -72.588 -48.706 -72.637 -48.514 -72.857 -48.659 -72.923 -48.813 -73.044 ; #294 -1 52.063 47.769 52.195 48.104 52.434 48.198 52.725 48.445 52.712 48.346 52.453 48.148 52.198 47.923 ; #295 1 50.077 155.429 50.245 155.830 50.500 156.088 50.659 155.945 50.390 155.577 50.217 155.247 ; #296 1 55.538 10.478 55.473 9.835 55.190 10.005 55.060 10.330 55.170 10.758 55.442 10.720 ; #297 1 55.951 -131.308 55.799 -131.571 55.547 -131.709 55.442 -131.451 55.379 -131.352 55.305 -131.170 55.566 -130.962 55.832 -131.099 ; #298 1 56.896 -134.187 56.723 -134.280 56.459 -134.148 56.179 -134.137 56.277 -133.918 56.544 -133.830 56.753 -133.901 ; #299 1 -1.261 123.473 -1.269 123.242 -1.190 122.973 -1.470 122.868 -1.484 123.165 -1.448 123.440 ; #300 1 -55.008 -67.148 -54.926 -67.566 -54.929 -68.148 -55.132 -68.121 -55.225 -67.687 -55.239 -67.192 ; #301 -1 54.942 -96.703 54.909 -96.978 54.788 -97.445 54.670 -97.912 54.610 -97.808 54.725 -97.374 54.863 -96.967 ; #302 1 -7.995 157.440 -8.214 157.280 -8.327 157.516 -8.527 157.791 -8.283 157.764 -8.085 157.599 ; #303 1 28.508 -16.385 28.382 -16.676 28.250 -16.841 28.041 -16.599 28.269 -16.374 28.508 -16.187 ; #304 1 -1.423 127.434 -1.602 127.412 -1.714 127.643 -1.646 128.027 -1.431 127.863 -1.376 127.588 ; #305 1 58.467 -6.214 58.382 -6.522 58.201 -6.907 57.885 -6.956 58.005 -6.544 58.242 -6.253 ; #306 1 56.975 -133.236 57.036 -133.764 56.832 -133.758 56.508 -133.549 56.654 -133.165 56.846 -132.973 ; #307 -1 -18.843 -45.033 -18.662 -45.165 -18.354 -45.275 -18.516 -45.385 -18.775 -45.275 -18.942 -45.330 -18.959 -45.225 ; #308 -1 31.146 119.929 30.951 120.154 31.008 120.473 31.129 120.434 31.431 120.280 31.398 119.995 ; #309 1 28.371 -14.159 28.140 -14.346 28.085 -14.346 28.223 -14.016 28.451 -13.852 28.662 -13.951 ; #310 1 -8.165 124.445 -8.343 124.445 -8.409 124.731 -8.302 125.060 -8.165 124.907 -8.165 124.610 ; #311 1 72.953 -22.148 73.038 -22.967 72.981 -24.165 72.896 -23.791 72.786 -22.835 72.758 -22.077 ; #312 1 2.011 128.302 2.085 128.505 2.332 128.654 2.569 128.549 2.412 128.302 2.159 128.242 ; #313 2 77.750 -93.478 77.769 -94.445 77.734 -95.791 77.500 -95.841 77.467 -94.396 77.555 -93.418 ; #314 1 -20.904 55.599 -20.945 55.302 -21.198 55.313 -21.349 55.560 -21.236 55.813 -21.038 55.742 ; #315 2 -64.440 -57.896 -64.368 -57.462 -64.124 -57.214 -63.931 -57.742 -64.030 -58.242 -64.321 -58.110 ; #316 -1 68.896 27.082 68.786 27.500 68.860 28.121 69.245 28.451 69.206 28.060 68.997 27.412 ; #317 2 -64.712 -64.236 -64.783 -63.841 -64.621 -63.104 -64.382 -63.181 -64.360 -63.632 -64.569 -64.049 ; #318 1 -1.681 130.335 -1.728 130.176 -1.857 129.841 -2.022 130.016 -2.008 130.313 -1.835 130.385 ; #319 1 21.819 -83.082 21.610 -83.060 21.456 -82.978 21.544 -82.643 21.802 -82.665 21.915 -82.945 ; #320 1 3.750 8.863 3.690 8.681 3.437 8.500 3.236 8.566 3.346 8.775 3.613 8.918 ; #321 1 52.396 -174.236 52.236 -174.390 52.055 -174.989 52.030 -174.747 52.088 -174.352 52.275 -174.088 ; #322 1 23.569 -75.286 23.277 -75.132 23.102 -75.082 22.997 -74.901 23.280 -75.099 23.544 -75.225 ; #323 1 -0.313 127.516 -0.418 127.368 -0.720 127.462 -0.821 127.758 -0.679 127.703 -0.431 127.626 ; #324 -1 -30.896 -62.659 -30.841 -62.396 -30.673 -62.242 -30.547 -62.495 -30.640 -62.857 -30.827 -62.841 ; #325 1 54.786 137.473 54.720 137.846 55.011 138.027 55.146 137.670 54.931 137.330 54.783 137.225 ; #326 2 -63.437 -56.346 -63.352 -55.956 -63.346 -55.324 -63.201 -55.231 -63.135 -55.830 -63.291 -56.407 ; #327 1 53.294 -128.995 53.049 -129.022 52.854 -129.044 52.753 -128.720 52.920 -128.533 53.176 -128.703 ; #328 1 0.830 103.027 0.945 102.868 1.063 102.599 0.942 102.462 0.788 102.615 0.755 102.940 ; #329 2 -78.648 -37.643 -78.588 -38.566 -78.560 -40.929 -78.618 -39.951 -78.648 -38.533 ; #330 1 22.783 90.665 22.615 90.593 22.187 90.698 22.363 90.863 22.635 90.797 ; #331 2 -74.863 -20.198 -74.703 -20.170 -74.294 -20.505 -74.464 -21.231 -74.739 -20.544 ; #332 -1 52.728 -119.104 52.602 -118.962 52.206 -118.462 52.382 -118.654 52.618 -118.929 ; #333 1 0.261 -50.000 0.206 -50.286 0.052 -50.275 -0.016 -49.956 0.203 -49.769 ; #334 1 58.376 -152.187 58.409 -152.511 58.269 -152.934 58.088 -153.077 58.104 -152.604 58.236 -152.154 ; #335 1 69.879 169.209 69.984 168.346 69.797 167.956 69.607 168.654 69.668 169.264 ; #336 2 76.755 -19.005 76.591 -19.005 76.121 -18.736 76.321 -18.665 76.615 -18.720 ; #337 -1 4.981 -55.077 4.788 -55.220 4.555 -55.264 4.593 -54.962 4.841 -54.874 ; #338 1 -44.934 -73.247 -44.835 -73.027 -44.607 -72.841 -44.437 -73.022 -44.566 -73.264 -44.794 -73.346 ; #339 1 7.052 171.786 7.099 171.159 7.069 171.478 6.992 171.687 ; #340 2 80.470 59.582 80.470 60.973 80.750 62.005 80.824 60.407 80.681 59.374 ; #341 1 20.964 -73.681 20.940 -73.440 21.143 -73.099 21.176 -73.308 21.118 -73.604 ; #342 1 53.882 -130.247 53.670 -130.055 53.398 -129.654 53.596 -129.665 53.816 -129.995 ; #343 -1 32.706 119.165 32.780 119.341 33.085 119.313 33.088 119.011 33.080 119.181 32.885 119.176 ; #344 1 -11.819 130.137 -11.758 130.484 -11.462 130.390 -11.431 130.220 -11.698 130.110 ; #345 1 33.544 126.830 33.530 126.643 33.341 126.275 33.239 126.549 33.407 126.874 ; #346 1 73.044 70.137 73.195 71.275 73.390 71.093 73.442 70.269 73.176 69.984 ; #347 2 76.088 -117.824 75.945 -118.429 75.613 -118.967 75.695 -118.060 75.986 -117.621 ; #348 1 -20.058 57.599 -20.294 57.379 -20.492 57.445 -20.376 57.736 -20.179 57.769 ; #349 1 -6.085 39.198 -6.310 39.335 -6.277 39.500 -5.978 39.385 -5.824 39.280 ; #350 2 82.137 -44.929 82.407 -44.736 82.626 -46.621 82.423 -46.989 82.195 -45.648 ; #351 1 55.330 165.984 55.198 165.956 54.945 166.214 54.852 166.522 55.223 166.247 ; #352 1 51.621 -68.758 51.437 -69.049 51.209 -68.874 51.319 -68.495 51.514 -68.429 ; #353 1 -10.871 122.868 -10.821 123.132 -10.593 123.368 -10.560 123.231 -10.717 122.995 ; #354 2 77.723 -105.940 77.492 -105.742 77.203 -105.027 77.379 -104.709 77.635 -105.269 ; #355 -1 -49.736 -72.143 -49.588 -72.379 -49.475 -72.835 -49.632 -72.901 -49.712 -72.445 ; #356 2 74.217 113.088 74.464 113.104 74.451 112.005 74.245 111.747 74.113 112.500 ; #357 1 -48.681 -75.181 -48.486 -75.121 -48.135 -75.379 -48.321 -75.445 -48.571 -75.286 ; #358 1 20.923 -156.544 20.646 -156.396 20.679 -156.088 20.871 -156.137 ; #359 2 -62.214 -58.918 -62.157 -58.467 -62.005 -57.846 -61.942 -58.264 -62.085 -58.780 ; #360 -1 38.484 33.538 38.635 33.648 38.940 33.445 38.810 33.198 38.571 33.390 ; #361 1 67.997 -73.549 68.069 -74.093 68.049 -74.610 67.810 -74.412 67.819 -73.555 ; #362 1 54.266 19.341 54.335 19.560 54.610 20.104 54.569 19.824 54.368 19.412 ; #363 1 39.363 26.286 39.258 25.951 39.115 26.132 39.025 26.473 39.203 26.478 ; #364 1 -13.805 -172.484 -13.758 -172.264 -13.514 -172.297 -13.519 -172.648 -13.701 -172.615 ; #365 -1 27.184 -80.813 27.036 -80.989 26.832 -80.973 26.764 -80.714 27.063 -80.659 ; #366 1 -46.745 167.835 -47.143 167.670 -47.088 168.115 -46.890 168.077 ; #367 1 36.420 28.137 36.321 27.907 36.036 27.753 36.063 28.016 36.316 28.187 ; #368 1 25.277 -112.143 25.129 -112.170 24.852 -112.181 24.712 -112.170 25.140 -112.148 ; #369 1 -40.239 148.220 -40.091 148.280 -39.813 148.049 -39.874 147.852 -40.143 148.000 ; #370 1 -9.376 150.445 -9.580 150.500 -9.670 150.802 -9.541 150.868 -9.401 150.643 ; #371 1 69.104 17.302 69.239 17.890 69.511 17.764 69.401 17.198 69.159 16.995 ; #372 1 -26.115 113.198 -25.937 113.137 -25.607 113.000 -25.712 112.945 -25.973 113.077 ; #373 1 -0.893 130.890 -0.981 130.725 -1.234 130.775 -1.275 130.995 -0.970 131.016 ; #374 1 60.324 -147.055 60.228 -147.280 59.909 -147.731 59.937 -147.456 60.176 -147.126 ; #375 1 -53.615 -70.577 -53.846 -70.758 -54.135 -70.725 -54.008 -70.527 -53.745 -70.473 ; #376 2 80.599 45.082 80.527 46.247 80.692 48.005 80.810 47.390 80.681 45.868 ; #377 1 29.571 -113.588 29.404 -113.549 29.121 -113.269 29.266 -113.253 29.497 -113.456 ; #378 1 53.607 -130.489 53.456 -130.341 53.223 -129.945 53.343 -129.846 53.544 -130.187 ; #379 1 -5.775 120.478 -5.931 120.445 -6.313 120.467 -6.209 120.533 -5.920 120.533 ; #380 1 -16.755 139.148 -16.698 139.286 -16.511 139.599 -16.445 139.418 -16.602 139.187 ; #381 2 -72.555 -91.165 -72.728 -91.500 -73.025 -91.379 -73.025 -91.038 -72.747 -90.846 ; #382 2 -72.690 -100.802 -72.772 -100.231 -72.758 -99.236 -72.604 -99.451 -72.585 -100.434 ; #383 -1 1.602 32.385 1.640 32.495 1.797 32.879 1.777 32.692 1.673 32.423 ; #384 1 27.852 -80.440 27.706 -80.390 27.338 -80.242 27.440 -80.269 27.712 -80.374 ; #385 1 31.783 121.203 31.654 121.341 31.505 121.714 31.610 121.654 31.772 121.379 ; #386 -1 47.687 -76.538 47.527 -76.736 47.198 -76.577 47.310 -76.462 47.544 -76.571 ; #387 1 -2.481 149.956 -2.582 150.088 -2.662 150.357 -2.467 150.379 -2.423 150.088 ; #388 1 21.703 -157.973 21.615 -158.137 21.407 -158.170 21.349 -157.841 21.571 -157.879 ; #389 1 24.236 -77.769 24.066 -77.868 23.799 -77.687 23.898 -77.544 24.148 -77.665 ; #390 -1 50.747 -117.731 50.615 -117.912 50.245 -117.874 50.341 -117.857 50.629 -117.846 ; #391 1 -9.805 150.802 -10.027 150.956 -10.096 151.225 -9.975 151.110 -9.810 150.879 ; #392 1 -11.503 159.978 -11.618 160.115 -11.766 160.429 -11.676 160.407 -11.538 160.143 ; #393 1 -8.275 123.407 -8.418 123.352 -8.560 123.467 -8.319 123.758 -8.294 123.571 ; #394 1 63.258 -77.500 63.393 -77.692 63.462 -78.308 63.266 -78.302 63.151 -77.769 ; #395 1 57.651 -6.253 57.486 -6.560 57.212 -6.093 57.415 -6.137 ; #396 1 27.835 -97.055 27.692 -97.181 27.376 -97.346 27.451 -97.297 27.703 -97.143 ; #397 1 14.005 124.148 13.648 124.115 13.665 124.357 13.931 124.324 ; #398 1 27.816 -15.731 27.824 -15.445 28.102 -15.440 28.074 -15.731 ; #399 -1 34.802 -87.615 34.775 -87.363 34.648 -87.049 34.684 -87.038 34.808 -87.352 ; #400 1 -11.426 43.258 -11.632 43.242 -11.863 43.346 -11.791 43.451 -11.478 43.374 ; #401 1 52.113 -174.033 52.052 -173.758 52.060 -173.214 52.107 -173.341 52.124 -173.780 ; #402 1 35.190 -75.720 35.283 -75.538 35.569 -75.484 35.632 -75.478 35.286 -75.571 ; #403 1 52.420 -127.275 52.321 -127.522 52.093 -127.846 52.077 -127.670 52.291 -127.324 ; #404 1 55.228 -133.165 55.060 -133.154 54.766 -132.863 54.852 -132.813 55.099 -133.022 ; #405 2 79.887 91.308 79.725 92.582 79.953 93.297 80.052 91.560 ; #406 1 -11.357 153.198 -11.497 153.324 -11.607 153.615 -11.503 153.610 -11.385 153.335 ; #407 1 47.412 -87.868 47.464 -88.093 47.173 -88.456 47.236 -88.143 ; #408 1 -5.445 39.725 -5.341 39.808 -5.055 39.852 -4.992 39.736 -5.277 39.698 ; #409 2 74.429 -20.901 74.338 -21.780 74.126 -21.385 74.212 -20.418 ; #410 1 38.308 138.505 38.203 138.363 37.926 138.269 37.882 138.445 38.115 138.495 ; #411 -1 15.368 -89.313 15.423 -89.154 15.662 -88.923 15.659 -88.995 15.503 -89.297 ; #412 -1 51.214 30.511 51.063 30.396 50.734 30.434 50.791 30.544 51.085 30.566 ; #413 1 0.904 103.148 1.049 103.005 1.118 102.736 1.011 102.764 0.879 103.033 ; #414 1 30.398 -86.544 30.401 -86.731 30.349 -87.121 30.349 -87.055 30.390 -86.725 ; #415 1 48.173 -88.484 48.110 -88.698 47.942 -89.110 47.901 -88.978 48.058 -88.621 ; #416 2 -71.014 -2.610 -70.810 -2.280 -70.681 -3.192 -70.956 -3.110 ; #417 2 78.368 22.203 78.580 21.505 78.398 20.511 78.220 21.176 ; #418 1 22.223 -159.445 22.093 -159.720 21.904 -159.538 22.038 -159.330 ; #419 1 2.052 101.714 2.030 101.467 1.777 101.478 1.816 101.709 ; #420 1 -14.055 -171.742 -14.041 -171.549 -13.909 -171.582 -13.841 -171.929 -13.997 -171.879 ; #421 1 -5.393 133.088 -5.808 132.923 -5.690 133.022 -5.437 133.154 ; #422 2 77.536 -91.143 77.264 -90.648 77.335 -89.764 77.591 -90.269 ; #423 2 -70.159 -75.357 -70.058 -74.709 -69.846 -75.214 -70.005 -75.747 ; #424 1 -20.835 167.302 -20.772 167.132 -21.022 167.126 -21.093 167.396 ; #425 1 20.692 58.907 20.566 58.824 20.330 58.665 20.297 58.758 20.541 58.907 ; #426 1 69.288 -78.692 68.975 -79.209 68.975 -78.758 69.255 -78.368 ; #427 -1 57.978 -156.720 57.745 -156.198 57.816 -156.016 58.008 -156.308 ; #428 1 54.863 11.060 54.684 11.253 54.709 11.725 54.871 11.489 ; #429 1 47.640 -61.412 47.580 -61.615 47.341 -61.929 47.382 -61.802 47.574 -61.544 ; #430 1 29.151 -112.473 28.931 -112.505 28.835 -112.286 29.165 -112.286 ; #431 1 43.192 16.379 43.143 16.577 43.121 16.995 43.148 16.967 43.198 16.577 ; #432 1 6.734 122.060 6.626 121.885 6.426 122.038 6.615 122.225 ; #433 1 13.124 122.973 12.986 123.033 12.794 123.269 12.824 123.286 13.041 123.093 ; #434 1 72.294 77.253 72.409 78.110 72.593 77.874 72.445 77.143 ; #435 1 -48.632 -74.533 -48.308 -74.681 -48.442 -74.857 -48.640 -74.819 ; #436 1 24.574 -75.648 24.212 -75.445 24.264 -75.374 24.516 -75.571 ; #437 2 76.297 -103.038 76.217 -104.071 76.049 -103.912 76.143 -102.753 ; #438 2 75.407 -104.440 75.187 -104.775 75.069 -104.016 75.321 -103.835 ; #439 2 80.942 55.154 80.775 56.923 80.907 56.912 81.052 55.198 ; #440 -1 -20.613 -46.593 -20.503 -46.687 -20.335 -46.929 -20.401 -46.940 -20.525 -46.775 ; #441 2 -62.643 -60.852 -62.673 -60.192 -62.533 -60.181 -62.544 -60.885 ; #442 2 74.091 -98.066 73.959 -99.044 73.835 -98.846 73.967 -97.874 ; #443 1 22.626 -73.945 22.302 -74.137 22.349 -74.011 22.610 -73.863 ; #444 1 14.731 -61.181 14.497 -60.967 14.662 -60.890 14.821 -61.049 ; #445 1 60.451 -1.396 60.203 -1.429 60.096 -1.214 60.412 -1.126 ; #446 1 37.788 -25.742 37.723 -25.374 37.832 -25.280 37.865 -25.687 ; #447 2 76.640 -104.423 76.442 -104.462 76.360 -103.467 76.574 -103.742 ; #448 1 -17.747 -149.538 -17.794 -149.280 -17.651 -149.308 -17.569 -149.560 ; #449 1 66.049 -84.253 65.723 -83.698 65.876 -83.742 ; #450 2 -65.676 100.511 -65.662 100.890 -65.451 101.077 -65.538 100.396 ; #451 2 80.739 63.055 80.981 64.797 80.942 63.242 ; #452 1 56.346 -132.401 56.198 -132.621 56.003 -132.286 56.209 -132.330 ; #453 1 54.291 13.181 54.299 13.538 54.560 13.445 54.470 13.225 ; #454 2 80.118 57.896 80.277 58.538 80.459 57.824 80.231 57.308 ; #455 1 -50.434 -75.247 -50.234 -74.945 -50.129 -75.181 -50.316 -75.346 ; #456 -1 46.302 6.258 46.412 6.725 46.497 6.593 46.363 6.247 ; #457 1 28.442 129.577 28.308 129.280 28.198 129.346 28.385 129.621 ; #458 1 -53.915 -71.808 -53.959 -72.121 -54.209 -71.973 -54.077 -71.797 ; #459 1 56.478 -5.742 56.585 -6.132 56.382 -6.192 56.349 -5.819 ; #460 1 -44.047 -176.462 -43.816 -176.390 -43.734 -176.429 -43.843 -176.670 ; #461 1 11.008 -64.379 10.989 -63.984 11.047 -64.192 ; #462 1 68.206 -86.720 67.860 -86.747 68.022 -86.401 ; #463 2 -70.154 16.137 -70.000 16.258 -69.918 15.621 -70.140 15.681 ; #464 1 4.516 126.791 4.173 126.764 4.330 126.890 ; #465 1 1.313 102.302 1.025 102.297 1.060 102.456 ; #466 2 -69.695 -62.060 -69.324 -62.055 -69.527 -62.170 ; #467 1 69.717 -80.566 69.582 -80.275 69.673 -79.670 69.769 -80.049 ; #468 1 1.464 102.495 1.544 102.181 1.360 102.407 ; #469 1 62.129 29.308 62.069 29.066 61.841 29.027 61.967 29.390 ; #470 1 -40.107 143.962 -39.772 144.027 -39.970 143.868 ; #471 -1 11.376 34.676 11.632 34.418 11.470 34.516 ; #472 1 -9.005 152.527 -9.143 152.830 -8.978 152.714 ; #473 1 52.896 172.659 52.843 173.181 52.995 172.901 ; #474 1 70.470 22.148 70.665 22.962 70.632 22.346 ; #475 1 5.973 120.967 5.923 121.291 6.036 121.209 ; #476 1 7.170 93.731 6.874 93.797 7.047 93.901 ; #477 1 12.659 122.126 12.327 122.000 12.527 122.121 ; #478 -1 12.376 -86.473 12.212 -86.236 12.352 -86.192 ; #479 1 29.201 -13.462 28.992 -13.736 29.008 -13.516 ; #480 1 21.154 -157.247 21.107 -156.885 21.190 -157.016 ; #481 1 1.126 104.621 1.118 104.363 0.937 104.516 ; #482 1 10.445 125.643 10.102 125.599 10.272 125.665 ; #483 2 75.451 135.885 75.728 135.896 75.728 135.604 75.481 135.505 ; #484 1 -51.063 -74.879 -51.047 -74.654 -50.860 -74.500 -50.926 -74.791 ; #485 1 -17.569 168.390 -17.739 168.264 -17.758 168.527 ; #486 2 -64.470 -62.538 -64.176 -62.203 -64.286 -62.511 ; #487 1 61.624 -64.725 61.635 -65.214 61.434 -64.890 ; #488 1 -15.945 168.225 -15.615 168.192 -15.750 168.137 ; #489 1 38.456 20.544 38.310 20.440 38.151 20.582 38.321 20.637 ; #490 1 45.168 14.319 44.835 14.396 45.022 14.412 ; #491 1 -54.904 -70.434 -54.975 -70.824 -55.118 -70.637 -55.041 -70.451 ; #492 -1 59.852 39.093 59.607 39.560 59.739 39.379 ; #493 1 65.997 -85.088 65.690 -84.874 65.871 -84.780 ; #494 1 44.695 14.736 44.442 15.044 44.599 14.890 ; #495 -1 47.525 9.632 47.720 9.253 47.602 9.313 ; #496 1 -0.516 -90.401 -0.714 -90.456 -0.629 -90.220 ; #497 1 7.571 -12.912 7.505 -12.610 7.626 -12.742 ; #498 1 -8.429 143.203 -8.610 143.484 -8.492 143.352 ; #499 1 -5.549 147.780 -5.766 147.967 -5.569 147.973 ; #500 1 38.566 25.978 38.286 25.967 38.401 26.143 ; #501 1 18.923 -73.297 18.797 -72.989 18.940 -73.148 ; #502 2 80.140 -99.830 79.854 -99.390 80.063 -99.060 ; #503 1 -18.742 169.203 -18.755 169.005 -18.940 169.231 ; #504 1 47.060 152.093 46.893 151.934 47.135 152.258 ; #505 1 39.786 19.731 39.503 19.901 39.687 19.896 ; #506 1 16.016 -61.637 16.277 -61.621 16.192 -61.780 ; #507 1 45.288 -87.022 45.016 -87.258 45.151 -87.066 ; #508 1 -1.978 125.918 -2.297 125.973 -2.113 125.984 ; #509 1 0.071 -49.429 -0.027 -49.681 -0.066 -49.434 ; #510 2 73.959 140.786 74.212 140.703 73.995 140.236 ; #511 2 -73.912 -116.060 -74.071 -116.907 -74.104 -116.308 ; #512 1 13.456 121.835 13.277 122.005 13.495 122.022 ; #513 1 -0.011 -50.681 -0.168 -50.918 -0.140 -50.698 ; #514 2 75.346 -18.456 75.060 -18.055 75.255 -18.000 ; #515 1 64.467 -40.247 64.747 -40.566 64.610 -40.544 ; #516 1 5.341 120.187 5.168 119.956 5.198 120.165 ; #517 1 63.462 -76.555 63.602 -77.099 63.423 -76.868 ; #518 1 30.835 131.060 30.541 130.945 30.684 131.060 ; #519 1 -5.102 121.901 -5.365 121.923 -5.209 122.033 ; #520 1 12.379 -69.159 12.151 -68.940 12.283 -69.044 ; #521 1 -54.091 -71.533 -54.269 -71.247 -54.132 -71.137 ; #522 1 70.973 53.071 71.275 52.824 71.102 52.830 ; #523 1 51.967 -176.643 51.728 -176.813 51.819 -176.522 ; #524 1 12.305 119.885 12.096 120.121 12.234 120.027 ; #525 1 1.731 -157.176 1.904 -157.423 1.753 -157.324 ; #526 1 0.404 6.648 0.170 6.538 0.266 6.725 ; #527 1 68.591 14.973 68.843 15.242 68.739 14.791 ; #528 1 -50.838 -74.192 -50.582 -74.418 -50.777 -74.385 ; #529 1 52.566 5.830 52.429 5.418 52.434 5.736 ; #530 1 34.569 134.995 34.324 134.786 34.401 134.934 ; #531 1 60.574 -68.038 60.352 -68.264 60.412 -67.890 ; #532 1 48.258 -122.604 48.088 -122.538 48.396 -122.621 ; #533 1 -52.093 -74.973 -51.797 -74.846 -51.920 -74.973 ; #534 -1 55.228 -97.275 55.071 -97.709 55.082 -97.451 ; #535 1 -2.690 -79.984 -2.885 -80.209 -2.841 -80.055 ; #536 1 28.673 -17.747 28.747 -17.918 28.495 -17.835 ; #537 1 15.624 40.242 15.810 40.088 15.739 39.989 ; #538 1 -11.445 136.516 -11.192 136.692 -11.302 136.593 ; #539 1 -9.349 161.352 -9.629 161.462 -9.462 161.451 ; #540 1 -7.640 156.516 -7.843 156.670 -7.651 156.687 ; #541 1 16.780 41.874 16.703 42.016 16.876 41.753 ; #542 1 15.624 -61.473 15.368 -61.374 15.552 -61.335 ; #543 1 51.912 -177.066 51.758 -177.445 51.747 -177.203 ; #544 1 -45.170 -73.736 -45.058 -74.077 -45.212 -73.984 ; #545 2 81.986 -51.357 82.209 -52.555 82.055 -52.582 ; #546 1 10.841 92.467 10.621 92.379 10.637 92.538 ; #547 1 -16.157 168.099 -16.310 168.027 -16.297 168.264 ; #548 1 72.843 78.610 72.747 79.099 72.959 79.231 ; #549 2 -65.459 103.423 -65.212 103.077 -65.363 103.077 ; #550 1 13.648 144.874 13.404 144.720 13.511 144.874 ; #551 1 26.231 50.473 25.959 50.522 26.146 50.588 ; #552 1 0.610 -50.374 0.316 -50.418 0.462 -50.346 ; #553 1 16.239 94.648 16.008 94.467 16.088 94.621 ; #554 -1 49.624 -118.110 49.478 -118.071 49.780 -118.104 ; #555 1 -8.473 124.022 -8.316 124.258 -8.319 124.110 ; #556 2 77.986 -114.786 77.769 -114.313 77.942 -114.005 ; #557 1 8.173 98.297 7.898 98.313 8.041 98.396 ; #558 -1 26.558 -99.148 26.832 -99.275 26.665 -99.242 ; #559 1 16.959 -25.192 17.140 -25.110 17.055 -25.341 ; #560 1 -19.110 178.093 -19.027 178.352 -18.956 178.319 ; #561 1 -21.431 168.033 -21.516 167.874 -21.632 168.077 ; #562 1 -54.942 -69.203 -54.940 -69.703 -54.989 -69.407 ; #563 1 15.030 121.879 14.775 121.923 14.934 122.005 ; #564 1 15.044 -23.577 15.198 -23.758 15.000 -23.731 ; #565 -1 56.280 -95.863 56.170 -96.324 56.154 -96.071 ; #566 1 68.701 -75.280 68.440 -75.071 68.607 -74.967 ; #567 1 28.393 -96.407 28.217 -96.676 28.286 -96.511 ; #568 1 -0.783 -89.473 -0.907 -89.484 -0.723 -89.286 ; #569 1 54.412 -4.363 54.190 -4.626 54.261 -4.374 ; #570 1 10.390 103.929 10.151 103.978 10.308 104.066 ; #571 1 68.887 15.451 69.126 15.868 69.052 15.549 ; #572 1 -60.731 -45.170 -60.574 -45.665 -60.668 -45.478 ; #573 1 69.429 -77.236 69.201 -77.181 69.330 -76.824 ; #574 1 68.157 14.220 68.335 14.786 68.299 14.396 ; #575 2 -77.102 -149.115 -76.931 -149.967 -77.085 -149.857 ; #576 1 25.343 -80.264 25.110 -80.456 25.201 -80.346 ; #577 1 53.407 -4.495 53.217 -4.478 53.299 -4.198 ; #578 1 -15.354 168.159 -15.069 168.148 -15.162 168.121 ; #579 1 -0.772 130.846 -0.849 130.582 -0.849 130.802 ; #580 1 51.904 -178.093 51.712 -178.022 51.788 -177.791 ; #581 1 65.629 -37.929 65.673 -37.505 65.830 -37.703 ; #582 1 69.533 18.192 69.717 18.742 69.673 18.319 ; #583 1 60.555 -172.995 60.374 -172.549 60.470 -172.764 ; #584 1 69.797 19.181 69.984 19.456 69.967 18.951 ; #585 1 -48.393 -74.923 -48.159 -75.005 -48.297 -75.137 ; #586 1 -2.110 33.132 -1.953 32.962 -2.052 32.907 ; #587 1 -8.165 138.819 -8.261 138.643 -8.346 138.813 ; #588 1 37.890 -75.346 38.143 -75.176 38.058 -75.236 ; #589 1 56.478 -132.363 56.236 -132.165 56.382 -132.143 ; #590 2 -74.451 -130.786 -74.352 -131.571 -74.508 -131.396 ; #591 1 -9.253 150.154 -9.459 150.231 -9.338 150.330 ; #592 1 34.687 129.467 34.437 129.330 34.563 129.462 ; #593 1 56.516 -79.555 56.316 -79.879 56.365 -79.659 ; #594 1 55.148 10.923 54.896 10.725 55.003 10.857 ; #595 1 -47.978 -74.341 -47.937 -73.995 -47.865 -74.280 ; #596 1 54.945 11.753 54.720 11.846 54.838 12.005 ; #597 2 76.813 -90.291 76.574 -90.165 76.706 -89.791 ; #598 1 49.780 -124.648 49.596 -124.341 49.712 -124.429 ; #599 1 22.159 91.082 22.409 91.132 22.363 91.044 ; #600 1 56.799 -132.901 56.599 -132.907 56.615 -132.670 ; #601 1 -7.879 157.016 -8.080 157.033 -7.975 157.176 ; #602 1 -5.022 154.610 -5.275 154.610 -5.137 154.692 ; #603 1 16.321 -61.522 16.236 -61.319 16.412 -61.412 ; #604 1 13.717 -60.940 13.953 -60.918 13.832 -61.033 ; #605 1 -23.755 151.269 -23.530 151.159 -23.657 151.115 ; #606 1 52.794 -128.390 52.527 -128.401 52.651 -128.324 ; #607 1 -50.544 166.192 -50.775 166.027 -50.701 166.203 ; #608 1 -19.470 169.407 -19.448 169.253 -19.635 169.407 ; #609 2 -77.203 -148.555 -77.316 -147.753 -77.126 -148.000 ; #610 1 -12.162 44.209 -12.264 44.429 -12.140 44.374 ; #611 2 -65.876 -66.099 -65.657 -65.775 -65.728 -66.060 ; #612 2 75.962 -102.082 75.852 -102.989 75.830 -102.478 ; #613 1 35.824 27.220 35.563 27.143 35.668 27.192 ; #614 -1 48.538 -118.137 48.412 -118.181 48.673 -118.093 ; #615 1 -3.706 128.060 -3.640 128.280 -3.563 128.170 ; #616 2 -74.508 -127.077 -74.330 -127.593 -74.500 -127.604 ; #617 1 60.291 22.934 60.121 22.577 60.151 22.841 ; #618 1 34.819 -76.346 34.734 -76.434 34.931 -76.214 ; #619 1 -0.146 -51.132 -0.330 -51.302 -0.283 -51.176 ; #620 1 -10.813 165.797 -10.769 166.033 -10.703 165.907 ; #621 -1 -4.137 15.527 -4.176 15.357 -4.316 15.445 ; #622 1 -52.228 -73.698 -52.011 -73.945 -52.118 -73.863 ; #623 1 -17.099 49.835 -16.863 49.956 -16.953 49.885 ; #624 1 40.025 25.440 39.929 25.170 39.868 25.297 ; #625 1 -7.810 129.604 -7.975 129.654 -7.876 129.786 ; #626 1 52.816 -129.264 52.588 -129.093 52.712 -129.071 ; #627 1 55.261 14.753 55.058 14.912 55.195 15.005 ; #628 1 -51.475 -75.016 -51.327 -74.687 -51.346 -74.896 ; #629 1 19.511 93.659 19.343 93.824 19.489 93.824 ; #630 1 -44.802 -74.286 -44.717 -74.033 -44.665 -74.286 ; #631 1 70.277 23.165 70.475 23.484 70.442 23.121 ; #632 1 -49.865 -75.231 -49.668 -75.390 -49.777 -75.467 ; #633 1 39.129 1.544 38.975 1.335 38.995 1.544 ; #634 1 29.981 48.143 29.764 48.170 29.865 48.280 ; #635 1 16.283 -86.632 16.382 -86.385 16.374 -86.505 ; #636 1 63.258 -41.247 63.423 -41.549 63.363 -41.681 ; #637 1 55.876 -6.302 55.698 -6.363 55.761 -6.088 ; #638 1 59.962 -43.813 60.008 -43.445 60.088 -43.819 ; #639 1 62.297 -7.192 62.077 -6.951 62.187 -6.956 ; #640 -1 56.390 -94.802 56.431 -95.236 56.352 -95.071 ; #641 1 2.184 -50.379 1.997 -50.462 2.036 -50.313 ; #642 -1 66.805 -125.533 66.717 -125.099 66.887 -125.214 ; #643 1 -17.003 179.929 -16.827 -179.907 -16.874 179.951 ; #644 1 55.286 -159.879 55.074 -160.093 55.137 -159.918 ; #645 2 76.121 -78.923 75.931 -79.434 75.937 -79.033 ; #646 2 -70.585 72.121 -70.385 72.005 -70.412 71.742 ; #647 1 69.019 -100.484 68.821 -100.560 68.849 -100.236 ; #648 1 0.648 -50.077 0.495 -50.225 0.505 -50.071 ; #649 -1 34.967 97.615 34.810 97.725 34.975 97.797 ; #650 1 69.918 -51.110 69.717 -51.192 69.802 -50.835 ; #651 1 22.385 -73.154 22.341 -72.901 22.418 -73.005 ; #652 1 12.341 98.346 12.560 98.412 12.503 98.319 ; #653 1 16.566 -24.313 16.621 -24.187 16.657 -24.423 ; #654 1 -46.102 -75.060 -45.956 -74.813 -45.951 -74.984 ; #655 1 7.725 134.632 7.500 134.555 7.566 134.643 ; #656 1 44.151 14.846 43.973 15.082 44.063 15.005 ; #657 1 -0.423 -91.588 -0.330 -91.473 -0.286 -91.665 ; #658 1 60.396 19.857 60.209 19.824 60.247 20.071 ; #659 1 40.036 4.220 40.044 4.000 39.909 4.192 ; #660 1 63.571 9.132 63.560 8.626 63.492 8.852 ; #661 1 37.775 27.066 37.761 26.780 37.690 26.918 ; #662 2 -61.247 -55.341 -61.170 -54.951 -61.115 -55.264 ; #663 1 -50.794 -75.319 -50.569 -75.269 -50.673 -75.418 ; #664 1 57.321 -135.786 57.115 -135.780 57.190 -135.593 ; #665 1 42.956 16.676 42.920 17.000 42.970 16.918 ; #666 1 1.385 103.989 1.390 103.769 1.305 103.868 ; #667 1 -0.291 -90.786 -0.247 -90.632 -0.148 -90.791 ; #668 1 20.580 -86.742 20.434 -86.940 20.442 -86.830 ; #669 1 36.874 27.352 36.799 27.060 36.799 27.187 ; #670 1 3.429 125.659 3.621 125.533 3.489 125.544 ; #671 1 33.802 11.055 33.849 10.841 33.714 10.896 ; #672 1 -11.324 132.593 -11.099 132.582 -11.173 132.516 ; #673 1 -49.049 -75.231 -48.882 -75.440 -48.995 -75.456 ; #674 -1 32.011 -85.099 31.775 -85.121 31.821 -85.082 ; #675 1 -8.085 131.033 -8.236 130.879 -8.190 131.044 ; #676 1 69.753 -78.165 69.591 -78.544 69.607 -78.148 ; #677 1 58.956 -2.687 59.025 -3.088 58.934 -2.995 ; #678 1 11.953 119.890 11.769 119.945 11.843 120.027 ; #679 1 -51.626 -75.291 -51.420 -75.126 -51.475 -75.253 ; #680 1 37.876 20.648 37.714 20.824 37.824 20.835 ; #681 1 56.437 -78.698 56.247 -78.852 56.253 -78.692 ; #682 1 7.574 -81.813 7.376 -81.731 7.489 -81.692 ; #683 1 -8.426 151.093 -8.657 151.077 -8.571 151.121 ; #684 1 -45.772 -74.434 -45.599 -74.291 -45.618 -74.467 ; #685 1 -52.989 73.236 -53.118 73.544 -53.016 73.451 ; #686 1 43.343 16.429 43.280 16.709 43.368 16.665 ; #687 2 -73.071 -90.341 -73.000 -89.736 -72.929 -90.077 ; #688 1 58.808 -160.703 58.681 -161.022 58.657 -160.841 ; #689 1 -8.121 127.780 -8.209 127.984 -8.126 127.934 ; #690 1 62.772 -70.588 62.843 -70.940 62.684 -70.692 ; #691 1 -27.728 153.423 -27.514 153.484 -27.574 153.407 ; #692 1 37.970 24.725 37.794 24.846 37.871 24.918 ; #693 1 52.055 -128.033 51.868 -128.165 51.904 -127.989 ; #694 1 -52.352 -74.016 -52.159 -74.209 -52.245 -74.209 ; #695 1 -10.577 121.714 -10.555 121.912 -10.470 121.852 ; #696 1 -54.725 -64.291 -54.780 -64.544 -54.786 -64.165 ; #697 1 49.841 -126.896 49.692 -126.852 49.761 -126.665 ; #698 1 56.143 -133.291 56.047 -133.610 56.005 -133.440 ; #699 1 45.225 14.555 45.047 14.566 45.077 14.703 ; #700 -1 52.236 104.352 52.047 104.566 52.129 104.527 ; #701 1 -7.975 39.725 -7.805 39.846 -7.865 39.714 ; #702 1 53.712 -128.830 53.558 -129.104 53.582 -128.956 ; #703 2 77.118 96.005 77.025 95.929 77.195 96.527 ; #704 1 11.343 -60.527 11.242 -60.720 11.236 -60.610 ; #705 1 -48.038 -75.247 -47.967 -74.934 -47.959 -75.055 ; #706 1 -0.566 -50.835 -0.681 -51.000 -0.701 -50.879 ; #707 1 54.085 -130.379 53.975 -130.615 53.923 -130.445 ; #708 1 -8.429 119.451 -8.621 119.407 -8.569 119.505 ; #709 1 24.527 -112.016 24.418 -111.819 24.505 -111.852 ; #710 1 60.412 -146.132 60.390 -146.538 60.332 -146.352 ; #711 1 -15.481 167.714 -15.404 167.901 -15.368 167.775 ; #712 1 29.753 -84.703 29.651 -84.929 29.668 -84.846 ; #713 2 76.731 -100.286 76.665 -101.148 76.640 -100.780 ; #714 1 55.712 -5.297 55.530 -5.308 55.588 -5.132 ; #715 -1 44.602 -92.577 44.492 -92.313 44.541 -92.363 ; #716 1 55.404 -160.720 55.266 -160.824 55.250 -160.610 ; #717 1 23.673 -76.027 23.525 -75.846 23.604 -75.896 ; #718 1 22.099 -77.945 21.986 -77.764 22.077 -77.791 ; #719 1 -45.755 -73.654 -45.574 -73.626 -45.618 -73.758 ; #720 1 -27.352 153.429 -27.143 153.429 -27.203 153.374 ; #721 1 -48.695 -75.588 -48.558 -75.385 -48.560 -75.549 ; #722 1 50.690 -1.071 50.723 -1.346 50.624 -1.286 ; #723 1 37.684 26.357 37.604 26.115 37.585 26.225 ; #724 1 56.926 -61.467 56.731 -61.566 56.783 -61.440 ; #725 1 -52.140 -74.874 -51.953 -74.714 -52.003 -74.830 ; #726 1 -1.357 149.566 -1.527 149.643 -1.437 149.692 ; #727 1 13.077 -59.478 13.236 -59.533 13.148 -59.615 ; #728 1 -0.261 127.231 -0.374 127.126 -0.412 127.247 ; #729 1 47.104 -56.363 46.907 -56.363 46.934 -56.286 ; #730 1 -8.412 157.352 -8.604 157.297 -8.560 157.368 ; #731 1 51.717 -128.016 51.538 -128.066 51.574 -127.923 ; #732 1 -12.816 45.088 -12.857 45.170 -12.676 45.099 ; #733 1 12.302 -68.396 12.148 -68.313 12.198 -68.253 ; #734 1 38.846 20.692 38.709 20.588 38.668 20.681 ; #735 1 -8.376 143.324 -8.459 143.478 -8.382 143.495 ; #736 2 76.272 96.000 76.192 95.698 76.201 96.451 ; #737 1 -11.684 136.181 -11.577 136.363 -11.588 136.297 ; #738 2 -67.780 -67.742 -67.745 -67.357 -67.654 -67.577 ; #739 1 34.049 -119.890 33.992 -119.670 34.052 -119.692 ; #740 1 28.157 -115.181 28.247 -115.280 28.091 -115.308 ; #741 1 54.742 8.291 54.915 8.429 54.893 8.308 ; #742 1 -4.110 133.319 -4.236 133.478 -4.181 133.445 ; #743 2 -64.533 -57.467 -64.467 -57.060 -64.431 -57.258 ; #744 1 22.827 -74.346 22.709 -74.181 22.777 -74.192 ; #745 -1 29.473 -101.192 29.508 -101.000 29.555 -101.176 ; #746 1 49.096 -123.692 48.942 -123.495 48.981 -123.533 ; #747 1 50.431 -125.291 50.272 -125.247 50.299 -125.126 ; #748 1 68.044 13.495 68.140 13.813 68.198 13.621 ; #749 -1 30.398 32.330 30.253 32.456 30.299 32.484 ; #750 1 11.448 98.187 11.621 98.275 11.580 98.209 ; #751 -1 53.646 -103.412 53.574 -103.698 53.549 -103.571 ; #752 2 75.382 81.791 75.338 82.093 75.497 82.154 ; #753 -1 -21.525 -44.434 -21.393 -44.473 -21.376 -44.555 ; #754 1 -49.272 -75.516 -49.126 -75.385 -49.140 -75.533 ; #755 1 -10.632 152.549 -10.684 152.731 -10.640 152.703 ; #756 -1 46.648 -111.692 46.484 -111.582 46.516 -111.538 ; #757 1 34.701 -76.692 34.684 -76.934 34.687 -76.874 ; #758 1 29.352 -94.813 29.217 -94.967 29.253 -94.874 ; #759 1 17.720 -64.885 17.714 -64.703 17.766 -64.720 ; #760 -1 34.511 -114.379 34.374 -114.214 34.412 -114.242 ; #761 1 -0.492 32.214 -0.310 32.209 -0.393 32.170 ; #762 1 60.602 -145.769 60.541 -146.099 60.500 -146.033 ; #763 1 -45.025 -74.313 -44.992 -74.093 -44.926 -74.170 ; #764 1 50.283 -125.291 50.110 -125.264 50.154 -125.192 ; #765 1 18.788 -91.538 18.714 -91.714 18.712 -91.643 ; #766 1 12.225 52.088 12.170 52.264 12.214 52.236 ; #767 -1 34.401 -83.918 34.269 -84.016 34.302 -83.885 ; #768 -1 -29.981 24.725 -30.124 24.852 -30.077 24.857 ; #769 1 22.799 -79.632 22.701 -79.467 22.742 -79.500 ; #770 1 28.126 -96.857 27.984 -96.973 27.989 -96.923 ; #771 1 68.091 13.099 67.942 12.907 67.951 13.033 ; #772 1 22.404 -78.313 22.332 -78.170 22.390 -78.154 ; #773 1 10.728 98.286 10.868 98.236 10.832 98.187 ; #774 1 2.055 97.341 2.184 97.253 2.126 97.236 ; #775 -1 57.385 -4.341 57.255 -4.527 57.261 -4.495 ; #776 1 17.901 -87.995 18.030 -87.901 18.030 -87.934 ; #777 2 77.060 149.060 77.060 149.621 77.198 149.341 ; #778 2 77.060 156.934 77.060 157.500 77.198 157.220 ; #779 2 77.060 158.621 76.500 158.621 76.643 158.912 ; #780 1 71.437 -175.500 71.437 -174.934 71.580 -175.220 ; #781 1 60.187 154.687 60.187 154.945 60.302 154.835 ; #782 1 59.624 153.000 59.624 153.560 59.766 153.280 ; #783 1 52.310 175.500 52.310 176.060 52.445 175.780 ; #784 1 38.810 -29.808 38.810 -28.687 38.975 -29.247 ; #785 -1 35.437 3.934 35.437 4.500 35.604 4.231 ; #786 1 33.187 -16.308 33.352 -16.099 33.750 -16.308 ; #787 -1 33.750 -2.247 33.750 -1.687 33.846 -1.962 ; #788 1 32.624 -65.247 32.060 -65.808 32.060 -65.247 ; #789 1 28.687 -178.308 28.687 -177.747 28.797 -178.022 ; #790 1 28.687 -176.060 28.687 -175.500 28.797 -175.720 ; #791 1 25.874 -173.247 26.437 -173.247 26.099 -173.516 ; #792 1 19.124 -82.121 19.124 -81.560 19.206 -81.868 ; #793 1 13.500 -60.187 13.500 -59.621 13.582 -59.896 ; #794 1 12.374 -82.121 12.374 -81.560 12.937 -81.560 ; #795 1 12.374 71.434 12.937 71.434 12.637 71.209 ; #796 1 10.124 -109.687 10.687 -109.687 10.415 -109.896 ; #797 1 3.937 108.000 4.500 108.000 4.500 107.434 ; #798 1 2.250 -158.060 2.250 -157.500 2.332 -157.720 ; #799 -1 0.302 29.126 0.000 29.247 0.560 29.247 ; #800 -1 -1.687 28.687 -1.687 28.907 -1.602 28.791 ; #801 1 -2.250 176.060 -2.810 176.060 -2.802 175.835 ; #802 1 -6.187 176.060 -6.187 176.621 -6.077 176.374 ; #803 1 -7.310 71.434 -7.310 72.000 -6.750 72.000 ; #804 1 -7.874 -141.187 -7.874 -140.621 -7.764 -140.896 ; #805 1 -8.437 -14.621 -7.874 -14.621 -7.874 -14.786 ; #806 1 -9.000 -158.621 -9.000 -158.060 -8.896 -158.280 ; #807 1 -10.124 -139.500 -10.124 -138.934 -9.560 -139.500 ; #808 1 -15.187 -147.934 -15.187 -148.500 -15.269 -148.264 ; #809 1 -15.750 -6.187 -15.750 -5.621 -15.662 -5.841 ; #810 1 -16.874 -145.687 -16.874 -145.121 -16.791 -145.341 ; #811 1 -15.750 -143.995 -16.310 -143.995 -16.008 -143.720 ; #812 1 -15.750 -142.874 -16.310 -143.434 -16.874 -143.434 ; #813 -1 -19.124 -67.500 -18.560 -67.500 -18.560 -68.060 ; #814 1 -19.687 -158.621 -19.124 -158.621 -19.124 -159.187 ; #815 1 -25.310 -131.060 -24.750 -131.060 -25.025 -131.214 ; #816 1 -50.060 165.934 -50.624 165.934 -50.275 166.099 ; #817 1 -54.000 3.934 -54.560 3.934 -54.151 4.071 ; #818 2 -67.500 -91.687 -67.500 -91.121 -67.401 -91.335 ; #819 1 51.187 178.308 51.187 178.874 51.750 178.874 51.750 178.308 51.750 177.747 51.750 177.187 52.310 177.187 51.750 176.923 ; #820 -1 -29.250 136.687 -29.250 137.247 -28.687 137.808 -28.124 137.808 -27.560 137.247 -27.560 136.687 -28.124 136.687 -28.687 136.687 ; #821 -1 -18.560 15.187 -19.124 15.747 -18.560 16.308 -18.560 16.874 -18.000 16.874 -18.000 16.308 -18.000 15.747 ; #822 1 71.437 -9.560 71.437 -9.000 71.437 -8.434 71.437 -7.874 72.000 -7.874 72.000 -8.434 ; #823 -1 -24.750 129.934 -24.750 130.500 -24.750 131.060 -24.187 131.060 -24.187 130.500 -24.187 129.934 ; #824 1 10.687 72.000 10.687 72.560 11.250 72.560 11.810 72.560 11.250 72.000 ; #825 -1 -30.937 139.500 -30.937 140.060 -30.374 140.060 -29.810 140.060 -30.374 139.500 ; #826 1 56.810 -170.434 56.810 -169.874 57.374 -171.000 57.374 -170.434 ; #827 -1 49.500 135.560 49.500 136.121 50.060 136.121 50.060 135.560 ; #828 -1 50.624 136.264 50.624 136.687 51.187 136.687 51.187 136.264 ; #829 1 32.624 -17.434 32.624 -16.874 33.750 -16.874 33.187 -17.434 ; #830 -1 29.250 53.434 29.810 53.434 29.810 52.874 29.810 52.308 ; #831 1 19.124 -111.374 19.124 -110.808 19.687 -110.808 19.687 -111.374 ; #832 1 16.310 -23.060 16.310 -23.621 15.750 -24.187 15.187 -24.187 ; #833 1 13.500 144.000 13.500 144.560 14.060 144.560 14.060 144.000 ; #834 1 9.560 169.874 10.124 169.874 10.124 169.308 10.124 168.747 ; #835 1 -1.124 174.934 -0.560 174.374 -0.560 173.808 -1.124 174.374 ; #836 1 -14.060 146.247 -14.060 146.808 -13.500 146.808 -13.500 146.247 ; #837 1 -21.937 -158.621 -21.937 -158.060 -21.374 -158.060 -21.374 -158.621 ; #838 -1 -23.624 122.621 -23.624 123.187 -23.060 123.187 -23.060 122.621 ; #839 -1 -29.250 139.500 -29.250 140.060 -28.687 139.500 -28.687 138.934 ; #840 1 -46.687 37.121 -46.687 37.687 -46.124 37.687 -46.124 37.121 ; #841 2 -66.937 178.308 -66.937 178.874 -66.374 178.874 -66.374 178.308 ; end jana/libjana-gtk/data/Makefile.am0000644000175000017500000000032011327631152017023 0ustar paulliupaulliuresdir = $(pkgdatadir) res_DATA = landwater.vmf if WITH_GLADE gladedir = $(catalogdir) glade_DATA = libjana-gtk-catalog.xml endif MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(res_DATA) $(glade_DATA) jana/libjana-gtk/data/libjana-gtk-catalog.xml0000644000175000017500000001035611327631152021316 0ustar paulliupaulliu libjana-gtk jana_gtk_clock_glade_post_create jana_gtk_date_time_glade_post_create empty empty empty empty jana_gtk_world_map_glade_post_create jana/libjana-gtk/jana-gtk-month-view.h0000644000175000017500000000623211327631152020026 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_MONTH_VIEW_H #define _JANA_GTK_MONTH_VIEW_H #include #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_MONTH_VIEW jana_gtk_month_view_get_type() #define JANA_GTK_MONTH_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_MONTH_VIEW, JanaGtkMonthView)) #define JANA_GTK_MONTH_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_MONTH_VIEW, JanaGtkMonthViewClass)) #define JANA_GTK_IS_MONTH_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_MONTH_VIEW)) #define JANA_GTK_IS_MONTH_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_MONTH_VIEW)) #define JANA_GTK_MONTH_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_MONTH_VIEW, JanaGtkMonthViewClass)) typedef struct { GtkEventBox parent; } JanaGtkMonthView; typedef struct { GtkEventBoxClass parent_class; /* Signals */ void (*selection_changed) (JanaGtkMonthView *self, JanaTime *day); } JanaGtkMonthViewClass; enum { JANA_GTK_MONTH_VIEW_COL_ROW, JANA_GTK_MONTH_VIEW_COL_LAST }; GType jana_gtk_month_view_get_type (void); GtkWidget * jana_gtk_month_view_new (JanaTime *month); void jana_gtk_month_view_add_store (JanaGtkMonthView *self, JanaGtkEventStore *store); void jana_gtk_month_view_remove_store (JanaGtkMonthView *self, JanaGtkEventStore *store); JanaGtkCellRendererEvent * jana_gtk_month_view_get_cell_renderer (JanaGtkMonthView *self); void jana_gtk_month_view_set_month (JanaGtkMonthView *self, JanaTime *month); JanaTime * jana_gtk_month_view_get_month (JanaGtkMonthView *self); void jana_gtk_month_view_set_spacing (JanaGtkMonthView *self, guint spacing); guint jana_gtk_month_view_get_spacing (JanaGtkMonthView *self); void jana_gtk_month_view_set_selection (JanaGtkMonthView *self, JanaTime *day); JanaTime * jana_gtk_month_view_get_selection (JanaGtkMonthView *self); void jana_gtk_month_view_set_visible_func (JanaGtkMonthView *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data); void jana_gtk_month_view_refilter (JanaGtkMonthView *self); void jana_gtk_month_view_set_highlighted_time(JanaGtkMonthView *self, JanaTime *time); G_END_DECLS #endif /* _JANA_GTK_MONTH_VIEW_H */ jana/libjana-gtk/jana-gtk-cell-renderer-event.h0000644000175000017500000000407311327631152021574 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_CELL_RENDERER_EVENT_H #define _JANA_GTK_CELL_RENDERER_EVENT_H #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_CELL_RENDERER_EVENT \ jana_gtk_cell_renderer_event_get_type() #define JANA_GTK_CELL_RENDERER_EVENT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_EVENT, JanaGtkCellRendererEvent)) #define JANA_GTK_CELL_RENDERER_EVENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_CELL_RENDERER_EVENT, JanaGtkCellRendererEventClass)) #define JANA_GTK_IS_CELL_RENDERER_EVENT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_EVENT)) #define JANA_GTK_IS_CELL_RENDERER_EVENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_CELL_RENDERER_EVENT)) #define JANA_GTK_CELL_RENDERER_EVENT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_EVENT, JanaGtkCellRendererEventClass)) typedef struct { GtkCellRenderer parent; } JanaGtkCellRendererEvent; typedef struct { GtkCellRendererClass parent_class; } JanaGtkCellRendererEventClass; GType jana_gtk_cell_renderer_event_get_type (void); GtkCellRenderer* jana_gtk_cell_renderer_event_new (void); G_END_DECLS #endif /* _JANA_GTK_CELL_RENDERER_EVENT_H */ jana/libjana-gtk/jana-gtk-month-view.c0000644000175000017500000006433411327631152020030 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include "jana-gtk-month-view.h" G_DEFINE_TYPE (JanaGtkMonthView, jana_gtk_month_view, GTK_TYPE_EVENT_BOX) #define MONTH_VIEW_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_MONTH_VIEW, \ JanaGtkMonthViewPrivate)) typedef struct _JanaGtkMonthViewPrivate JanaGtkMonthViewPrivate; struct _JanaGtkMonthViewPrivate { GtkWidget *alignment; GtkWidget *layout; GtkCellRenderer *event_renderer; GtkAllocation allocation; gint visible_weeks; JanaTime *start; JanaTime *end; JanaTime *selection; JanaTime *month; gchar *style_hint; guint spacing; JanaTime *highlighted_time; }; enum { PROP_MONTH = 1, PROP_SPACING, PROP_STYLE_HINT, PROP_SELECTION, PROP_HIGHLIGHTED_TIME, }; enum { SELECTION_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void relayout (JanaGtkMonthView *self); static void jana_gtk_month_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (object); switch (property_id) { case PROP_MONTH : if (priv->month) g_value_take_object (value, jana_time_duplicate (priv->month)); break; case PROP_SPACING : g_value_set_uint (value, priv->spacing); break; case PROP_STYLE_HINT : g_value_set_string (value, priv->style_hint); break; case PROP_SELECTION : g_value_take_object (value, priv->selection ? jana_time_duplicate (priv->selection) : NULL); break; case PROP_HIGHLIGHTED_TIME : if (priv->highlighted_time) g_value_take_object (value, jana_time_duplicate (priv->highlighted_time)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_month_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (object); switch (property_id) { case PROP_MONTH : jana_gtk_month_view_set_month (JANA_GTK_MONTH_VIEW (object), g_value_get_object (value)); break; case PROP_SPACING : jana_gtk_month_view_set_spacing ( JANA_GTK_MONTH_VIEW (object), g_value_get_uint (value)); break; case PROP_STYLE_HINT : if (priv->style_hint) { g_free (priv->style_hint); priv->style_hint = NULL; } priv->style_hint = g_value_dup_string (value); gtk_widget_queue_draw (GTK_WIDGET (object)); break; case PROP_SELECTION : jana_gtk_month_view_set_selection (JANA_GTK_MONTH_VIEW (object), g_value_get_object (value)); break; case PROP_HIGHLIGHTED_TIME : jana_gtk_month_view_set_highlighted_time ( JANA_GTK_MONTH_VIEW (object), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_month_view_dispose (GObject *object) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (object); if (priv->event_renderer) { g_object_unref (priv->event_renderer); priv->event_renderer = NULL; } if (G_OBJECT_CLASS (jana_gtk_month_view_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_month_view_parent_class)-> dispose (object); } static void jana_gtk_month_view_finalize (GObject *object) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (object); if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } if (priv->start) { g_object_unref (priv->start); priv->start = NULL; } if (priv->end) { g_object_unref (priv->end); priv->end = NULL; } if (priv->month) { g_object_unref (priv->month); priv->month = NULL; } if (priv->selection) { g_object_unref (priv->selection); priv->selection = NULL; } if (priv->style_hint) { g_free (priv->style_hint); priv->style_hint = NULL; } G_OBJECT_CLASS (jana_gtk_month_view_parent_class)->finalize (object); } static gboolean jana_gtk_month_view_expose_event (GtkWidget *widget, GdkEventExpose *event) { JanaTime *time; gint week; gint x, y, box_y, row0_height, row_height = 0, col0_width, col_width = 0; GtkStyle *dark_style, *light_style, *style; PangoLayout *layout; JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (widget); if (!priv->month) return FALSE; /* Draw background */ box_y = 0; row_height = widget->allocation.height / (priv->visible_weeks + 1); layout = gtk_widget_create_pango_layout (widget, NULL); dark_style = gtk_style_copy (widget->style); dark_style->bg[GTK_STATE_NORMAL] = dark_style->bg[GTK_STATE_ACTIVE]; dark_style->fg[GTK_STATE_NORMAL] = dark_style->fg[GTK_STATE_ACTIVE]; dark_style = gtk_style_attach (dark_style, widget->window); light_style = gtk_style_copy (widget->style); light_style->bg[GTK_STATE_NORMAL] = light_style->base[GTK_STATE_NORMAL]; light_style->bg[GTK_STATE_SELECTED] = light_style->base[GTK_STATE_SELECTED]; light_style = gtk_style_attach (light_style, widget->window); time = jana_time_duplicate (priv->start); for (y = 0; y < priv->visible_weeks + 1; y++) { gint box_x = 0, box_height = 0; week = ((gint)jana_utils_time_week_of_year (time, TRUE)); for (x = 0; x < 8; x++) { gint box_width, text_width, text_height; GtkShadowType shadow = GTK_SHADOW_IN; GtkStateType state = GTK_STATE_NORMAL; style = light_style; if (y == 0) { if (x == 0) { guint top, left; /* Month label */ pango_layout_set_text (layout, nl_langinfo (ABMON_1 + (jana_time_get_month ( priv->month) - 1)), -1); pango_layout_get_pixel_size ( layout, &col0_width, &row0_height); /* The first column/row will fit to the * text size (+ spacing) */ col0_width += priv->spacing * 2; row0_height += priv->spacing * 2; col_width = (widget->allocation.width - col0_width) / 7; row_height = (widget->allocation.height- row0_height) / priv->visible_weeks; /* Align the tree layout to the events * area. */ gtk_alignment_get_padding ( GTK_ALIGNMENT (priv->alignment), &top, NULL, &left, NULL); if ((top != row0_height) || (left != col0_width)) { gtk_alignment_set_padding ( GTK_ALIGNMENT (priv-> alignment), row0_height, 0, col0_width, 0); } } else { /* Day label */ pango_layout_set_text (layout, jana_utils_ab_day (x - 1), -1); } } else if (x == 0) { gchar week_string[3]; /* Week label */ snprintf (week_string, 3, "%02d", week); pango_layout_set_text (layout, week_string, -1); } else { /* We're in a date box, so check if we're in * the month (and if not, set insensitive), * and increment day. */ if ((priv->selection) && (jana_utils_time_compare (time, priv->selection, TRUE) == 0)) { state = GTK_STATE_SELECTED; } else if (jana_time_get_month (time) != jana_time_get_month (priv->month)) { state = GTK_STATE_INSENSITIVE; } jana_time_set_day (time, jana_time_get_day (time) + 1); } if ((x == 0) || (y == 0)) { shadow = GTK_SHADOW_OUT; style = dark_style; } if (x == 0) box_width = col0_width; else box_width = col_width; if (y == 0) box_height = row0_height; else box_height = row_height; gtk_paint_flat_box (style, widget->window, state, shadow, &event->area, widget, priv->style_hint, box_x, box_y, box_width, box_height); gtk_paint_shadow (style, widget->window, state, shadow, &event->area, widget, priv->style_hint, box_x, box_y, box_width, box_height); pango_layout_get_pixel_size ( layout, &text_width, &text_height); if ((x == 0) || (y == 0)) gtk_paint_layout (style, widget->window, state, FALSE, &event->area, widget, priv->style_hint, box_x + (box_width / 2) - (text_width / 2), box_y + (box_height / 2) - (text_height / 2), layout); box_x += box_width; } box_y += box_height; } gtk_style_detach (dark_style); GTK_WIDGET_CLASS (jana_gtk_month_view_parent_class)-> expose_event (widget, event); /* Draw date labels */ jana_utils_time_copy (priv->start, time); for (y = 0; y < priv->visible_weeks; y++) { for (x = 0; x < 7; x++) { gint text_width, text_height; GtkStateType state; /* Date label */ if (priv->highlighted_time && (jana_utils_time_compare ( priv->highlighted_time, time, TRUE) == 0)) { gchar *markup = g_strdup_printf ("%d", jana_time_get_day (time)); pango_layout_set_markup (layout, markup, -1); g_free (markup); } else { gchar date_string[3]; snprintf (date_string, 3, "%d", jana_time_get_day (time)); pango_layout_set_markup ( layout, date_string, -1); } if ((priv->selection) && (jana_utils_time_compare ( priv->selection, time, TRUE) == 0)) { state = GTK_STATE_SELECTED; } else if (jana_time_get_month (time) != jana_time_get_month (priv->month)) state = GTK_STATE_INSENSITIVE; else state = GTK_STATE_NORMAL; pango_layout_get_pixel_size ( layout, &text_width, &text_height); gtk_paint_layout (light_style, widget->window, state, TRUE, &event->area, widget, priv->style_hint, (x * col_width) + (col_width / 2) + col0_width - (text_width / 2), (y * row_height) + row0_height + (row_height / 2) - (text_height / 2), layout); jana_time_set_day (time, jana_time_get_day (time) + 1); } } gtk_style_detach (light_style); g_object_unref (layout); g_object_unref (time); return FALSE; } static void relayout (JanaGtkMonthView *self) { gint x, y, width, height; JanaTime *time; GList *cell, *cells; JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (!priv->month) return; cells = jana_gtk_tree_layout_get_cells ( JANA_GTK_TREE_LAYOUT (priv->layout)); if (!cells) return; /* Place cells in their day boxes, 4 events per box */ width = priv->layout->allocation.width / 7; height = priv->layout->allocation.height / priv->visible_weeks; cell = cells; time = jana_time_duplicate (priv->start); for (y = 0; (y < priv->visible_weeks) && (cell); y++) { for (x = 0; (x < 7) && (cell); x++) { gint events = 0; do { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaTime *start; /* Work out what month the cell is in */ model = gtk_tree_row_reference_get_model (info->row); path = gtk_tree_row_reference_get_path (info->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start, -1); if (start && (jana_utils_time_compare ( start, time, TRUE) == 0)) { gint event_x, event_y, event_width, event_height; event_width = (width/2) - (priv->spacing * 1.5); event_height = (height/2) - (priv->spacing * 1.5); switch (events) { case 0 : /* Upper-left quadrant */ event_x = (x * width) + priv->spacing; event_y = (y * height) + priv->spacing; break; case 1 : /* Upper-right quadrant */ event_x = (x * width) + (width/2) + (priv->spacing / 2); event_y = (y * height) + priv->spacing; break; case 2 : /* Lower-left quadrant */ event_x = (x * width) + priv->spacing; event_y = (y * height) + (height / 2) + (priv->spacing / 2); break; case 3 : default : /* Lower-right quadrant */ event_x = (x * width) + (width/2) + (priv->spacing / 2); event_y = (y * height) + (height / 2) + (priv->spacing / 2); break; } if (jana_time_get_month (start) == jana_time_get_month (priv->month)) jana_gtk_tree_layout_set_cell_sensitive ( JANA_GTK_TREE_LAYOUT ( priv->layout), info->row, TRUE); else jana_gtk_tree_layout_set_cell_sensitive ( JANA_GTK_TREE_LAYOUT ( priv->layout), info->row, FALSE); jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT ( priv->layout), info->row, event_x, event_y, event_width, event_height); events ++; g_object_unref (start); } else if (start) { /* Make cell invisible (it isn't in * range). */ jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT ( priv->layout), info->row, 0, 0, 0, 0); g_object_unref (start); break; } cell = cell->next; } while (cell); jana_time_set_day (time, jana_time_get_day (time) + 1); } } g_object_unref (time); g_list_free (cells); } static void size_request_cb (GtkWidget *widget, GtkRequisition *requisition, JanaGtkMonthView *self) { requisition->width = 0; requisition->height = 0; } static void size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if ((allocation->width != priv->allocation.width) || (allocation->height != priv->allocation.height)) { priv->allocation.width = allocation->width; priv->allocation.height = allocation->height; relayout (self); } } static gboolean button_press_event_cb (GtkWidget *layout, GdkEventButton *event, JanaGtkMonthView *self) { JanaTime *date; gint day_increment; JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (!priv->month) return FALSE; /* Work out which day box (and thereby, date) was clicked */ date = jana_time_duplicate (priv->start); day_increment = 6 - (((layout->allocation.width - (gint)event->x + 1) * 7) / layout->allocation.width); day_increment += ((priv->visible_weeks - 1) - (((layout->allocation.height - (gint)event->y + 1) * priv->visible_weeks) / layout->allocation.height)) * 7; jana_time_set_day (date, jana_time_get_day (date) + day_increment); if (priv->selection) g_object_unref (priv->selection); priv->selection = date; g_signal_emit (self, signals[SELECTION_CHANGED], 0, priv->selection); gtk_widget_queue_draw (GTK_WIDGET (self)); return TRUE; } static void jana_gtk_month_view_class_init (JanaGtkMonthViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkMonthViewPrivate)); object_class->get_property = jana_gtk_month_view_get_property; object_class->set_property = jana_gtk_month_view_set_property; object_class->dispose = jana_gtk_month_view_dispose; object_class->finalize = jana_gtk_month_view_finalize; widget_class->expose_event = jana_gtk_month_view_expose_event; g_object_class_install_property ( object_class, PROP_MONTH, g_param_spec_object ( "month", "Month", "A JanaTime in the month this view should show.", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property ( object_class, PROP_SPACING, g_param_spec_uint ( "spacing", "Spacing", "Spacing to use inside month boxes.", 0, G_MAXUINT, 2, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_STYLE_HINT, g_param_spec_string ( "style_hint", "Style hint", "The style hint to use when drawing.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SELECTION, g_param_spec_object ( "selection", "Selection", "The currently selected JanaTime.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_TIME, g_param_spec_object ( "highlighted_time", "Highlighted time", "A time that should be highlighted, " "for example, the current time.", G_TYPE_OBJECT, G_PARAM_READWRITE)); signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkMonthViewClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } static gint sort_cells_cb (JanaGtkTreeLayoutCellInfo *info_a, JanaGtkTreeLayoutCellInfo *info_b) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaTime *start_a, *end_a, *start_b, *end_b; gchar *summary_a, *summary_b; gint result = 0; model = gtk_tree_row_reference_get_model (info_a->row); path = gtk_tree_row_reference_get_path (info_a->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start_a, JANA_GTK_EVENT_STORE_COL_END, &end_a, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary_a, -1); model = gtk_tree_row_reference_get_model (info_b->row); path = gtk_tree_row_reference_get_path (info_b->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start_b, JANA_GTK_EVENT_STORE_COL_END, &end_b, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary_b, -1); if (start_a && start_b) result = jana_utils_time_compare (start_a, start_b, FALSE); if (result == 0) { if (end_a && end_b) result = jana_utils_time_compare (end_b, end_a, FALSE); if ((result == 0) && summary_a && summary_b) result = g_utf8_collate (summary_a, summary_b); } g_free (summary_a); g_free (summary_b); if (start_a) g_object_unref (start_a); if (start_b) g_object_unref (start_b); if (end_a) g_object_unref (end_a); if (end_b) g_object_unref (end_b); return result; } static void jana_gtk_month_view_init (JanaGtkMonthView *self) { static gboolean locale_set = FALSE; JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (!locale_set) { setlocale (LC_TIME, ""); locale_set = TRUE; } gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); priv->spacing = 2; priv->alignment = gtk_alignment_new (0.5, 0.5, 1, 1); priv->layout = jana_gtk_tree_layout_new (); g_object_set (G_OBJECT (priv->layout), "sort_cb", sort_cells_cb, "select_mode", GTK_SELECTION_NONE, NULL); gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout); gtk_container_add (GTK_CONTAINER (self), priv->alignment); gtk_widget_show (priv->alignment); gtk_widget_show (priv->layout); priv->event_renderer = g_object_ref_sink ( jana_gtk_cell_renderer_event_new ()); g_object_set (G_OBJECT (priv->event_renderer), "draw_text", FALSE, NULL); g_signal_connect (priv->layout, "size-request", G_CALLBACK (size_request_cb), self); g_signal_connect (priv->layout, "size-allocate", G_CALLBACK (size_allocate_cb), self); g_signal_connect (priv->layout, "button-press-event", G_CALLBACK (button_press_event_cb), self); } GtkWidget * jana_gtk_month_view_new (JanaTime *month) { return GTK_WIDGET (g_object_new ( JANA_GTK_TYPE_MONTH_VIEW, "month", month, NULL)); } static void row_changed_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkMonthView *self) { relayout (self); } static void row_inserted_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkMonthView *self) { GtkTreeRowReference *row; JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); /* Add row to layout */ row = gtk_tree_row_reference_new (tree_model, path); jana_gtk_tree_layout_add_cell (JANA_GTK_TREE_LAYOUT (priv->layout), row, 0, 0, 0, 0, priv->event_renderer, "uid", JANA_GTK_EVENT_STORE_COL_UID, "categories", JANA_GTK_EVENT_STORE_COL_CATEGORIES, "summary", JANA_GTK_EVENT_STORE_COL_SUMMARY, "description", JANA_GTK_EVENT_STORE_COL_DESCRIPTION, "start", JANA_GTK_EVENT_STORE_COL_START, "end", JANA_GTK_EVENT_STORE_COL_END, "first_instance", JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, "last_instance", JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, "has_recurrences", JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, "has_alarm", JANA_GTK_EVENT_STORE_COL_HAS_ALARM, NULL); gtk_tree_row_reference_free (row); relayout (self); } static void row_deleted_cb (GtkTreeModel *tree_model, GtkTreePath *path, JanaGtkMonthView *self) { relayout (self); } static void insert_rows (JanaGtkMonthView *self, JanaGtkEventStore *store) { GtkTreeIter iter; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) do { GtkTreePath *path = gtk_tree_model_get_path ( (GtkTreeModel *)store, &iter); row_inserted_cb ((GtkTreeModel *)store, path, &iter, self); gtk_tree_path_free (path); } while (gtk_tree_model_iter_next ((GtkTreeModel *)store, &iter)); } static void remove_rows (JanaGtkMonthView *self, JanaGtkEventStore *store) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); GList *cell, *cells = jana_gtk_tree_layout_get_cells ( JANA_GTK_TREE_LAYOUT (priv->layout)); for (cell = cells; cell; cell = cell->next) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; if (gtk_tree_row_reference_get_model (info->row) == (GtkTreeModel *)store) jana_gtk_tree_layout_remove_cell ( (JanaGtkTreeLayout *)self, info->row); } g_list_free (cells); } void jana_gtk_month_view_add_store (JanaGtkMonthView *self, JanaGtkEventStore *store) { insert_rows (self, store); g_signal_connect (store, "row-inserted", G_CALLBACK (row_inserted_cb), self); g_signal_connect_after (store, "row-changed", G_CALLBACK (row_changed_cb), self); g_signal_connect_after (store, "row-deleted", G_CALLBACK (row_deleted_cb), self); } void jana_gtk_month_view_remove_store (JanaGtkMonthView *self, JanaGtkEventStore *store) { g_signal_handlers_disconnect_by_func (store, row_inserted_cb, self); g_signal_handlers_disconnect_by_func (store, row_changed_cb, self); g_signal_handlers_disconnect_by_func (store, row_deleted_cb, self); remove_rows (self, store); } JanaGtkCellRendererEvent * jana_gtk_month_view_get_cell_renderer (JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); return (JanaGtkCellRendererEvent *)priv->event_renderer; } void jana_gtk_month_view_set_month (JanaGtkMonthView *self, JanaTime *month) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (priv->month) { g_object_unref (priv->month); priv->month = NULL; } if (month) { GDateWeekday start_day, end_day, day; JanaTime *time; priv->month = jana_time_duplicate (month); jana_time_set_isdate (priv->month, TRUE); jana_time_set_day (priv->month, 1); priv->start = jana_time_duplicate (priv->month); start_day = jana_utils_time_set_start_of_week (priv->start); priv->end = jana_time_duplicate (priv->month); jana_time_set_day (priv->end, jana_utils_time_days_in_month ( jana_time_get_year (priv->end), jana_time_get_month (priv->end))); end_day = jana_utils_time_set_end_of_week (priv->end); /* Count number of rows (weeks) */ for (priv->visible_weeks = 0, day = start_day, time = jana_time_duplicate (priv->start); jana_utils_time_compare (time, priv->end, TRUE) < 0; jana_time_set_day (time, jana_time_get_day (time) + 1), day++) { if (day > G_DATE_SUNDAY) day -= G_DATE_SUNDAY; if (day == start_day) priv->visible_weeks++; } g_object_unref (time); } if (priv->selection) { g_object_unref (priv->selection); priv->selection = NULL; g_signal_emit (self, signals[SELECTION_CHANGED], 0, NULL); } relayout (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } JanaTime * jana_gtk_month_view_get_month (JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); return priv->month ? jana_time_duplicate (priv->month) : NULL; } void jana_gtk_month_view_set_spacing (JanaGtkMonthView *self, guint spacing) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); priv->spacing = spacing; gtk_widget_queue_draw (GTK_WIDGET (self)); } guint jana_gtk_month_view_get_spacing (JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); return priv->spacing; } void jana_gtk_month_view_set_selection (JanaGtkMonthView *self, JanaTime *day) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (priv->selection) { if (day && jana_utils_time_compare (priv->selection, day, TRUE) == 0) return; g_object_unref (priv->selection); priv->selection = NULL; } if (day) priv->selection = jana_time_duplicate (day); g_signal_emit (self, signals[SELECTION_CHANGED], 0, priv->selection); gtk_widget_queue_draw (GTK_WIDGET (self)); } JanaTime * jana_gtk_month_view_get_selection (JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); return priv->selection ? jana_time_duplicate (priv->selection) : NULL; } void jana_gtk_month_view_set_visible_func (JanaGtkMonthView *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); jana_gtk_tree_layout_set_visible_func ( JANA_GTK_TREE_LAYOUT (priv->layout), visible_cb, data); } void jana_gtk_month_view_refilter (JanaGtkMonthView *self) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); jana_gtk_tree_layout_refilter (JANA_GTK_TREE_LAYOUT (priv->layout)); } void jana_gtk_month_view_set_highlighted_time (JanaGtkMonthView *self, JanaTime *time) { JanaGtkMonthViewPrivate *priv = MONTH_VIEW_PRIVATE (self); if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } if (time) priv->highlighted_time = jana_time_duplicate (time); gtk_widget_queue_draw (GTK_WIDGET (self)); } jana/libjana-gtk/jana-gtk-utils.h0000644000175000017500000000203611327631152017067 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #ifndef _JANA_GTK_UTILS_H #define _JANA_GTK_UTILS_H void jana_gtk_utils_treeview_resize (GtkWidget *tree_view, GtkAllocation *allocation, gpointer cell_renderer); #endif /* JANA_GTK_UTILS_H */ jana/libjana-gtk/jana-gtk-world-map.c0000644000175000017500000007054111327631152017632 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_GLADE #include #endif #include "jana-gtk-world-map.h" #include #include #include #include G_DEFINE_TYPE (JanaGtkWorldMap, jana_gtk_world_map, GTK_TYPE_EVENT_BOX) #define WORLD_MAP_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_WORLD_MAP, \ JanaGtkWorldMapPrivate)) typedef struct _JanaGtkWorldMapPrivate JanaGtkWorldMapPrivate; struct _JanaGtkWorldMapPrivate { JanaTime *time; gint width; gint height; gboolean scale; gboolean clicked; gboolean in; /* Data read from the VMF file */ gdouble phi_min; gdouble phi_max; gdouble theta_min; gdouble theta_max; /* An array of polygon co-ordinate pairs, separated by NULLs and * terminated with two NULLs. * i.e. { {0, 0}, {0, 1}, {1, 1}, NULL, NULL } */ gdouble **map; cairo_surface_t *buffer; GPtrArray *marks; GtkStyle *style; JanaTime *time_copy; GThread *draw_thread; gboolean dirty; }; enum { PROP_TIME = 1, PROP_WIDTH, PROP_HEIGHT, PROP_STATIC }; enum { RENDER_START, RENDER_STOP, CLICKED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; /* * Very basic vmf file reader. It ignores all colour data, open curves, labels, * etc. It just reads in the closed, filled curves, the range of the map and * ignores everything else. The code in sunclock is pretty much unreadable, * so wrote my own. */ #define VMF_LEN 256 #define VMF_ALLOC 5000 static gboolean read_vmf (JanaGtkWorldMap *self) { FILE *vmf; char string[VMF_LEN]; gint i; glong points, alloc_points; gboolean fill; gboolean closed; JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); vmf = fopen (PKGDATADIR G_DIR_SEPARATOR_S "landwater.vmf", "rb"); if (!vmf) { g_warning ("Background data not found"); return FALSE; } /* Check file header */ fgets (string, VMF_LEN, vmf); if (strncmp (string, "%!VMF", 5) != 0) goto vmf_error; /* Skip past colours and palette */ for (i = 0; i < 2; i++) do { if (!fgets (string, VMF_LEN, vmf)) goto vmf_error; } while (string[0] != ';'); /* Get range */ do { if (!fgets (string, VMF_LEN, vmf)) goto vmf_error; } while (strncmp (string, "range ", 6) != 0); if (sscanf (string, "range %lg %lg %lg %lg", &priv->phi_min, &priv->phi_max, &priv->theta_min, &priv->theta_max) != 4) goto vmf_error; /* Read data */ closed = FALSE; fill = TRUE; alloc_points = points = 0; while (fgets (string, VMF_LEN, vmf)) { if (strncmp (string, "closedcurves", 12) == 0) { closed = TRUE; } else if (strncmp (string, "opencurves", 10) == 0) { closed = FALSE; } else if (strncmp (string, "fillmode", 8) == 0) { gint fillmode; if (sscanf (string, "fillmode %d", &fillmode) == 1) fill = (fillmode == 2) ? TRUE : FALSE; } else if ((string[0] == '#') && closed && fill) { /* Read co-ordinate pairs for polygon */ gboolean first_point = TRUE; if (!fgets (string, VMF_LEN, vmf)) goto vmf_error; i = 0; while (string[0] != ';') { gint j; gdouble x, y; gchar *substring = g_strchug (string); while (substring && (substring[0] != '\0')) { for (j = 0; (substring[j] != ' ') && (substring[j] != '\0') && (substring[j] != '\n')&& (substring[j] != '%'); j++); substring[j] = '\0'; if (sscanf (substring, "%lg", i ? &y : &x) != 1) goto vmf_error; if (i == 1) { /* Normalise theta */ /* No idea if this is the * correct way to do this, but * it seems to work correctly */ if ((!first_point) && (y < 0)) { gdouble y2 = y + ( priv->theta_max - priv->theta_min); if (ABS (priv->map[ points-1][1] - y) > ABS (priv->map[ points-1][1] - y2)) y = y2; } /* Allocate memory and * store points - Always * allocate at least 1 more * point than is necessary for * the ending marker. */ points ++; if ((points+1) > alloc_points) { priv->map = g_realloc ( priv->map, sizeof ( gdouble **) * (alloc_points+ VMF_ALLOC)); alloc_points += VMF_ALLOC; } priv->map[points-1] = g_malloc ( sizeof (gdouble) * 2); priv->map[points-1][0] = x; priv->map[points-1][1] = y; i = 0; first_point = FALSE; } else i++; /* Move onto next value */ substring = g_strchug (substring+j+1); } if (!fgets (string, VMF_LEN, vmf)) goto vmf_error; } if (i != 0) g_warning ("Floating co-ordinate"); /* End polygon */ points ++; priv->map[points-1] = NULL; } else if (string[0] == '#') do { /* Skip polygon */ if (!fgets (string, VMF_LEN, vmf)) goto vmf_error; } while (string[0] != ';'); } /* Terminate polygon list and resize allocated memory to what is * needed. */ points ++; if (alloc_points != points) priv->map = g_realloc (priv->map, sizeof (gdouble **) * points); priv->map[points-1] = NULL; fclose (vmf); return TRUE; vmf_error: g_warning ("Error reading .vmf file"); fclose (vmf); return FALSE; } static void jana_gtk_world_map_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (object); switch (property_id) { case PROP_TIME : g_value_take_object (value, priv->time ? jana_time_duplicate (priv->time) : NULL); break; case PROP_STATIC : g_value_set_boolean (value, priv->scale); break; case PROP_WIDTH : g_value_set_int (value, priv->width); break; case PROP_HEIGHT : g_value_set_int (value, priv->height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_world_map_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_TIME : jana_gtk_world_map_set_time (JANA_GTK_WORLD_MAP (object), JANA_TIME (g_value_get_object (value))); break; case PROP_STATIC : jana_gtk_world_map_set_static (JANA_GTK_WORLD_MAP (object), g_value_get_boolean (value)); break; case PROP_WIDTH : jana_gtk_world_map_set_width (JANA_GTK_WORLD_MAP (object), g_value_get_int (value)); break; case PROP_HEIGHT : jana_gtk_world_map_set_height (JANA_GTK_WORLD_MAP (object), g_value_get_int (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void stop_draw_thread (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (priv->draw_thread) { g_thread_join (priv->draw_thread); priv->draw_thread = NULL; g_object_unref (priv->style); priv->style = NULL; if (priv->time_copy) { g_object_unref (priv->time_copy); priv->time_copy = NULL; } } } static void jana_gtk_world_map_dispose (GObject *object) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (object); stop_draw_thread (JANA_GTK_WORLD_MAP (object)); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (G_OBJECT_CLASS (jana_gtk_world_map_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_world_map_parent_class)-> dispose (object); } static void jana_gtk_world_map_finalize (GObject *object) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (object); if (priv->map) { gint i; for (i = 0; priv->map[i] && priv->map[i+1]; i++) if (priv->map[i]) g_free (priv->map[i]); g_free (priv->map); priv->map = NULL; } if (priv->buffer) { cairo_surface_destroy (priv->buffer); priv->buffer = NULL; } G_OBJECT_CLASS (jana_gtk_world_map_parent_class)->finalize (object); } static gboolean idle_redraw (GtkWidget *widget) { g_signal_emit (widget, signals[RENDER_STOP], 0); gtk_widget_queue_draw (widget); return FALSE; } static gpointer draw_map (JanaGtkWorldMap *self) { cairo_pattern_t *bg_pattern; double base_color[3], bg_color[3], fg_color[3], mid_color[3]; gint width, height; JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); cairo_t *cr = cairo_create (priv->buffer); width = cairo_image_surface_get_width (priv->buffer); height = cairo_image_surface_get_height (priv->buffer); /* Draw background */ base_color[0] = ((double)priv->style->bg[GTK_STATE_SELECTED].red)/ (double)G_MAXUINT16; base_color[1] = ((double)priv->style->bg[GTK_STATE_SELECTED].green)/ (double)G_MAXUINT16; base_color[2] = ((double)priv->style->bg[GTK_STATE_SELECTED].blue)/ (double)G_MAXUINT16; bg_color[0] = ((double)priv->style->base[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; bg_color[1] = ((double)priv->style->base[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; bg_color[2] = ((double)priv->style->base[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; fg_color[0] = ((double)priv->style->text[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; fg_color[1] = ((double)priv->style->text[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; fg_color[2] = ((double)priv->style->text[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; mid_color[0] = (base_color[0] + bg_color[0]) / 2; mid_color[1] = (base_color[1] + bg_color[1]) / 2; mid_color[2] = (base_color[2] + bg_color[2]) / 2; bg_pattern = cairo_pattern_create_linear (0, 0, 0, height); cairo_pattern_add_color_stop_rgb (bg_pattern, 0, base_color[0] * 1.1, base_color[1] * 1.1, base_color[2] * 1.1); cairo_pattern_add_color_stop_rgb (bg_pattern, 0.5, mid_color[0] * 1.05, mid_color[1] * 1.05, mid_color[2] * 1.05); cairo_pattern_add_color_stop_rgb (bg_pattern, 0.5, mid_color[0], mid_color[1], mid_color[2]); cairo_pattern_add_color_stop_rgb (bg_pattern, 1, base_color[0], base_color[1], base_color[2]); cairo_set_source (cr, bg_pattern); cairo_paint (cr); cairo_pattern_destroy (bg_pattern); if (priv->map && priv->map[0]) { /*cairo_pattern_t *pattern;*/ double scale_x, scale_y; gint i, j; cairo_translate (cr, width/2, height/2); cairo_rotate (cr, -M_PI/2); scale_x = (double)height / (double)(priv->phi_max - priv->phi_min); scale_y = (double)width / (double)(priv->theta_max - priv->theta_min); cairo_scale (cr, scale_x, scale_y); /*pattern = cairo_pattern_create_radial (priv->phi_max, 0, 0, priv->phi_max, 0, priv->phi_max - priv->phi_min); cairo_pattern_add_color_stop_rgb (pattern, 0, bg_color[0] * 1.2, bg_color[1] * 1.2, bg_color[2] * 1.2); cairo_pattern_add_color_stop_rgb (pattern, 1, bg_color[0] * 0.9, bg_color[1] * 0.9, bg_color[2] * 0.9);*/ /* Loop through polygon co-ordinates and draw */ for (i = 0; i < 2; i++) { cairo_save (cr); if (i == 0) { /* First run, draw shadow */ cairo_translate (cr, -(priv->phi_max-priv->phi_min)/180, (priv->theta_max-priv->theta_min)/360); cairo_set_source_rgb (cr, fg_color[0], fg_color[1], fg_color[2]); } else { /*cairo_set_source (cr, pattern);*/ cairo_set_source_rgb (cr, bg_color[0], bg_color[1], bg_color[2]); } for (j = 0; priv->map[j]; j++) { gint k, skip; cairo_rectangle_t bounds = { priv->phi_max, priv->theta_max, priv->phi_min, priv->theta_min }; /* Count the amount of points in this poly and * get bounding rectangle */ for (k = j; priv->map[k]; k++) { if (priv->map[k][0] < bounds.x) bounds.x = priv->map[k][0]; if (priv->map[k][1] < bounds.y) bounds.y = priv->map[k][1]; if (priv->map[k][0] > bounds.width) bounds.width = priv->map[k][0]; if (priv->map[k][1] > bounds.height) bounds.height = priv->map[k][1]; } bounds.width -= bounds.x; bounds.height -= bounds.y; /* If the polygon is tiny, skip it entirely */ if ((bounds.width < 1) || (bounds.height < 1)) { j = k; continue; } /* Decide how many points we can skip depending * on the length of perimiter of the * bounding rectangle, multiplied by 1.5. * We at least always draw a triangle. */ skip = MAX (1, MIN ((k-j)/3, (k-j) / (((bounds.width*1.5)+ (bounds.height*1.5)) * MAX (scale_x, scale_y)))); cairo_new_path (cr); cairo_move_to (cr, priv->map[j][0], priv->map[j][1]); for (j = j + 1; j < k; j += skip) { cairo_line_to (cr, priv->map[j][0], priv->map[j][1]); } j = k; cairo_close_path (cr); cairo_fill (cr); if (priv->dirty) break; } cairo_restore (cr); if (priv->dirty) break; } /*cairo_pattern_destroy (pattern);*/ if (priv->time_copy && (!priv->dirty)) { /* Draw daylight hours */ gdouble lat, time_offset, lon, prev_hours = 0; gboolean first = TRUE; cairo_path_t *path_copy, *path; guint day; const cairo_matrix_t flip_matrix = { 1, 0, 0, -1, 0, 0 }; /* Create curve - See: * http://mathforum.org/library/drmath/view/56478.html * for an explanation of the formula used. */ day = jana_utils_time_day_of_year (priv->time_copy); cairo_set_line_width (cr, 1.0); cairo_new_path (cr); cairo_line_to (cr, priv->phi_min, 0); for (lat = priv->phi_min; lat < priv->phi_max; lat+=1) { gdouble degrees; gdouble hours = jana_utils_time_daylight_hours ( lat, day); if (isnan (hours)) { gdouble flat = lat - 1; while (first) { /* Read ahead and find * the next daylight */ prev_hours = jana_utils_time_daylight_hours ( flat, day); flat += 1; if (!isnan (prev_hours)) first = FALSE; } hours = (prev_hours > 12) ? 24.0 : 0.0; } degrees = (hours/24.0) * 360; cairo_line_to (cr, lat, -degrees/2); prev_hours = hours; first = FALSE; } cairo_line_to (cr, priv->phi_max, 0); cairo_line_to (cr, priv->phi_max, priv->theta_min); cairo_line_to (cr, priv->phi_min, priv->theta_min); path_copy = cairo_copy_path (cr); /* Flip along the vertical axis and draw path again, * then make a copy of the new, full curve so that we * can draw it repeated. */ cairo_transform (cr, &flip_matrix); cairo_append_path (cr, path_copy); path = cairo_copy_path (cr); cairo_path_destroy (path_copy); /* Calculate midday offset */ time_offset = (((((gdouble)jana_time_get_hours ( priv->time_copy) * 60 * 60) + ((gdouble)jana_time_get_minutes ( priv->time_copy) * 60) + (gdouble)jana_time_get_seconds ( priv->time_copy)) / (24.0 * 60.0 * 60.0)) * 360.0) - 180.0; /* Draw repeated curve */ lon = (time_offset > 0) ? time_offset - 360 : time_offset; cairo_translate (cr, 0, lon); cairo_new_path (cr); for (; lon < (priv->theta_max - priv->theta_min); lon += 360) { cairo_append_path (cr, path); cairo_translate (cr, 0, 360); } cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_fill (cr); cairo_path_destroy (path); } } cairo_destroy (cr); if (!priv->dirty) { g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)idle_redraw, self, NULL); } return NULL; } static void draw_marks (JanaGtkWorldMap *self, cairo_t *cr) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); GtkWidget *widget = GTK_WIDGET (self); int i; for (i = 0; i < priv->marks->len; i++) { JanaGtkWorldMapMarker *marker = priv->marks->pdata[i]; gint x, y; jana_gtk_world_map_get_xy (self, marker->lat, marker->lon, &x, &y); cairo_save (cr); jana_gtk_world_map_marker_render (marker, widget->style, cr, GTK_WIDGET_STATE (widget), x, y); cairo_restore (cr); } } static gboolean jana_gtk_world_map_expose_event (GtkWidget *widget, GdkEventExpose *event) { cairo_t *cr = gdk_cairo_create (widget->window); JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); cairo_translate (cr, widget->allocation.x, widget->allocation.y); if (priv->buffer) { cairo_pattern_t *pattern = cairo_pattern_create_for_surface ( priv->buffer); if (priv->scale) { cairo_matrix_t matrix; cairo_matrix_init_scale (&matrix, (priv->width > 0) ? ((double)priv->width/ (double)widget->allocation.width) : 1.0, (priv->height > 0) ? ((double)priv->height/ (double)widget->allocation.height) : 1.0); cairo_pattern_set_matrix (pattern, &matrix); } cairo_set_source (cr, pattern); cairo_paint (cr); cairo_pattern_destroy (pattern); } draw_marks ((JanaGtkWorldMap *)widget, cr); cairo_destroy (cr); return GTK_WIDGET_CLASS (jana_gtk_world_map_parent_class)-> expose_event (widget, event); } static void refresh_buffer (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); priv->dirty = TRUE; if (!GTK_WIDGET_MAPPED (self)) return; stop_draw_thread (self); priv->dirty = FALSE; if (!priv->buffer) return; priv->style = gtk_style_copy (GTK_WIDGET (self)->style); priv->time_copy = priv->time ? jana_time_duplicate (priv->time) : NULL; g_signal_emit (self, signals[RENDER_START], 0); priv->draw_thread = g_thread_create ((GThreadFunc)draw_map, self, TRUE, NULL); } static void jana_gtk_world_map_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { gint width, height; JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); GTK_WIDGET_CLASS (jana_gtk_world_map_parent_class)-> size_allocate (widget, allocation); if (!GTK_WIDGET_REALIZED (widget)) gtk_widget_realize (widget); if (priv->scale) { width = (priv->width > 0) ? priv->width : allocation->width; height = (priv->height > 0) ? priv->height : allocation->height; } else { width = allocation->width; height = allocation->height; } if ((!priv->buffer) || (width != cairo_image_surface_get_width (priv->buffer)) || (height != cairo_image_surface_get_height (priv->buffer))) { stop_draw_thread (JANA_GTK_WORLD_MAP (widget)); if (priv->buffer) cairo_surface_destroy (priv->buffer); priv->buffer = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); refresh_buffer (JANA_GTK_WORLD_MAP (widget)); } } static gboolean jana_gtk_world_map_map_event (GtkWidget *widget, GdkEventAny *event) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); if (priv->dirty) refresh_buffer (JANA_GTK_WORLD_MAP (widget)); return FALSE; } static void jana_gtk_world_map_style_set (GtkWidget *widget, GtkStyle *previous_style) { GTK_WIDGET_CLASS (jana_gtk_world_map_parent_class)-> style_set (widget, previous_style); refresh_buffer (JANA_GTK_WORLD_MAP (widget)); } static gboolean jana_gtk_world_map_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); priv->in = TRUE; return FALSE; } static gboolean jana_gtk_world_map_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); priv->in = FALSE; return FALSE; } static gboolean jana_gtk_world_map_button_press_event (GtkWidget *widget, GdkEventButton *event) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); priv->clicked = TRUE; return FALSE; } static gboolean jana_gtk_world_map_button_release_event (GtkWidget *widget, GdkEventButton *event) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (widget); if (priv->clicked && priv->in) g_signal_emit (widget, signals[CLICKED], 0, event); priv->clicked = FALSE; return FALSE; } static void jana_gtk_world_map_class_init (JanaGtkWorldMapClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkWorldMapPrivate)); object_class->get_property = jana_gtk_world_map_get_property; object_class->set_property = jana_gtk_world_map_set_property; object_class->dispose = jana_gtk_world_map_dispose; object_class->finalize = jana_gtk_world_map_finalize; widget_class->expose_event = jana_gtk_world_map_expose_event; widget_class->size_allocate = jana_gtk_world_map_size_allocate; widget_class->map_event = jana_gtk_world_map_map_event; widget_class->style_set = jana_gtk_world_map_style_set; widget_class->enter_notify_event = jana_gtk_world_map_enter_notify_event; widget_class->leave_notify_event = jana_gtk_world_map_leave_notify_event; widget_class->button_press_event = jana_gtk_world_map_button_press_event; widget_class->button_release_event = jana_gtk_world_map_button_release_event; g_object_class_install_property ( object_class, PROP_TIME, g_param_spec_object ( "time", "Time", "The JanaTime the world map will show.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_WIDTH, g_param_spec_int ( "width", "Width", "The width to use when using a static size.", 0, G_MAXINT, 0, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HEIGHT, g_param_spec_int ( "height", "Height", "The height to use when using a static size.", 0, G_MAXINT, 0, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_STATIC, g_param_spec_boolean ( "static", "Static", "Whether to render a static size once and scale to the " "widget's allocated size.", FALSE, G_PARAM_READWRITE)); signals[RENDER_START] = g_signal_new ("render_start", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkWorldMapClass, render_start), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[RENDER_STOP] = g_signal_new ("render_stop", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkWorldMapClass, render_stop), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CLICKED] = g_signal_new ("clicked", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkWorldMapClass, clicked), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void jana_gtk_world_map_init (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (!g_thread_supported ()) g_thread_init (NULL); gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); gtk_event_box_set_visible_window (GTK_EVENT_BOX (self), FALSE); read_vmf (self); priv->marks = g_ptr_array_new (); } GtkWidget * jana_gtk_world_map_new (void) { return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_WORLD_MAP, NULL)); } void jana_gtk_world_map_set_time (JanaGtkWorldMap *self, JanaTime *time) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (time) { priv->time = jana_time_duplicate (time); /* Set time to UTC */ jana_time_set_offset (priv->time, 0); } refresh_buffer (self); } void jana_gtk_world_map_get_latlon (JanaGtkWorldMap *self, gint x, gint y, gdouble *lat, gdouble *lon) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (lon) { *lon = (((gdouble)x / (gdouble)GTK_WIDGET (self)-> allocation.width) * (priv->theta_max - priv->theta_min)) + priv->theta_min; } if (lat) { *lat = -((((gdouble)y / (gdouble)GTK_WIDGET (self)-> allocation.height) * (priv->phi_max - priv->phi_min)) + priv->phi_min); } } void jana_gtk_world_map_get_xy (JanaGtkWorldMap *self, gdouble lat, gdouble lon, gint *x, gint *y) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (x) { *x = ((lon / (priv->theta_max - priv->theta_min)) * (gdouble)GTK_WIDGET (self)->allocation.width) + GTK_WIDGET (self)->allocation.width/2; } if (y) { *y = (((-lat) / (priv->phi_max - priv->phi_min)) * (gdouble)GTK_WIDGET (self)->allocation.height) + GTK_WIDGET (self)->allocation.height/2; } } JanaGtkWorldMapMarker * jana_gtk_world_map_add_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *marker, gdouble lat, gdouble lon) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); marker->lat = lat; marker->lon = lon; g_object_ref_sink (G_OBJECT (marker)); g_ptr_array_add (priv->marks, marker); gtk_widget_queue_draw (GTK_WIDGET (self)); return marker; } void jana_gtk_world_map_remove_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *marker) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); g_ptr_array_remove (priv->marks, marker); g_object_unref (marker); gtk_widget_queue_draw (GTK_WIDGET (self)); } void jana_gtk_world_map_move_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *marker, gdouble lat, gdouble lon) { marker->lat = lat; marker->lon = lon; gtk_widget_queue_draw (GTK_WIDGET (self)); } GList * jana_gtk_world_map_get_markers (JanaGtkWorldMap *self) { gint i; GList *markers; JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); for (i = 0, markers = NULL; i < priv->marks->len; i++) { markers = g_list_prepend (markers, priv->marks->pdata[i]); } return markers; } void jana_gtk_world_map_set_static (JanaGtkWorldMap *self, gboolean set_static) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (priv->scale != set_static) { priv->scale = set_static; refresh_buffer (self); } } gboolean jana_gtk_world_map_get_static (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); return priv->scale; } void jana_gtk_world_map_set_width (JanaGtkWorldMap *self, gint width) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (priv->width != width) { priv->width = width; if (priv->scale) refresh_buffer (self); } } gint jana_gtk_world_map_get_width (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); return priv->width; } void jana_gtk_world_map_set_height (JanaGtkWorldMap *self, gint height) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); if (priv->height != height) { priv->height = height; if (priv->scale) refresh_buffer (self); } } gint jana_gtk_world_map_get_height (JanaGtkWorldMap *self) { JanaGtkWorldMapPrivate *priv = WORLD_MAP_PRIVATE (self); return priv->height; } #ifdef HAVE_GLADE /* The following is a nasty hack to get the widget to display correctly in * Glade-3. Taken from JanaGtkClock. */ static void placeholder_realize_cb (GtkWidget *widget) { GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW); if (widget->window) g_object_unref (widget->window); widget->window = g_object_ref (gtk_widget_get_parent (widget)->window); gtk_widget_queue_draw (gtk_widget_get_parent (widget)); } static void jana_gtk_world_map_glade_add_cb (GtkContainer *container, GtkWidget *widget, gpointer user_data) { if (!GLADE_IS_PLACEHOLDER (widget)) return; g_signal_connect_after (widget, "realize", G_CALLBACK (placeholder_realize_cb), NULL); if (GTK_WIDGET_REALIZED (widget)) placeholder_realize_cb (widget); } static void jana_gtk_world_map_glade_remove_cb (GtkContainer *container, GtkWidget *widget, gpointer user_data) { if (!GLADE_IS_PLACEHOLDER (widget)) return; g_signal_handlers_disconnect_by_func ( widget, placeholder_realize_cb, NULL); } void jana_gtk_world_map_glade_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GList *children; g_return_if_fail (GTK_IS_CONTAINER (object)); g_signal_connect (object, "add", G_CALLBACK (jana_gtk_world_map_glade_add_cb), NULL); g_signal_connect (object, "remove", G_CALLBACK (jana_gtk_world_map_glade_remove_cb), NULL); if (reason == GLADE_CREATE_USER) { GtkContainer *container = GTK_CONTAINER (object); children = gtk_container_get_children (container); if (!children) gtk_container_add (container, glade_placeholder_new ()); else g_list_free (children); } } #endif jana/libjana-gtk/jana-gtk-cell-renderer-note.h0000644000175000017500000000404511327631152021417 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_CELL_RENDERER_NOTE_H #define _JANA_GTK_CELL_RENDERER_NOTE_H #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_CELL_RENDERER_NOTE \ jana_gtk_cell_renderer_note_get_type() #define JANA_GTK_CELL_RENDERER_NOTE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_NOTE, JanaGtkCellRendererNote)) #define JANA_GTK_CELL_RENDERER_NOTE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_CELL_RENDERER_NOTE, JanaGtkCellRendererNoteClass)) #define JANA_GTK_IS_CELL_RENDERER_NOTE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_NOTE)) #define JANA_GTK_IS_CELL_RENDERER_NOTE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_CELL_RENDERER_NOTE)) #define JANA_GTK_CELL_RENDERER_NOTE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_CELL_RENDERER_NOTE, JanaGtkCellRendererNoteClass)) typedef struct { GtkCellRenderer parent; } JanaGtkCellRendererNote; typedef struct { GtkCellRendererClass parent_class; } JanaGtkCellRendererNoteClass; GType jana_gtk_cell_renderer_note_get_type (void); GtkCellRenderer* jana_gtk_cell_renderer_note_new (void); G_END_DECLS #endif /* _JANA_GTK_CELL_RENDERER_NOTE_H */ jana/libjana-gtk/jana-gtk-cell-renderer-note.c0000644000175000017500000007373711327631152021430 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "jana-gtk-note-store.h" #include "jana-gtk-cell-renderer-note.h" G_DEFINE_TYPE (JanaGtkCellRendererNote, jana_gtk_cell_renderer_note, \ GTK_TYPE_CELL_RENDERER) #define CELL_RENDERER_NOTE_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_CELL_RENDERER_NOTE, \ JanaGtkCellRendererNotePrivate)) typedef struct _JanaGtkCellRendererNotePrivate JanaGtkCellRendererNotePrivate; struct _JanaGtkCellRendererNotePrivate { gchar *style_hint; gchar *uid; gchar **categories; gchar *author; gchar *recipient; gchar *body; JanaTime *created; JanaTime *modified; GdkPixbuf *icon; GtkJustification justify; gboolean draw_box; gboolean show_author; gboolean show_recipient; gboolean show_body; gboolean show_created; gboolean show_modified; guint xpadi; guint ypadi; gint cell_width; GHashTable *category_color_hash; GHashTable *category_icon_hash; }; enum { PROP_STYLE_HINT = 1, PROP_UID, PROP_CATEGORIES, PROP_AUTHOR, PROP_RECIPIENT, PROP_BODY, PROP_CREATED, PROP_MODIFIED, PROP_ICON, PROP_JUSTIFY, PROP_DRAW_BOX, PROP_SHOW_AUTHOR, PROP_SHOW_RECIPIENT, PROP_SHOW_BODY, PROP_SHOW_CREATED, PROP_SHOW_MODIFIED, PROP_XPAD_INNER, PROP_YPAD_INNER, PROP_CELL_WIDTH, PROP_CATEGORY_COLOR_HASH, PROP_CATEGORY_ICON_HASH, }; static void cell_renderer_note_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags); static void cell_renderer_note_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void jana_gtk_cell_renderer_note_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (object); switch (property_id) { case PROP_STYLE_HINT : g_value_set_string (value, priv->style_hint); break; case PROP_UID : g_value_set_string (value, priv->uid); break; case PROP_CATEGORIES : g_value_set_boxed (value, priv->categories); break; case PROP_AUTHOR : g_value_set_string (value, priv->author); break; case PROP_RECIPIENT : g_value_set_string (value, priv->recipient); break; case PROP_BODY : g_value_set_string (value, priv->body); break; case PROP_CREATED : g_value_set_object (value, priv->created); break; case PROP_MODIFIED : g_value_set_object (value, priv->modified); break; case PROP_DRAW_BOX : g_value_set_boolean (value, priv->draw_box); break; case PROP_SHOW_AUTHOR : g_value_set_boolean (value, priv->show_author); break; case PROP_SHOW_RECIPIENT : g_value_set_boolean (value, priv->show_recipient); break; case PROP_SHOW_BODY : g_value_set_boolean (value, priv->show_body); break; case PROP_SHOW_CREATED : g_value_set_boolean (value, priv->show_created); break; case PROP_SHOW_MODIFIED : g_value_set_boolean (value, priv->show_modified); break; case PROP_ICON : g_value_set_object (value, priv->icon); break; case PROP_JUSTIFY : g_value_set_enum (value, priv->justify); break; case PROP_XPAD_INNER : g_value_set_uint (value, priv->xpadi); break; case PROP_YPAD_INNER : g_value_set_uint (value, priv->ypadi); break; case PROP_CELL_WIDTH : g_value_set_int (value, priv->cell_width); break; case PROP_CATEGORY_COLOR_HASH : g_value_set_boxed (value, priv->category_color_hash); break; case PROP_CATEGORY_ICON_HASH : g_value_set_boxed (value, priv->category_icon_hash); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_cell_renderer_note_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (object); switch (property_id) { case PROP_STYLE_HINT : g_free (priv->style_hint); priv->style_hint = g_value_dup_string (value); break; case PROP_UID : g_free (priv->uid); priv->uid = g_value_dup_string (value); break; case PROP_CATEGORIES : g_strfreev (priv->categories); priv->categories = g_value_dup_boxed (value); break; case PROP_AUTHOR : g_free (priv->author); priv->author = g_value_dup_string (value); break; case PROP_RECIPIENT : g_free (priv->recipient); priv->recipient = g_value_dup_string (value); break; case PROP_BODY : g_free (priv->body); priv->body = g_value_dup_string (value); break; case PROP_CREATED : if (priv->created) g_object_unref (priv->created); priv->created = JANA_TIME (g_value_dup_object (value)); break; case PROP_MODIFIED : if (priv->modified) g_object_unref (priv->modified); priv->modified = JANA_TIME (g_value_dup_object (value)); break; case PROP_DRAW_BOX : priv->draw_box = g_value_get_boolean (value); break; case PROP_SHOW_AUTHOR : priv->show_author = g_value_get_boolean (value); break; case PROP_SHOW_RECIPIENT : priv->show_recipient = g_value_get_boolean (value); break; case PROP_SHOW_BODY : priv->show_body = g_value_get_boolean (value); break; case PROP_SHOW_CREATED : priv->show_created = g_value_get_boolean (value); break; case PROP_SHOW_MODIFIED : priv->show_modified = g_value_get_boolean (value); break; case PROP_ICON : if (priv->icon) g_object_unref (priv->icon); priv->icon = g_value_dup_object (value); break; case PROP_JUSTIFY : priv->justify = g_value_get_enum (value); break; case PROP_XPAD_INNER : priv->xpadi = g_value_get_uint (value); break; case PROP_YPAD_INNER : priv->ypadi = g_value_get_uint (value); break; case PROP_CELL_WIDTH : priv->cell_width = g_value_get_int (value); break; case PROP_CATEGORY_COLOR_HASH : if (priv->category_color_hash) g_hash_table_unref (priv->category_color_hash); priv->category_color_hash = g_value_dup_boxed (value); break; case PROP_CATEGORY_ICON_HASH : if (priv->category_icon_hash) g_hash_table_unref (priv->category_icon_hash); priv->category_icon_hash = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_cell_renderer_note_dispose (GObject *object) { JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (object); if (priv->created) { g_object_unref (priv->created); priv->created = NULL; } if (priv->modified) { g_object_unref (priv->modified); priv->modified = NULL; } if (G_OBJECT_CLASS (jana_gtk_cell_renderer_note_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_cell_renderer_note_parent_class)-> dispose (object); } static void jana_gtk_cell_renderer_note_finalize (GObject *object) { JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (object); g_free (priv->style_hint); g_free (priv->uid); g_free (priv->author); g_free (priv->recipient); g_free (priv->body); if (priv->category_color_hash) g_hash_table_unref (priv->category_color_hash); if (priv->category_icon_hash) g_hash_table_unref (priv->category_icon_hash); G_OBJECT_CLASS (jana_gtk_cell_renderer_note_parent_class)-> finalize (object); } static void jana_gtk_cell_renderer_note_class_init (JanaGtkCellRendererNoteClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkCellRendererClass *renderer_class = GTK_CELL_RENDERER_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkCellRendererNotePrivate)); object_class->get_property = jana_gtk_cell_renderer_note_get_property; object_class->set_property = jana_gtk_cell_renderer_note_set_property; object_class->dispose = jana_gtk_cell_renderer_note_dispose; object_class->finalize = jana_gtk_cell_renderer_note_finalize; renderer_class->get_size = cell_renderer_note_get_size; renderer_class->render = cell_renderer_note_render; g_object_class_install_property ( object_class, PROP_STYLE_HINT, g_param_spec_string ( "style_hint", "gchar *", "The style hint to use when drawing.", "button", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_UID, g_param_spec_string ( "uid", "gchar *", "The UID of the represented note.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CATEGORIES, g_param_spec_boxed ( "categories", "gchar **", "A list of category strings.", G_TYPE_STRV, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_AUTHOR, g_param_spec_string ( "author", "gchar *", "The author of the represented note.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_RECIPIENT, g_param_spec_string ( "recipient", "gchar *", "The recipient of the represented note.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_BODY, g_param_spec_string ( "body", "gchar *", "The body of the represented note.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CREATED, g_param_spec_object ( "created", "JanaTime *", "The creation time of the represented note.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_MODIFIED, g_param_spec_object ( "modified", "JanaTime *", "The last modification time of the represented note.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_ICON, g_param_spec_object ( "icon", "GdkPixbuf *", "An icon to show alongside the note.", GDK_TYPE_PIXBUF, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_JUSTIFY, g_param_spec_enum ( "justify", "GtkJustification", "The justification to use when laying out the note.", GTK_TYPE_JUSTIFICATION, GTK_JUSTIFY_LEFT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_BOX, g_param_spec_boolean ( "draw_box", "gboolean", "Whether to draw a box surrounding the note.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_AUTHOR, g_param_spec_boolean ( "show_author", "gboolean", "Whether to show the author of the note.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_RECIPIENT, g_param_spec_boolean ( "show_recipient", "gboolean", "Whether to show the recipient of the note.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_BODY, g_param_spec_boolean ( "show_body", "gboolean", "Whether to show the body of the note.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_CREATED, g_param_spec_boolean ( "show_created", "gboolean", "Whether to show the creation time of the note.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_MODIFIED, g_param_spec_boolean ( "show_modified", "gboolean", "Whether to show the modification time of the note.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_XPAD_INNER, g_param_spec_uint ( "xpad_inner", "gint", "Inner padding on the x-axis, in pixels.", 0, G_MAXUINT, 3, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_YPAD_INNER, g_param_spec_uint ( "ypad_inner", "gint", "Inner padding on the y-axis, in pixels.", 0, G_MAXUINT, 3, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CELL_WIDTH, g_param_spec_int ( "cell_width", "gint", "Width the cell should try to size itself for.", -G_MAXINT, G_MAXINT, -1, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CATEGORY_COLOR_HASH, g_param_spec_boxed ( "category_color_hash", "GHashTable *", "A mapping of category strings to GdkColors.", G_TYPE_HASH_TABLE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CATEGORY_ICON_HASH, g_param_spec_boxed ( "category_icon_hash", "GHashTable *", "A mapping of category strings to GdkPixbufs.", G_TYPE_HASH_TABLE, G_PARAM_READWRITE)); } static void jana_gtk_cell_renderer_note_init (JanaGtkCellRendererNote *self) { JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (self); priv->style_hint = g_strdup ("button"); priv->show_author = TRUE; priv->show_created = TRUE; priv->show_body = TRUE; priv->justify = GTK_JUSTIFY_LEFT; priv->xpadi = 3; priv->ypadi = 3; priv->cell_width = -1; } static void layout_set_justification (PangoLayout *layout, GtkJustification justify) { switch (justify) { case GTK_JUSTIFY_RIGHT : pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case GTK_JUSTIFY_CENTER : pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; case GTK_JUSTIFY_FILL : pango_layout_set_justify (layout, TRUE); break; case GTK_JUSTIFY_LEFT : default : pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; } } static PangoLayout * get_header_layout (JanaGtkCellRendererNote *cell, GtkWidget *widget, GdkRectangle *area) { GString *string; PangoLayout *layout; JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (cell); if ((!priv->show_created) && (!priv->show_modified) && (!priv->show_author) && (!priv->show_recipient) && (!priv->show_body)) return NULL; string = g_string_new (""); if (priv->show_created && priv->created) { g_string_append_printf (string, "%d/%d/%02d", jana_time_get_day (priv->created), jana_time_get_month (priv->created), jana_time_get_year (priv->created)); if (priv->show_modified && priv->modified) { g_string_append (string, ", "); } else g_string_append (string, " "); } if (priv->show_modified && priv->modified) { g_string_append_printf (string, "%d/%d/%02d ", jana_time_get_day (priv->modified), jana_time_get_month (priv->modified), jana_time_get_year (priv->modified)); } g_string_append (string, ""); if (priv->show_author && priv->author) { g_string_append (string, priv->author); if (priv->show_recipient && priv->recipient) { g_string_append (string, ", to "); } } if (priv->show_recipient && priv->recipient) { g_string_append (string, priv->recipient); } layout = gtk_widget_create_pango_layout (widget, NULL); pango_layout_set_width (layout, area->width * PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); pango_layout_set_markup (layout, string->str, string->len); g_string_free (string, TRUE); layout_set_justification (layout, priv->justify); return layout; } /* FIXME: This code adapted from JanaGtkCellRendererEvent... Could do with * making this shared, it's not trivial */ static PangoLayout * get_body_layout (JanaGtkCellRendererNote *cell, GtkWidget *widget, GdkRectangle *area) { gint el_width, height; PangoLayout *layout; JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (cell); if ((!priv->body) || (!priv->show_body)) return NULL; /* Measure the width of the '...' string */ layout = gtk_widget_create_pango_layout (widget, "..."); pango_layout_get_pixel_size (layout, &el_width, NULL); g_object_unref (layout); /* Make the body layout */ layout = gtk_widget_create_pango_layout (widget, priv->body); pango_layout_set_width (layout, area->width * PANGO_SCALE); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); /* Manual ellipsis for multiple-line layouts */ /* TODO: Width for height, natural size */ pango_layout_get_pixel_size (layout, NULL, &height); if (height > area->height) { PangoLayoutIter *iter = pango_layout_get_iter (layout); gint line_n = 0; height = 0; if (pango_layout_get_line_count (layout) <= 1) { pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); } else do { PangoRectangle rect; PangoLayoutLine *line = pango_layout_iter_get_line_readonly (iter); gint descent; pango_layout_line_get_pixel_extents (line, NULL, &rect); height += rect.height; descent = PANGO_DESCENT (rect); if (descent < 0) descent = 0; if (height + descent > area->height) { gchar *string_short, *string_ellip, *end_string; gint width; if (line_n == 0) { pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); break; } /* Get previous line */ line = pango_layout_get_line (layout, line_n - 1); pango_layout_line_ref (line); /* Do ellipsis */ end_string = priv->body + line->start_index + line->length; pango_layout_line_get_pixel_extents (line, NULL, &rect); /* Find out if the line wrapped */ if (area->width - (rect.x + rect.width) <= el_width) { do { gint length; /* FIXME: Something faster..? */ /* Cut off characters from the * end of the string until we * have enough space to append * ellipsis. */ /* Cut off a character */ end_string = g_utf8_offset_to_pointer ( end_string, -1); length = (priv->body + line->start_index + line->length) - end_string; /* Safe-guard - if we reach * the start of the line, break */ if (length <= 1) break; /* Measure the string we've * cut off. */ pango_layout_set_text (layout, end_string, length); pango_layout_get_pixel_extents ( layout, NULL, &rect); width = rect.width; } while (width <= el_width); } pango_layout_line_unref (line); if (end_string <= priv->body) { pango_layout_iter_free (iter); g_object_unref (layout); return NULL; } string_short = g_strndup (priv->body, end_string - priv->body); string_ellip = g_strconcat ( string_short, "...", NULL); pango_layout_set_text ( layout, string_ellip, -1); g_free (string_short); g_free (string_ellip); break; } line_n ++; } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); } layout_set_justification (layout, priv->justify); return layout; } static void cell_renderer_note_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) { GtkStateType state; guint xpad, ypad; gint w, h, x, y; GtkStyle *style; PangoLayout *layout; GdkRectangle text_clip; JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (cell); if (flags & GTK_CELL_RENDERER_INSENSITIVE) state = GTK_STATE_INSENSITIVE; else if (flags & GTK_CELL_RENDERER_SELECTED) state = GTK_STATE_ACTIVE; else if (flags & GTK_CELL_RENDERER_PRELIT) state = GTK_STATE_PRELIGHT; else state = GTK_STATE_NORMAL; g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL); /* Check if there's enough allocated space to draw in */ w = cell_area->width - (xpad * 2); h = cell_area->height - (ypad * 2); x = cell_area->x + xpad; y = cell_area->y + ypad; if ((w <= 0) || (h <= 0)) return; if ((!priv->draw_box) || (!priv->category_color_hash) || (!priv->categories) || (!priv->categories[0])) { style = widget->style; } else { GdkColor *color; color = g_hash_table_lookup ( priv->category_color_hash, priv->categories[0]); style = gtk_style_copy (widget->style); if (color) { gint intensity, avg; style->bg[state] = *color; switch (state) { case GTK_STATE_INSENSITIVE : /* De-saturated */ avg = (((gint)color->red*3)+ ((gint)color->green*6)+ (gint)color->blue)/10; style->bg[state].red = (style->bg[state].red + avg)/2; style->bg[state].green = (style->bg[state].green + avg)/2; style->bg[state].blue = (style->bg[state].blue + avg)/2; break; case GTK_STATE_ACTIVE : /* Darkened */ style->bg[state].red = ((gint)style->bg[state].red*4)/5; style->bg[state].green = ((gint)style->bg[state].green*4)/5; style->bg[state].blue = ((gint)style->bg[state].blue*4)/5; break; case GTK_STATE_PRELIGHT : /* Brightened */ avg = G_MAXUINT16; style->bg[state].red = (style->bg[state].red + avg)/2; style->bg[state].green = (style->bg[state].green + avg)/2; style->bg[state].blue = (style->bg[state].blue + avg)/2; break; default : break; } /* Grey out text if it's insensitive */ if (state == GTK_STATE_INSENSITIVE) { style->fg[state].red = G_MAXUINT16/2; style->fg[state].green = G_MAXUINT16/2; style->fg[state].blue = G_MAXUINT16/2; } else { /* Choose text colour (black/white) based on * rough background colour intensity */ intensity = (((gint)style->bg[state].red)+ ((gint)style->bg[state].green)+ (gint)style->bg[state].blue)/3; if (intensity > G_MAXUINT16/2) { style->fg[state] = style->black; } else { style->fg[state] = style->white; } } } style = gtk_style_attach (style, widget->window); } /* Draw box */ if (priv->draw_box) { gtk_paint_box (style, window, state, (state == GTK_STATE_ACTIVE) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, expose_area, widget, priv->style_hint, x, y, w, h); } /* Calculate text size text */ text_clip.x = x + priv->xpadi; text_clip.y = y + priv->ypadi; text_clip.width = w - (priv->xpadi * 2); text_clip.height = h - (priv->ypadi * 2); /* Draw icon */ if (priv->icon) { /* FIXME: Read l10n settings for ltr to decide where to put * icon with GTK_JUSTIFY_FILL. */ switch (priv->justify) { case GTK_JUSTIFY_RIGHT : gdk_draw_pixbuf (window, style->black_gc, priv->icon, 0, 0, (text_clip.x + text_clip.width) - gdk_pixbuf_get_width (priv->icon), text_clip.y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); text_clip.width -= gdk_pixbuf_get_width (priv->icon) + priv->xpadi; break; case GTK_JUSTIFY_CENTER : gdk_draw_pixbuf (window, style->black_gc, priv->icon, 0, 0, text_clip.x + (text_clip.width/2) - (gdk_pixbuf_get_width (priv->icon)/2), text_clip.y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); text_clip.y += gdk_pixbuf_get_height (priv->icon) + priv->ypadi; text_clip.height -= gdk_pixbuf_get_height (priv->icon) + priv->ypadi; break; case GTK_JUSTIFY_FILL : case GTK_JUSTIFY_LEFT : default : gdk_draw_pixbuf (window, style->black_gc, priv->icon, 0, 0, text_clip.x, text_clip.y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); text_clip.x += gdk_pixbuf_get_width (priv->icon) + priv->xpadi; text_clip.width -= gdk_pixbuf_get_width (priv->icon) + priv->xpadi; break; } } /* Draw header */ if ((text_clip.height > 0) && (text_clip.width > 0) && (layout = get_header_layout ( JANA_GTK_CELL_RENDERER_NOTE (cell), widget, &text_clip))) { gtk_paint_layout (style, window, state, !priv->draw_box, &text_clip, widget, priv->style_hint, text_clip.x, text_clip.y, layout); pango_layout_get_pixel_size (layout, NULL, &h); text_clip.y += h; text_clip.height -= h; g_object_unref (layout); } /* Draw body */ if ((text_clip.height > 0) && (text_clip.width > 0) && (layout = get_body_layout (JANA_GTK_CELL_RENDERER_NOTE (cell), widget, &text_clip))) { gtk_paint_layout (style, window, state, !priv->draw_box, &text_clip, widget, priv->style_hint, text_clip.x, text_clip.y, layout); pango_layout_get_pixel_size (layout, NULL, &h); text_clip.y += h; text_clip.height -= h; g_object_unref (layout); } /* Draw emblems */ /* TODO: A lot of the logic here is untested... */ if (priv->category_icon_hash && priv->categories) { gint i, cumu_width, cumu_height, max_height; cumu_height = cumu_width = max_height = 0; for (i = 0; priv->categories[i]; i++) { GdkPixbuf *pixbuf; pixbuf = (GdkPixbuf *)g_hash_table_lookup ( priv->category_icon_hash, priv->categories[i]); if (!pixbuf) continue; w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); x = text_clip.x + cumu_width; y = text_clip.y + cumu_height; if (h > max_height) max_height = h; if (cumu_width && (w > text_clip.width)) { y += max_height + priv->ypadi; cumu_height += h + priv->ypadi; x = 0; } else { cumu_width += w; if (cumu_width >= text_clip.width) { cumu_height += max_height; cumu_width = 0; } else { cumu_width += priv->xpadi; } } gdk_draw_pixbuf (window, style->black_gc, pixbuf, 0, 0, x, y, MIN (text_clip.width - w, w), MIN (text_clip.height - h, h), GDK_RGB_DITHER_NORMAL, 0, 0); cumu_width += w; } } /* Detach style */ if (priv->draw_box && priv->category_color_hash && priv->categories && priv->categories[0]) { gtk_style_detach (style); } } static void cell_renderer_note_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { gint text_width, text_height, icon_width, icon_height; gboolean layout_visible; PangoLayout *layout; GdkRectangle area; guint xpad, ypad; JanaGtkCellRendererNotePrivate *priv = CELL_RENDERER_NOTE_PRIVATE (cell); if (cell_area) { /* TODO: Alignment? */ if (x_offset) *x_offset = 0; if (y_offset) *y_offset = 0; } /* Ask for at least enough room to draw the box with inner padding */ g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL); if (width) *width = ((priv->xpadi + xpad)*2); if (height) *height = ((priv->ypadi + ypad) * 2); /* Add room for icon */ if (priv->icon) { icon_width = gdk_pixbuf_get_width (priv->icon); icon_height = gdk_pixbuf_get_height (priv->icon); if (width) *width += icon_width; if (height) *height += icon_height; } else { icon_width = 0; icon_height = 0; } /* TODO: Width for height, natural size */ /* Calculate available room for text */ area.x = 0; area.y = 0; g_object_get (G_OBJECT (cell), "width", &area.width, NULL); if (area.width < 0) { if (cell_area) { area.width = cell_area->width - (priv->xpadi + xpad) * 2; } else if (priv->cell_width >= 0) { area.width = priv->cell_width - (priv->xpadi + xpad) * 2; } else { area.width = G_MAXINT; } } else { area.width -= (priv->xpadi + xpad) * 2; } area.height = (cell_area && (cell_area->height >= 0)) ? cell_area->height : G_MAXINT; if (priv->justify == GTK_JUSTIFY_CENTER) { if (area.height < G_MAXINT) area.height -= icon_height + priv->ypadi; } else { if (area.width < G_MAXINT) area.width -= icon_width + priv->xpadi; } /* Calculate text size */ /* Header */ layout_visible = FALSE; text_height = 0; text_width = 0; if ((layout = get_header_layout (JANA_GTK_CELL_RENDERER_NOTE (cell), widget, &area))) { pango_layout_get_pixel_size (layout, &text_width, &text_height); if (area.width == G_MAXINT) area.width = text_width; g_object_unref (layout); layout_visible = TRUE; } /* Body */ if ((layout = get_body_layout ( JANA_GTK_CELL_RENDERER_NOTE (cell), widget, &area))) { gint body_width, body_height; pango_layout_get_pixel_size (layout, &body_width, &body_height); text_width += body_width; text_height += body_height; g_object_unref (layout); layout_visible = TRUE; } /* Add space for text */ if (layout_visible) { if (priv->icon) { if (priv->justify == GTK_JUSTIFY_CENTER) { if (*width && (area.width < 0)) *width += MAX ( 0, text_width - icon_width); if (*height) *height += priv->ypadi + text_height; } else { if (*width && (area.width < 0)) *width += priv->xpadi + text_width; if (*height) *height += MAX ( 0, text_height - icon_height); } } else { if (width && (area.width < 0)) *width += text_width; if (height) *height += text_height; } } /* Add space for emblems */ if (height && priv->category_icon_hash && priv->categories) { gint i, max_height, cumu_width; max_height = cumu_width = 0; for (i = 0; priv->categories[i]; i++) { gint w, h; GdkPixbuf *pixbuf = (GdkPixbuf *) g_hash_table_lookup ( priv->category_icon_hash, priv->categories[i]); if (!pixbuf) continue; w = gdk_pixbuf_get_width (pixbuf) + priv->xpadi; h = gdk_pixbuf_get_height (pixbuf) + priv->ypadi; if (!width) { /* Add the height of the highest emblem */ if (h > max_height) { *height += h - max_height; max_height = h; } } else { /* Check the total height with wrapping */ if (w > *width) { /* Image is too big to fit in bounds, * if we have icons before it, clip it * on the next row, otherwise just * stick it in and wrap immediately * after. */ cumu_width = 0; *height += h; } else { cumu_width += w; if (cumu_width + priv->xpadi > *width) { *height += h; cumu_width = w; max_height = h; } else { cumu_width += w; if (h > max_height) { *height += h - max_height; max_height = h; } } } } } } } GtkCellRenderer* jana_gtk_cell_renderer_note_new (void) { return g_object_new (JANA_GTK_TYPE_CELL_RENDERER_NOTE, NULL); } jana/libjana-gtk/jana-gtk-world-map-marker.h0000644000175000017500000000447611327631152021122 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_WORLD_MAP_MARKER_H #define _JANA_GTK_WORLD_MAP_MARKER_H #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_WORLD_MAP_MARKER jana_gtk_world_map_marker_get_type() #define JANA_GTK_WORLD_MAP_MARKER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER, JanaGtkWorldMapMarker)) #define JANA_GTK_WORLD_MAP_MARKER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_WORLD_MAP_MARKER, JanaGtkWorldMapMarkerClass)) #define JANA_GTK_IS_WORLD_MAP_MARKER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER)) #define JANA_GTK_IS_WORLD_MAP_MARKER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_WORLD_MAP_MARKER)) #define JANA_GTK_WORLD_MAP_MARKER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER, JanaGtkWorldMapMarkerClass)) typedef struct { GObject parent; gdouble lat; gdouble lon; } JanaGtkWorldMapMarker; typedef struct { GObjectClass parent_class; void (* render) (JanaGtkWorldMapMarker *marker, GtkStyle *style, cairo_t *cr, GtkStateType state, gint x, gint y); } JanaGtkWorldMapMarkerClass; GType jana_gtk_world_map_marker_get_type (void); JanaGtkWorldMapMarker * jana_gtk_world_map_marker_new (); void jana_gtk_world_map_marker_render (JanaGtkWorldMapMarker *marker, GtkStyle *style, cairo_t *cr, GtkStateType state, gint x, gint y); G_END_DECLS #endif jana/libjana-gtk/jana-gtk-world-map-marker.c0000644000175000017500000000365111327631152021107 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include "jana-gtk-world-map-marker.h" #include G_DEFINE_TYPE (JanaGtkWorldMapMarker, jana_gtk_world_map_marker, \ G_TYPE_INITIALLY_UNOWNED) static void render (JanaGtkWorldMapMarker *marker, GtkStyle *style, cairo_t *cr, GtkStateType state, gint x, gint y) { cairo_arc (cr, x, y, 5, 0, 2 * M_PI); gdk_cairo_set_source_color (cr, &style->mid[state]); cairo_fill_preserve (cr); gdk_cairo_set_source_color (cr, &style->fg[state]); cairo_stroke (cr); } static void jana_gtk_world_map_marker_class_init (JanaGtkWorldMapMarkerClass *klass) { klass->render = render; } static void jana_gtk_world_map_marker_init (JanaGtkWorldMapMarker *marker) { } void jana_gtk_world_map_marker_render (JanaGtkWorldMapMarker *marker, GtkStyle *style, cairo_t *cr, GtkStateType state, gint x, gint y) { JanaGtkWorldMapMarkerClass *klass = JANA_GTK_WORLD_MAP_MARKER_GET_CLASS (marker); klass->render (marker, style, cr, state, x, y); } JanaGtkWorldMapMarker * jana_gtk_world_map_marker_new () { JanaGtkWorldMapMarker *marker; marker = g_object_new (JANA_GTK_TYPE_WORLD_MAP_MARKER, NULL); return marker; } jana/libjana-gtk/jana-gtk-event-list.h0000644000175000017500000000515111327631152020022 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_EVENT_LIST_H #define _JANA_GTK_EVENT_LIST_H #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_EVENT_LIST jana_gtk_event_list_get_type() #define JANA_GTK_EVENT_LIST(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_EVENT_LIST, JanaGtkEventList)) #define JANA_GTK_EVENT_LIST_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_EVENT_LIST, JanaGtkEventListClass)) #define JANA_GTK_IS_EVENT_LIST(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_EVENT_LIST)) #define JANA_GTK_IS_EVENT_LIST_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_EVENT_LIST)) #define JANA_GTK_EVENT_LIST_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_EVENT_LIST, JanaGtkEventListClass)) typedef struct { GtkTreeView parent; } JanaGtkEventList; typedef struct { GtkTreeViewClass parent_class; } JanaGtkEventListClass; enum { JANA_GTK_EVENT_LIST_COL_ROW, JANA_GTK_EVENT_LIST_COL_TIME, JANA_GTK_EVENT_LIST_COL_HEADER, JANA_GTK_EVENT_LIST_COL_IS_EVENT, JANA_GTK_EVENT_LIST_COL_IS_HEADER, JANA_GTK_EVENT_LIST_COL_LAST }; GType jana_gtk_event_list_get_type (void); GtkWidget* jana_gtk_event_list_new (void); void jana_gtk_event_list_add_store (JanaGtkEventList *self, JanaGtkEventStore *store); void jana_gtk_event_list_remove_store (JanaGtkEventList *self, JanaGtkEventStore *store); GtkTreeModelFilter * jana_gtk_event_list_get_filter (JanaGtkEventList *self); void jana_gtk_event_list_refilter (JanaGtkEventList *self); void jana_gtk_event_list_set_show_headers (JanaGtkEventList *self, gboolean show_headers); gboolean jana_gtk_event_list_get_show_headers (JanaGtkEventList *self); G_END_DECLS #endif /* _JANA_GTK_EVENT_LIST_H */ jana/libjana-gtk/jana-gtk.h0000644000175000017500000000326411327631152015735 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-gtk * @short_description: A set of GTK widgets to visualise libjana data */ #ifndef JANA_GTK_H #define JANA_GTK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif jana/libjana-gtk/jana-gtk-event-list.c0000644000175000017500000004312311327631152020016 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include "jana-gtk-event-list.h" #include "jana-gtk-cell-renderer-event.h" G_DEFINE_TYPE (JanaGtkEventList, jana_gtk_event_list, GTK_TYPE_TREE_VIEW) #define EVENT_LIST_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_EVENT_LIST, \ JanaGtkEventListPrivate)) typedef struct _JanaGtkEventListPrivate JanaGtkEventListPrivate; struct _JanaGtkEventListPrivate { GtkListStore *model; GList *stores; GtkTreeViewColumn *column; GtkCellRenderer *event_renderer; GtkCellRenderer *text_renderer; gboolean show_headers; }; enum { PROP_COLUMN = 1, PROP_EVENT_RENDERER, PROP_TEXT_RENDERER, PROP_SHOW_HEADERS, }; static gint jana_gtk_event_list_compare (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { GtkTreeRowReference *a_row, *b_row; GtkTreePath *path; GtkTreeModel *sub_model; GtkTreeIter iter; JanaTime *start1, *end1, *start2, *end2; gchar *summary1, *summary2; gint result = 0; gtk_tree_model_get (model, a, JANA_GTK_EVENT_LIST_COL_TIME, &start1, JANA_GTK_EVENT_LIST_COL_ROW, &a_row, -1); gtk_tree_model_get (model, b, JANA_GTK_EVENT_LIST_COL_TIME, &start2, JANA_GTK_EVENT_LIST_COL_ROW, &b_row, -1); if (a_row) { sub_model = gtk_tree_row_reference_get_model (a_row); path = gtk_tree_row_reference_get_path (a_row); gtk_tree_model_get_iter (sub_model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (sub_model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start1, JANA_GTK_EVENT_STORE_COL_END, &end1, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary1, -1); } if (b_row) { sub_model = gtk_tree_row_reference_get_model (b_row); path = gtk_tree_row_reference_get_path (b_row); gtk_tree_model_get_iter (sub_model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (sub_model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start2, JANA_GTK_EVENT_STORE_COL_END, &end2, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary2, -1); } result = jana_utils_time_compare (start1, start2, FALSE); if (result == 0) { if (a_row && b_row) { if (result == 0) result = jana_utils_time_compare ( end2, end1, FALSE); if ((result == 0) && summary1 && summary2) result = strcmp (summary1, summary2); } else { /* Make sure headers sort before events */ if (!a_row) result = -1; else if (!b_row) result = 1; } } g_object_unref (start1); if (a_row) { g_free (summary1); g_object_unref (end1); } g_object_unref (start2); if (b_row) { g_free (summary2); g_object_unref (end2); } return result; } static void recalculate_headers (JanaGtkEventList *self) { GtkTreeIter iter; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); gboolean skip; JanaTime *day = NULL; GtkTreeModelFilter *filter; /* Remove all header rows, then iterate through and add unique days * to table. */ if (!gtk_tree_model_get_iter_first ((GtkTreeModel *)priv->model, &iter)) return; do { GtkTreeRowReference *row; gtk_tree_model_get ((GtkTreeModel *)priv->model, &iter, JANA_GTK_EVENT_LIST_COL_ROW, &row, -1); skip = FALSE; if (!row) { if (gtk_list_store_remove (priv->model, &iter)) skip = TRUE; else break; } } while (skip || gtk_tree_model_iter_next ( (GtkTreeModel *)priv->model, &iter)); if (!priv->show_headers) return; filter = (GtkTreeModelFilter *)gtk_tree_view_get_model ( GTK_TREE_VIEW (self)); if (!gtk_tree_model_get_iter_first ((GtkTreeModel *)filter, &iter)) return; do { GtkTreeModel *model; GtkTreeRowReference *row; GtkTreePath *path; GtkTreeIter inner_iter; JanaTime *start; gtk_tree_model_get ((GtkTreeModel *)filter, &iter, JANA_GTK_EVENT_LIST_COL_ROW, &row, -1); if (!gtk_tree_row_reference_valid (row)) continue; model = gtk_tree_row_reference_get_model (row); path = gtk_tree_row_reference_get_path (row); gtk_tree_model_get_iter (model, &inner_iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &inner_iter, JANA_GTK_EVENT_STORE_COL_START, &start, -1); if ((!day)||(jana_utils_time_compare (start, day, TRUE) > 0)) { JanaTime *day_copy; gchar *header; GtkTreeIter child_iter; if (day) g_object_unref (day); day = jana_time_duplicate (start); jana_time_set_isdate (day, TRUE); header = jana_utils_strftime (day, "%A %-d %B %Y"); day_copy = jana_time_duplicate (day); gtk_tree_model_filter_convert_iter_to_child_iter ( filter, &child_iter, &iter); gtk_list_store_insert_before (priv->model, &child_iter, &child_iter); gtk_list_store_set (priv->model, &child_iter, JANA_GTK_EVENT_LIST_COL_HEADER, header, JANA_GTK_EVENT_LIST_COL_TIME, day_copy, JANA_GTK_EVENT_LIST_COL_IS_HEADER, TRUE, -1); g_object_unref (day_copy); gtk_tree_model_filter_convert_child_iter_to_iter ( filter, &iter, &child_iter); g_free (header); } g_object_unref (start); } while (gtk_tree_model_iter_next ((GtkTreeModel *)filter, &iter)); if (day) g_object_unref (day); } static void row_deleted_cb (GtkTreeModel *tree_model, GtkTreePath *path, JanaGtkEventList *self) { GtkTreeIter iter; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); gboolean skip = FALSE; if (!gtk_tree_model_get_iter_first ((GtkTreeModel *)priv->model, &iter)) return; do { GtkTreeRowReference *row; GtkTreePath *stored_path; GtkTreeModel *model; skip = FALSE; gtk_tree_model_get ((GtkTreeModel *)priv->model, &iter, JANA_GTK_EVENT_LIST_COL_ROW, &row, -1); if (!row) continue; /* We check the path in case we're manually deleting rows, * as is done when we remove a store from the list. */ model = gtk_tree_row_reference_get_model (row); stored_path = gtk_tree_row_reference_get_path (row); if ((!gtk_tree_row_reference_valid (row)) || ((model == tree_model) && (gtk_tree_path_compare (stored_path, path) == 0))) { if (gtk_list_store_remove (priv->model, &iter)) skip = TRUE; gtk_tree_row_reference_free (row); if (!skip) break; } } while (skip || gtk_tree_model_iter_next ( (GtkTreeModel *)priv->model, &iter)); recalculate_headers (self); } static void row_changed_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkEventList *self) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); /* Re-sort */ /* http://bugzilla.gnome.org/show_bug.cgi?id=316152 */ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->model), JANA_GTK_EVENT_LIST_COL_ROW, jana_gtk_event_list_compare, self, NULL); /* Re-filter */ /* Note, this isn't really necessary as recalculating headers will * trigger a re-filter, but that may change... */ gtk_tree_model_filter_refilter ((GtkTreeModelFilter *) gtk_tree_view_get_model (GTK_TREE_VIEW (self))); recalculate_headers (self); } static void row_inserted_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkEventList *self) { GtkTreeRowReference *row; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); row = gtk_tree_row_reference_new (tree_model, path); gtk_list_store_insert_with_values (priv->model, NULL, 0, JANA_GTK_EVENT_LIST_COL_ROW, row, JANA_GTK_EVENT_LIST_COL_IS_EVENT, TRUE, -1); recalculate_headers (self); } static void size_allocate_cb (GtkWidget *self, GtkAllocation *allocation, gpointer user_data) { static gint last_width[] = { 0, 0 }; gint width; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); /* Store the last two negotiated widths to stop oscillation when * crossing the threshold for which scroll-bars are required. */ width = gtk_tree_view_column_get_width (priv->column); if ((width != last_width[0]) && (width != last_width[1])) { last_width[1] = last_width[0]; last_width[0] = width; g_object_set (G_OBJECT (priv->event_renderer), "cell_width", width, NULL); gtk_tree_view_columns_autosize (GTK_TREE_VIEW (self)); } } static void jana_gtk_event_list_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (object); switch (property_id) { case PROP_COLUMN : g_value_set_object (value, priv->column); break; case PROP_EVENT_RENDERER : g_value_set_object (value, priv->event_renderer); break; case PROP_TEXT_RENDERER : g_value_set_object (value, priv->text_renderer); break; case PROP_SHOW_HEADERS : g_value_set_boolean (value, priv->show_headers); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_event_list_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_SHOW_HEADERS : jana_gtk_event_list_set_show_headers (JANA_GTK_EVENT_LIST ( object), g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_event_list_dispose (GObject *self) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); while (priv->stores) { GObject *object = (GObject *)priv->stores->data; g_signal_handlers_disconnect_by_func ( object, row_inserted_cb, self); g_signal_handlers_disconnect_by_func ( object, row_changed_cb, self); g_signal_handlers_disconnect_by_func ( object, row_deleted_cb, self); g_object_unref (object); priv->stores = g_list_delete_link (priv->stores, priv->stores); } if (G_OBJECT_CLASS (jana_gtk_event_list_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_event_list_parent_class)-> dispose (self); } static void jana_gtk_event_list_finalize (GObject *object) { /*JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (object);*/ G_OBJECT_CLASS (jana_gtk_event_list_parent_class)->finalize (object); } static void jana_gtk_event_list_class_init (JanaGtkEventListClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkEventListPrivate)); object_class->get_property = jana_gtk_event_list_get_property; object_class->set_property = jana_gtk_event_list_set_property; object_class->dispose = jana_gtk_event_list_dispose; object_class->finalize = jana_gtk_event_list_finalize; g_object_class_install_property ( object_class, PROP_COLUMN, g_param_spec_object ( "column", "Column", "The column used to display events and headers.", GTK_TYPE_TREE_VIEW_COLUMN, G_PARAM_READABLE)); g_object_class_install_property ( object_class, PROP_EVENT_RENDERER, g_param_spec_object ( "event-renderer", "Event renderer", "The cell renderer used to render event objects.", JANA_GTK_TYPE_CELL_RENDERER_EVENT, G_PARAM_READABLE)); g_object_class_install_property ( object_class, PROP_TEXT_RENDERER, g_param_spec_object ( "text-renderer", "Text renderer", "The cell renderer used to render headers.", GTK_TYPE_CELL_RENDERER_TEXT, G_PARAM_READABLE)); g_object_class_install_property ( object_class, PROP_SHOW_HEADERS, g_param_spec_boolean ( "show_headers", "Show headers", "Whether or not to display unique day headers.", TRUE, G_PARAM_READWRITE)); } static void style_set_cb (GtkWidget *widget, GtkStyle *previous_style, gpointer user_data) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (widget); gtk_widget_realize (widget); g_object_set (G_OBJECT (priv->text_renderer), "background-gdk", >k_widget_get_style (widget)->text_aa[GTK_STATE_NORMAL], "foreground-gdk", >k_widget_get_style (widget)->base[GTK_STATE_NORMAL], "weight", 800, NULL); } static void jana_gtk_event_list_init (JanaGtkEventList *self) { GtkTreeModel *filter; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); priv->show_headers = TRUE; priv->model = gtk_list_store_new (JANA_GTK_EVENT_LIST_COL_LAST, G_TYPE_POINTER, /* ROW */ G_TYPE_OBJECT, /* TIME */ G_TYPE_STRING, /* HEADER */ G_TYPE_BOOLEAN, /* IS_EVENT */ G_TYPE_BOOLEAN); /* IS_HEADER */ filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->model), NULL); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->model), JANA_GTK_EVENT_LIST_COL_ROW, jana_gtk_event_list_compare, self, NULL); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->model), JANA_GTK_EVENT_LIST_COL_ROW, GTK_SORT_ASCENDING); gtk_tree_view_set_model (GTK_TREE_VIEW (self), filter); g_object_unref (filter); priv->event_renderer = jana_gtk_cell_renderer_event_new (); priv->text_renderer = gtk_cell_renderer_text_new (); g_object_set (G_OBJECT (priv->event_renderer), "draw_time", TRUE, "draw_box", FALSE, NULL); g_object_set (G_OBJECT (priv->text_renderer), "weight", 800, "ellipsize", PANGO_ELLIPSIZE_END, NULL); priv->column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (priv->column, "Events"); gtk_tree_view_column_pack_start (priv->column, priv->event_renderer, TRUE); gtk_tree_view_column_pack_end (priv->column, priv->text_renderer, TRUE); gtk_tree_view_column_add_attribute (priv->column, priv->event_renderer, "row", JANA_GTK_EVENT_LIST_COL_ROW); gtk_tree_view_column_add_attribute (priv->column, priv->event_renderer, "visible", JANA_GTK_EVENT_LIST_COL_IS_EVENT); gtk_tree_view_column_add_attribute (priv->column, priv->text_renderer, "text", JANA_GTK_EVENT_LIST_COL_HEADER); gtk_tree_view_column_add_attribute (priv->column, priv->text_renderer, "visible", JANA_GTK_EVENT_LIST_COL_IS_HEADER); gtk_tree_view_append_column (GTK_TREE_VIEW (self), priv->column); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self), FALSE); g_signal_connect (G_OBJECT (self), "size-allocate", G_CALLBACK (size_allocate_cb), NULL); g_signal_connect (G_OBJECT (self), "style-set", G_CALLBACK (style_set_cb), NULL); } GtkWidget* jana_gtk_event_list_new (void) { return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_EVENT_LIST, NULL)); } static void insert_rows (JanaGtkEventList *self, JanaGtkEventStore *store) { GtkTreeIter iter; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) do { GtkTreePath *path = gtk_tree_model_get_path ( (GtkTreeModel *)store, &iter); row_inserted_cb ((GtkTreeModel *)store, path, &iter, self); gtk_tree_path_free (path); } while (gtk_tree_model_iter_next ((GtkTreeModel *)store, &iter)); } static void delete_rows (JanaGtkEventList *self, JanaGtkEventStore *store) { GtkTreeIter iter; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) do { GtkTreePath *path = gtk_tree_model_get_path ( (GtkTreeModel *)store, &iter); row_deleted_cb ((GtkTreeModel *)store, path, self); gtk_tree_path_free (path); } while (gtk_tree_model_iter_next ((GtkTreeModel *)store, &iter)); } void jana_gtk_event_list_add_store (JanaGtkEventList *self, JanaGtkEventStore *store) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); priv->stores = g_list_prepend (priv->stores, g_object_ref (store)); insert_rows (self, store); g_signal_connect (store, "row-inserted", G_CALLBACK (row_inserted_cb), self); g_signal_connect (store, "row-changed", G_CALLBACK (row_changed_cb), self); g_signal_connect (store, "row-deleted", G_CALLBACK (row_deleted_cb), self); } void jana_gtk_event_list_remove_store (JanaGtkEventList *self, JanaGtkEventStore *store) { GList *link; JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); if (!(link = g_list_find (priv->stores, store))) return; g_signal_handlers_disconnect_by_func (store, row_inserted_cb, self); g_signal_handlers_disconnect_by_func (store, row_changed_cb, self); g_signal_handlers_disconnect_by_func (store, row_deleted_cb, self); delete_rows (self, store); g_object_unref (store); priv->stores = g_list_delete_link (priv->stores, link); } GtkTreeModelFilter * jana_gtk_event_list_get_filter (JanaGtkEventList *self) { return GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model ( GTK_TREE_VIEW (self))); } void jana_gtk_event_list_refilter (JanaGtkEventList *self) { gtk_tree_model_filter_refilter ((GtkTreeModelFilter *) gtk_tree_view_get_model (GTK_TREE_VIEW (self))); recalculate_headers (self); } /** * jana_gtk_event_list_set_show_headers: * @self: A #JanaGtkEventList * @show_headers: %TRUE to show date headers, %FALSE otherwise * * Sets whether to display unique day-header rows for each day at least one * event falls on. */ void jana_gtk_event_list_set_show_headers (JanaGtkEventList *self, gboolean show_headers) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); if (priv->show_headers != show_headers) { priv->show_headers = show_headers; recalculate_headers (self); } } /** * jana_gtk_event_list_get_show_headers: * @self: A #JanaGtkEventList * * Determines whether unique day headers are to be displayed. See * jana_gtk_event_list_set_show_headers(). * * Returns: %TRUE if day headers are being displayed, %FALSE otherwise. */ gboolean jana_gtk_event_list_get_show_headers (JanaGtkEventList *self) { JanaGtkEventListPrivate *priv = EVENT_LIST_PRIVATE (self); return priv->show_headers; } jana/libjana-gtk/libjana-gtk.pc.in0000644000175000017500000000042611327631152017201 0ustar paulliupaulliuprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libjana-gtk Description: A set of GTK widgets to visualise libjana data Requires: libjana gtk+-2.0 gthread-2.0 Version: @VERSION@ Libs: -L${libdir} -ljana-gtk Cflags: -I${includedir}/jana jana/libjana-gtk/jana-gtk-world-map-marker-pixbuf.h0000644000175000017500000000441711327631152022410 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_WORLD_MAP_MARKER_PIXBUF_H #define _JANA_GTK_WORLD_MAP_MARKER_PIXBUF_H #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF \ jana_gtk_world_map_marker_pixbuf_get_type() #define JANA_GTK_WORLD_MAP_MARKER_PIXBUF(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF, \ JanaGtkWorldMapMarkerPixbuf)) #define JANA_GTK_WORLD_MAP_MARKER_PIXBUF_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF, \ JanaGtkWorldMapMarkerPixbufClass)) #define JANA_GTK_IS_WORLD_MAP_MARKER_PIXBUF(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF)) #define JANA_GTK_IS_WORLD_MAP_MARKER_PIXBUF_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF)) #define JANA_GTK_WORLD_MAP_MARKER_PIXBUF_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF, \ JanaGtkWorldMapMarkerPixbufClass)) typedef struct { JanaGtkWorldMapMarker parent; GdkPixbuf *pixbuf; } JanaGtkWorldMapMarkerPixbuf; typedef struct { JanaGtkWorldMapMarkerClass parent_class; } JanaGtkWorldMapMarkerPixbufClass; GType jana_gtk_world_map_marker_pixbuf_get_type (void); JanaGtkWorldMapMarker *jana_gtk_world_map_marker_pixbuf_new (GdkPixbuf *pixbuf); G_END_DECLS #endif jana/libjana-gtk/jana-gtk-clock.c0000644000175000017500000010525511327631152017024 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_GLADE #include #endif #include "jana-gtk-clock.h" #include G_DEFINE_TYPE (JanaGtkClock, jana_gtk_clock, GTK_TYPE_EVENT_BOX) #define CLOCK_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_CLOCK, JanaGtkClockPrivate)) typedef struct _JanaGtkClockPrivate JanaGtkClockPrivate; struct _JanaGtkClockPrivate { gboolean digital; gboolean show_seconds; gboolean buffer_time; gboolean draw_shadow; cairo_surface_t *buffer; JanaTime *time; gboolean in; gboolean clicked; /* Variables for threaded drawing */ GtkStyle *style; JanaTime *time_copy; GThread *draw_thread; gboolean dirty; }; enum { PROP_TIME = 1, PROP_DIGITAL, PROP_SHOW_SECONDS, PROP_BUFFER_TIME, PROP_DRAW_SHADOW, }; enum { RENDER_START, RENDER_STOP, CLICKED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void jana_gtk_clock_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (object); switch (property_id) { case PROP_TIME : g_value_take_object (value, priv->time ? jana_time_duplicate (priv->time) : NULL); break; case PROP_DIGITAL : g_value_set_boolean (value, priv->digital); break; case PROP_SHOW_SECONDS : g_value_set_boolean (value, priv->show_seconds); break; case PROP_BUFFER_TIME : g_value_set_boolean (value, priv->buffer_time); break; case PROP_DRAW_SHADOW : g_value_set_boolean (value, priv->draw_shadow); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_clock_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_TIME : jana_gtk_clock_set_time (JANA_GTK_CLOCK (object), g_value_get_object (value)); break; case PROP_DIGITAL : jana_gtk_clock_set_digital (JANA_GTK_CLOCK (object), g_value_get_boolean (value)); break; case PROP_SHOW_SECONDS : jana_gtk_clock_set_show_seconds (JANA_GTK_CLOCK (object), g_value_get_boolean (value)); break; case PROP_BUFFER_TIME : jana_gtk_clock_set_buffer_time (JANA_GTK_CLOCK (object), g_value_get_boolean (value)); break; case PROP_DRAW_SHADOW : jana_gtk_clock_set_draw_shadow (JANA_GTK_CLOCK (object), g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void stop_draw_thread (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->draw_thread) { priv->dirty = TRUE; g_thread_join (priv->draw_thread); priv->dirty = FALSE; priv->draw_thread = NULL; g_object_unref (priv->style); priv->style = NULL; if (priv->time_copy) { g_object_unref (priv->time_copy); priv->time_copy = NULL; } } } static void jana_gtk_clock_dispose (GObject *object) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (object); stop_draw_thread (JANA_GTK_CLOCK (object)); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (G_OBJECT_CLASS (jana_gtk_clock_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_clock_parent_class)->dispose (object); } static void jana_gtk_clock_finalize (GObject *object) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (object); if (priv->buffer) { cairo_surface_destroy (priv->buffer); priv->buffer = NULL; } G_OBJECT_CLASS (jana_gtk_clock_parent_class)->finalize (object); } static void draw_analogue_face (JanaGtkClock *clock, cairo_t *cr, GtkStyle *style, JanaTime *time) { gdouble pi_ratio; gint width, height, size, thickness, hours, minutes, seconds; JanaGtkClockPrivate *priv = CLOCK_PRIVATE (clock); if (time) { hours = jana_time_get_hours (time); minutes = jana_time_get_minutes (time); seconds = jana_time_get_seconds (time); } else { hours = minutes = seconds = 0; } width = cairo_image_surface_get_width (priv->buffer); height = cairo_image_surface_get_height (priv->buffer); if (priv->draw_shadow) height -= height/20; size = MIN (width, height); gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); cairo_set_line_width (cr, MAX (1.5, size / 60)); thickness = size / 20; /* Draw hour hand */ pi_ratio = ((gdouble)((hours*60)+minutes)/60.0)/6.0; cairo_new_path (cr); cairo_move_to (cr, (width/2) + ((size/2 - thickness/2 - size/4) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) + ((size/2 - thickness/2 - size/4) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_line_to (cr, (width/2) + ((size/35) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) +((size/35) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_close_path (cr); cairo_stroke (cr); if (priv->dirty) return; /* Draw minute hand */ pi_ratio = (gdouble)minutes/30.0; cairo_new_path (cr); cairo_move_to (cr, (width/2) + ((size/2 - thickness/2 - size/8) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) + ((size/2 - thickness/2 - size/8) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_line_to (cr, (width/2) + ((size/35) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) +((size/35) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_close_path (cr); cairo_stroke (cr); if ((!priv->show_seconds) || priv->dirty) return; /* Draw second hand */ gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_SELECTED]); cairo_set_line_width (cr, MAX (1, size / 120)); pi_ratio = (gdouble)seconds/30.0; cairo_new_path (cr); cairo_move_to (cr, (width/2) + ((size/2 - thickness/2 - size/8) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) + ((size/2 - thickness/2 - size/8) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_line_to (cr, (width/2) + ((size/35) * cos ((pi_ratio * M_PI)-(M_PI/2))), (height/2) +((size/35) * sin ((pi_ratio * M_PI)-(M_PI/2)))); cairo_close_path (cr); cairo_stroke (cr); } static void draw_analogue_clock (JanaGtkClock *clock, cairo_t *cr, GtkStyle *style) { cairo_pattern_t *pattern; gint width, height, size, thickness, i, shadow_radius; double base_color[3]; double bg_color[3]; double fg_color[3]; JanaGtkClockPrivate *priv = CLOCK_PRIVATE (clock); /* Draw a Tango-style analogue clock face */ base_color[0] = ((double)style->bg[GTK_STATE_SELECTED].red)/ (double)G_MAXUINT16; base_color[1] = ((double)style->bg[GTK_STATE_SELECTED].green)/ (double)G_MAXUINT16; base_color[2] = ((double)style->bg[GTK_STATE_SELECTED].blue)/ (double)G_MAXUINT16; bg_color[0] = ((double)style->base[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; bg_color[1] = ((double)style->base[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; bg_color[2] = ((double)style->base[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; fg_color[0] = ((double)style->text[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; fg_color[1] = ((double)style->text[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; fg_color[2] = ((double)style->text[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; width = cairo_image_surface_get_width (priv->buffer); height = cairo_image_surface_get_height (priv->buffer); if (priv->draw_shadow) height -= height/20; size = MIN (width, height); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); if (priv->dirty) return; /* Draw shadow */ if (priv->draw_shadow) { cairo_save (cr); shadow_radius = MIN (width, cairo_image_surface_get_height ( priv->buffer))/20; cairo_translate (cr, width/2, height/2 + size/2); cairo_scale (cr, (gdouble)size / (gdouble)(shadow_radius*2), 1.0); cairo_new_path (cr); cairo_arc (cr, 0, 0, shadow_radius, 0, 2 * M_PI); cairo_close_path (cr); pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, shadow_radius); cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 0, 0.5); cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 0, 0); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_restore (cr); } if (priv->dirty) return; /* Draw clock face */ thickness = size / 20; cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/2 - thickness/2, 0, 2 * M_PI); cairo_close_path (cr); pattern = cairo_pattern_create_radial (width/2, height/3, 0, width/2, height/2, size/2 - thickness/2); cairo_pattern_add_color_stop_rgb (pattern, 0, bg_color[0]*2, bg_color[1]*2, bg_color[2]*2); cairo_pattern_add_color_stop_rgb (pattern, 0.3, bg_color[0], bg_color[1], bg_color[2]); cairo_pattern_add_color_stop_rgb (pattern, 1, bg_color[0]/1.15, bg_color[1]/1.15, bg_color[2]/1.15); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); if (priv->dirty) return; /* Draw tick marks */ cairo_set_source_rgb (cr, fg_color[0], fg_color[1], fg_color[2]); for (i = 0; i < 4; i++) { cairo_new_path (cr); cairo_arc (cr, (width/2) + ((size/2 - thickness/2 - size/6) * cos (i * M_PI/2)), (height/2) + ((size/2 - thickness/2 - size/6) * sin (i * M_PI/2)), size/40, 0, 2 * M_PI); cairo_close_path (cr); cairo_fill (cr); } if (priv->dirty) return; /* Draw centre point */ cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/35, 0, 2 * M_PI); cairo_close_path (cr); cairo_set_line_width (cr, size/60); cairo_stroke (cr); if (priv->dirty) return; /* Draw internal clock-frame shadow */ thickness = size / 20; cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/2 - thickness, 0, 2 * M_PI); cairo_close_path (cr); pattern = cairo_pattern_create_radial ((width/2) - (size/4), (height/2) - (size/4), 0, width/2, height/2, size/2 - thickness/2); cairo_pattern_add_color_stop_rgb (pattern, 0, bg_color[0]/2, bg_color[1]/2, bg_color[2]/2); cairo_pattern_add_color_stop_rgb (pattern, 0.5, bg_color[0]/2, bg_color[1]/2, bg_color[2]/2); cairo_pattern_add_color_stop_rgb (pattern, 1, bg_color[0]*2, bg_color[1]*2, bg_color[2]*2); cairo_set_source (cr, pattern); cairo_set_line_width (cr, thickness); cairo_stroke (cr); cairo_pattern_destroy (pattern); if (priv->dirty) return; /* Draw internal clock-frame */ cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/2 - thickness/2, 0, 2 * M_PI); cairo_close_path (cr); pattern = cairo_pattern_create_radial ((width/2) - (size/3), (height/2) - (size/3), 0, width/3, height/3, size/2); cairo_pattern_add_color_stop_rgb (pattern, 0, base_color[0]*1.2, base_color[1]*1.2, base_color[2]*1.2); cairo_pattern_add_color_stop_rgb (pattern, 0.7, base_color[0], base_color[1], base_color[2]); cairo_pattern_add_color_stop_rgb (pattern, 1, base_color[0]/1.2, base_color[1]/1.2, base_color[2]/1.2); cairo_set_source (cr, pattern); cairo_stroke (cr); cairo_pattern_destroy (pattern); if (priv->dirty) return; /* Dark outline frame */ thickness = size / 60; cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/2 - thickness/2, 0, 2 * M_PI); cairo_close_path (cr); cairo_set_source_rgb (cr, base_color[0]/2, base_color[1]/2, base_color[2]/2); cairo_set_line_width (cr, thickness); cairo_stroke (cr); if (priv->dirty) return; /* Draw less dark inner outline frame */ thickness = size / 40; cairo_new_path (cr); cairo_arc (cr, width/2, height/2, size/2 - (size/20)/2 - thickness, 0, 2 * M_PI); cairo_close_path (cr); cairo_set_source_rgb (cr, base_color[0]/1.5, base_color[1]/1.5, base_color[2]/1.5); cairo_set_line_width (cr, thickness); cairo_stroke (cr); } static void draw_digital_number (cairo_t *cr, gint number, double *bg, double *fg) { double padding = 0.01; /* Draw a segmented number, like on an old digital LCD display */ /* Top */ switch (number) { case 0 : case 2 : case 3 : case 5 : case 6 : case 7 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 0, 0); cairo_line_to (cr, 8.0/8.0, 0); cairo_line_to (cr, 4.0/5.0 - padding, 1.0/8.0 - padding); cairo_line_to (cr, 1.0/5.0 + padding, 1.0/8.0 - padding); cairo_close_path (cr); cairo_fill (cr); /* Top-left */ switch (number) { case 0 : case 4 : case 5 : case 6 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 0, 0); cairo_line_to (cr, 0, 4.0/8.0); cairo_line_to (cr, 1.0/5.0 - padding, 3.5/8.0 - padding); cairo_line_to (cr, 1.0/5.0 - padding, 1.0/8.0 + padding); cairo_close_path (cr); cairo_fill (cr); /* Top-right */ switch (number) { case 0 : case 1 : case 2 : case 3 : case 4 : case 7 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 5.0/5.0, 0); cairo_line_to (cr, 5.0/5.0, 4.0/8.0); cairo_line_to (cr, 4.0/5.0 + padding, 3.5/8.0 - padding); cairo_line_to (cr, 4.0/5.0 + padding, 1.0/8.0 + padding); cairo_close_path (cr); cairo_fill (cr); /* Middle */ switch (number) { case 2 : case 3 : case 4 : case 5 : case 6 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 0, 4.0/8.0); cairo_line_to (cr, 1.0/5.0 + padding, 3.5/8.0 + padding); cairo_line_to (cr, 4.0/5.0 - padding, 3.5/8.0 + padding); cairo_line_to (cr, 5.0/5.0, 4.0/8.0); cairo_line_to (cr, 4.0/5.0 - padding, 4.5/8.0 - padding); cairo_line_to (cr, 1.0/5.0 + padding, 4.5/8.0 - padding); cairo_close_path (cr); cairo_fill (cr); /* Bottom-left */ switch (number) { case 0 : case 2 : case 6 : case 8 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 0, 4.0/8.0); cairo_line_to (cr, 0, 8.0/8.0); cairo_line_to (cr, 1.0/5.0 - padding, 7.0/8.0 - padding); cairo_line_to (cr, 1.0/5.0 - padding, 4.5/8.0 + padding); cairo_close_path (cr); cairo_fill (cr); /* Bottom-right */ switch (number) { case 0 : case 1 : case 3 : case 4 : case 5 : case 6 : case 7 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 5.0/5.0, 4.0/8.0); cairo_line_to (cr, 5.0/5.0, 8.0/8.0); cairo_line_to (cr, 4.0/5.0 + padding, 7.0/8.0 - padding); cairo_line_to (cr, 4.0/5.0 + padding, 4.5/8.0 + padding); cairo_close_path (cr); cairo_fill (cr); /* Bottom */ switch (number) { case 0 : case 2 : case 3 : case 5 : case 6 : case 8 : case 9 : cairo_set_source_rgb (cr, fg[0], fg[1], fg[2]); break; default : cairo_set_source_rgb (cr, bg[0], bg[1], bg[2]); break; } cairo_new_path (cr); cairo_move_to (cr, 0, 8.0/8.0); cairo_line_to (cr, 5.0/5.0, 8.0/8.0); cairo_line_to (cr, 4.0/5.0 - padding, 7.0/8.0 + padding); cairo_line_to (cr, 1.0/5.0 + padding, 7.0/8.0 + padding); cairo_close_path (cr); cairo_fill (cr); } static void draw_digital_face (JanaGtkClock *clock, cairo_t *cr, GtkStyle *style, JanaTime *time) { gint x, y, width, height, thickness, hours, minutes, seconds; double bg_color[3]; double fg_color[3]; JanaGtkClockPrivate *priv = CLOCK_PRIVATE (clock); if (time) { hours = jana_time_get_hours (time); minutes = jana_time_get_minutes (time); seconds = jana_time_get_seconds (time); } else { hours = minutes = seconds = 0; } bg_color[0] = ((double)style->text[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; bg_color[1] = ((double)style->text[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; bg_color[2] = ((double)style->text[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; fg_color[0] = ((double)style->base[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; fg_color[1] = ((double)style->base[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; fg_color[2] = ((double)style->base[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; height = cairo_image_surface_get_height (priv->buffer); if (priv->draw_shadow) height -= height/10; width = cairo_image_surface_get_width (priv->buffer); if (priv->draw_shadow) width -= width/10; width = MIN (width, height * 2); height = width / 2; x = (cairo_image_surface_get_width (priv->buffer) - width)/2; y = (cairo_image_surface_get_height (priv->buffer) - height)/2; thickness = width/28; if (priv->dirty) return; cairo_translate (cr, x + thickness*3, y + thickness*3); cairo_scale (cr, (double)(width - thickness*6)/5.0, (double)(height - thickness*6)); draw_digital_number (cr, time ? hours/10 : -1, bg_color, fg_color); cairo_translate (cr, 1.1, 0); if (priv->dirty) return; draw_digital_number (cr, time ? hours%10 : -1, bg_color, fg_color); cairo_translate (cr, 1.1, 0); if (priv->dirty) return; /* Draw separator */ if (time && priv->show_seconds && ((seconds % 2) == 1)) cairo_set_source_rgb ( cr, bg_color[0], bg_color[1], bg_color[2]); else cairo_set_source_rgb ( cr, fg_color[0], fg_color[1], fg_color[2]); cairo_new_path (cr); cairo_rectangle (cr, 0.15, 2.0/8.0, 0.3, 1.0/8.0); cairo_rectangle (cr, 0.15, 5.0/8.0, 0.3, 1.0/8.0); cairo_fill (cr); if (priv->dirty) return; cairo_translate (cr, 0.7, 0); draw_digital_number (cr, time ? minutes/10 : -1, bg_color, fg_color); cairo_translate (cr, 1.1, 0); if (priv->dirty) return; draw_digital_number (cr, time ? minutes%10 : -1, bg_color, fg_color); } static void draw_digital_clock (JanaGtkClock *clock, cairo_t *cr, GtkStyle *style) { cairo_pattern_t *pattern; gint x, y, width, height, thickness, shadow_radius; double base_color[3]; double bg_color[3]; double fg_color[3]; JanaGtkClockPrivate *priv = CLOCK_PRIVATE (clock); /* Draw a Tango-style digital clock face */ base_color[0] = ((double)style->bg[GTK_STATE_SELECTED].red)/ (double)G_MAXUINT16; base_color[1] = ((double)style->bg[GTK_STATE_SELECTED].green)/ (double)G_MAXUINT16; base_color[2] = ((double)style->bg[GTK_STATE_SELECTED].blue)/ (double)G_MAXUINT16; bg_color[0] = ((double)style->base[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; bg_color[1] = ((double)style->base[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; bg_color[2] = ((double)style->base[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; fg_color[0] = ((double)style->text[GTK_STATE_NORMAL].red)/ (double)G_MAXUINT16; fg_color[1] = ((double)style->text[GTK_STATE_NORMAL].green)/ (double)G_MAXUINT16; fg_color[2] = ((double)style->text[GTK_STATE_NORMAL].blue)/ (double)G_MAXUINT16; height = cairo_image_surface_get_height (priv->buffer); if (priv->draw_shadow) height -= height/10; width = cairo_image_surface_get_width (priv->buffer); if (priv->draw_shadow) width -= width/10; width = MIN (width, height * 2); height = width / 2; x = (cairo_image_surface_get_width (priv->buffer) - width)/2; y = (cairo_image_surface_get_height (priv->buffer) - height)/2; cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); if (priv->dirty) return; cairo_translate (cr, x, y); if (priv->draw_shadow) { /* Draw ground shadow */ cairo_save (cr); cairo_translate (cr, width/2, height); cairo_scale (cr, 1.0, ((double)height/(double)width)/10); cairo_new_path (cr); shadow_radius = ((10*width)/9)/2; cairo_arc (cr, 0, 0, shadow_radius, 0, 2 * M_PI); cairo_close_path (cr); pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, shadow_radius); cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 0, 0.5); cairo_pattern_add_color_stop_rgba (pattern, 0.5, 0, 0, 0, 0.5); cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 0, 0); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_restore (cr); } if (priv->dirty) return; /* Draw internal frame shadow */ thickness = width/28; cairo_new_path (cr); cairo_rectangle (cr, thickness*2, thickness*2, width - thickness*4, height - thickness*4); pattern = cairo_pattern_create_radial ( width - thickness * 4, height - thickness * 4, 0, width - thickness * 4, height - thickness * 4, height); cairo_pattern_add_color_stop_rgb (pattern, 0, (2*fg_color[0]+bg_color[0])/3, (2*fg_color[1]+bg_color[1])/3, (2*fg_color[2]+bg_color[2])/3); cairo_pattern_add_color_stop_rgb (pattern, 0.5, fg_color[0], fg_color[1], fg_color[2]); cairo_pattern_add_color_stop_rgb (pattern, 1, fg_color[0], fg_color[1], fg_color[2]); cairo_set_source (cr, pattern); cairo_set_line_width (cr, thickness); cairo_stroke (cr); cairo_pattern_destroy (pattern); if (priv->dirty) return; /* Draw clock face */ cairo_new_path (cr); cairo_rectangle (cr, thickness*2.5, thickness*2.5, width - thickness*5, height - thickness*5); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_source_rgb (cr, (15*fg_color[0]+bg_color[0])/16, (15*fg_color[1]+bg_color[1])/16, (15*fg_color[2]+bg_color[2])/16); cairo_set_line_width (cr, thickness/2); cairo_stroke_preserve (cr); cairo_fill (cr); if (priv->dirty) return; /* Draw dark outline frame */ cairo_new_path (cr); cairo_rectangle (cr, thickness/2, thickness/2, width - thickness, height - thickness); cairo_set_line_width (cr, thickness); cairo_set_source_rgb (cr, base_color[0]/2, base_color[1]/2, base_color[2]/2); cairo_stroke (cr); if (priv->dirty) return; /* Draw main outline frame */ cairo_new_path (cr); cairo_rectangle (cr, thickness, thickness, width - thickness*2, height - thickness*2); pattern = cairo_pattern_create_radial (thickness/2, thickness/2, 0, thickness/2, thickness/2, width); cairo_pattern_add_color_stop_rgb (pattern, 0, base_color[0]*1.2, base_color[1]*1.2, base_color[2]*1.2); cairo_pattern_add_color_stop_rgb (pattern, 0.7, base_color[0], base_color[1], base_color[2]); cairo_pattern_add_color_stop_rgb (pattern, 1, base_color[0]/1.2, base_color[1]/1.2, base_color[2]/1.2); cairo_set_source (cr, pattern); cairo_stroke (cr); cairo_pattern_destroy (pattern); if (priv->dirty) return; /* Draw less dark inner outline frame */ cairo_new_path (cr); cairo_rectangle (cr, thickness*1.5, thickness*1.5, width - thickness*3, height - thickness*3); cairo_set_source_rgb (cr, base_color[0]/1.5, base_color[1]/1.5, base_color[2]/1.5); cairo_set_line_width (cr, thickness/2); cairo_stroke (cr); } static gboolean jana_gtk_clock_expose_event (GtkWidget *widget, GdkEventExpose *event) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); /* Don't draw anything until the entire clock is ready to draw */ if (!priv->draw_thread) { cairo_t *cr = gdk_cairo_create (widget->window); cairo_translate (cr, widget->allocation.x, widget->allocation.y); /* Draw background */ if (priv->buffer) { cairo_set_source_surface (cr, priv->buffer, 0, 0); cairo_paint_with_alpha (cr, 1.0); } /* Draw face */ if (!priv->buffer_time) { if (priv->digital) draw_digital_face ((JanaGtkClock *)widget, cr, widget->style, priv->time); else draw_analogue_face ((JanaGtkClock *)widget, cr, widget->style, priv->time); } cairo_destroy (cr); } return GTK_WIDGET_CLASS (jana_gtk_clock_parent_class)-> expose_event (widget, event); } static gboolean idle_redraw (GtkWidget *widget) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); priv->draw_thread = NULL; g_signal_emit (widget, signals[RENDER_STOP], 0); gtk_widget_queue_draw (widget); return FALSE; } static gpointer draw_clock (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); cairo_t *cr = cairo_create (priv->buffer); if (priv->digital) { draw_digital_clock (self, cr, GTK_WIDGET (self)->style); if (priv->buffer_time && (!priv->dirty)) draw_digital_face (self, cr, GTK_WIDGET (self)->style, priv->time_copy); } else { draw_analogue_clock (self, cr, GTK_WIDGET (self)->style); if (priv->buffer_time && (!priv->dirty)) draw_analogue_face (self, cr, GTK_WIDGET (self)->style, priv->time_copy); } cairo_destroy (cr); if (!priv->dirty) { g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)idle_redraw, self, NULL); } return NULL; } static void refresh_buffer (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if ((!GTK_WIDGET_MAPPED (self)) || (!priv->buffer)) return; stop_draw_thread (self); priv->style = gtk_style_copy (GTK_WIDGET (self)->style); priv->time_copy = priv->time ? jana_time_duplicate (priv->time) : NULL; g_signal_emit (self, signals[RENDER_START], 0); priv->draw_thread = g_thread_create ((GThreadFunc)draw_clock, self, TRUE, NULL); } static void jana_gtk_clock_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); /* Note: Calling this after the below breaks things, not sure why */ GTK_WIDGET_CLASS (jana_gtk_clock_parent_class)-> size_allocate (widget, allocation); if (!GTK_WIDGET_REALIZED (widget)) gtk_widget_realize (widget); if ((!priv->buffer) || (allocation->width != cairo_image_surface_get_width (priv->buffer)) || (allocation->height != cairo_image_surface_get_height (priv->buffer))) { stop_draw_thread (JANA_GTK_CLOCK (widget)); if (priv->buffer) cairo_surface_destroy (priv->buffer); priv->buffer = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, allocation->width, allocation->height); refresh_buffer (JANA_GTK_CLOCK (widget)); } } static void jana_gtk_clock_map (GtkWidget *widget) { GTK_WIDGET_CLASS (jana_gtk_clock_parent_class)->map (widget); GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); refresh_buffer (JANA_GTK_CLOCK (widget)); } static void jana_gtk_clock_unmap (GtkWidget *widget) { GTK_WIDGET_CLASS (jana_gtk_clock_parent_class)->unmap (widget); GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); } static void jana_gtk_clock_style_set (GtkWidget *widget, GtkStyle *previous_style) { GTK_WIDGET_CLASS (jana_gtk_clock_parent_class)-> style_set (widget, previous_style); refresh_buffer (JANA_GTK_CLOCK (widget)); } static gboolean jana_gtk_clock_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); priv->in = TRUE; return FALSE; } static gboolean jana_gtk_clock_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); priv->in = FALSE; return FALSE; } static gboolean jana_gtk_clock_button_press_event (GtkWidget *widget, GdkEventButton *event) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); priv->clicked = TRUE; return FALSE; } static gboolean jana_gtk_clock_button_release_event (GtkWidget *widget, GdkEventButton *event) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (widget); if (priv->clicked && priv->in) g_signal_emit (widget, signals[CLICKED], 0, event); priv->clicked = FALSE; return FALSE; } static void jana_gtk_clock_class_init (JanaGtkClockClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkClockPrivate)); object_class->get_property = jana_gtk_clock_get_property; object_class->set_property = jana_gtk_clock_set_property; object_class->dispose = jana_gtk_clock_dispose; object_class->finalize = jana_gtk_clock_finalize; widget_class->expose_event = jana_gtk_clock_expose_event; widget_class->size_allocate = jana_gtk_clock_size_allocate; widget_class->style_set = jana_gtk_clock_style_set; widget_class->map = jana_gtk_clock_map; widget_class->unmap = jana_gtk_clock_unmap; widget_class->enter_notify_event = jana_gtk_clock_enter_notify_event; widget_class->leave_notify_event = jana_gtk_clock_leave_notify_event; widget_class->button_press_event = jana_gtk_clock_button_press_event; widget_class->button_release_event = jana_gtk_clock_button_release_event; g_object_class_install_property ( object_class, PROP_TIME, g_param_spec_object ( "time", "Time", "The JanaTime the clock will show.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DIGITAL, g_param_spec_boolean ( "digital", "Digital", "Whether to show a digital clock, as opposed to an " "analogue clock.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SHOW_SECONDS, g_param_spec_boolean ( "show_seconds", "Show seconds", "Whether to show seconds on the clock face.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_BUFFER_TIME, g_param_spec_boolean ( "buffer_time", "Buffer time", "Whether to double-buffer the time. Set this to " "%TRUE if you don't expect to change the time " "frequently.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_SHADOW, g_param_spec_boolean ( "draw_shadow", "Draw shadow", "Whether to draw a shadow underneath the clock.", FALSE, G_PARAM_READWRITE)); signals[RENDER_START] = g_signal_new ("render_start", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkClockClass, render_start), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[RENDER_STOP] = g_signal_new ("render_stop", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkClockClass, render_stop), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CLICKED] = g_signal_new ("clicked", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkClockClass, clicked), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void jana_gtk_clock_init (JanaGtkClock *self) { if (!g_thread_supported ()) g_thread_init (NULL); gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); gtk_event_box_set_visible_window (GTK_EVENT_BOX (self), FALSE); } GtkWidget * jana_gtk_clock_new (void) { return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_CLOCK, NULL)); } void jana_gtk_clock_set_time (JanaGtkClock *self, JanaTime *time) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (time) priv->time = jana_time_duplicate (time); if (priv->buffer_time) refresh_buffer (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } JanaTime * jana_gtk_clock_get_time (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); return priv->time ? jana_time_duplicate (priv->time) : NULL; } void jana_gtk_clock_set_digital (JanaGtkClock *self, gboolean digital) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->digital != digital) { priv->digital = digital; refresh_buffer (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } } gboolean jana_gtk_clock_get_digital (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); return priv->digital; } void jana_gtk_clock_set_show_seconds (JanaGtkClock *self, gboolean show_seconds) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->show_seconds != show_seconds) { priv->show_seconds = show_seconds; if (priv->buffer_time) refresh_buffer (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } } gboolean jana_gtk_clock_get_show_seconds (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); return priv->show_seconds; } void jana_gtk_clock_set_buffer_time (JanaGtkClock *self, gboolean buffer_time) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->buffer_time != buffer_time) { priv->buffer_time = buffer_time; refresh_buffer (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } } gboolean jana_gtk_clock_get_buffer_time (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); return priv->buffer_time; } void jana_gtk_clock_set_draw_shadow (JanaGtkClock *self, gboolean draw_shadow) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); if (priv->draw_shadow != draw_shadow) { priv->draw_shadow = draw_shadow; refresh_buffer (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } } gboolean jana_gtk_clock_get_draw_shadow (JanaGtkClock *self) { JanaGtkClockPrivate *priv = CLOCK_PRIVATE (self); return priv->draw_shadow; } #ifdef HAVE_GLADE /* The following is a nasty hack to get the widget to display correctly in * Glade-3. */ static void placeholder_realize_cb (GtkWidget *widget) { GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW); if (widget->window) g_object_unref (widget->window); widget->window = g_object_ref (gtk_widget_get_parent (widget)->window); gtk_widget_queue_draw (gtk_widget_get_parent (widget)); } static void jana_gtk_clock_glade_add_cb (GtkContainer *container, GtkWidget *widget, gpointer user_data) { if (!GLADE_IS_PLACEHOLDER (widget)) return; g_signal_connect_after (widget, "realize", G_CALLBACK (placeholder_realize_cb), NULL); if (GTK_WIDGET_REALIZED (widget)) placeholder_realize_cb (widget); } static void jana_gtk_clock_glade_remove_cb (GtkContainer *container, GtkWidget *widget, gpointer user_data) { if (!GLADE_IS_PLACEHOLDER (widget)) return; g_signal_handlers_disconnect_by_func ( widget, placeholder_realize_cb, NULL); } void jana_gtk_clock_glade_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GList *children; g_return_if_fail (GTK_IS_CONTAINER (object)); g_signal_connect (object, "add", G_CALLBACK (jana_gtk_clock_glade_add_cb), NULL); g_signal_connect (object, "remove", G_CALLBACK (jana_gtk_clock_glade_remove_cb), NULL); if (reason == GLADE_CREATE_USER) { GtkContainer *container = GTK_CONTAINER (object); children = gtk_container_get_children (container); if (!children) gtk_container_add (container, glade_placeholder_new ()); else g_list_free (children); } } #endif jana/libjana-gtk/jana-gtk-date-time.c0000644000175000017500000007757611327631152017620 0ustar paulliupaulliu #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_GLADE #include #endif #include #include #include "jana-gtk-date-time.h" #include G_DEFINE_TYPE (JanaGtkDateTime, jana_gtk_date_time, GTK_TYPE_VBOX) #define DATE_TIME_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_DATE_TIME, \ JanaGtkDateTimePrivate)) typedef struct _JanaGtkDateTimePrivate JanaGtkDateTimePrivate; typedef enum { JANA_GTK_DATE_TIME_DMY, JANA_GTK_DATE_TIME_MDY, JANA_GTK_DATE_TIME_YMD, } JanaGtkDateTimeEntryFormat; struct _JanaGtkDateTimePrivate { JanaTime *time; GtkWidget *label; GtkWidget *edit_vbox; GtkWidget *time_header; GtkWidget *time_table; GtkWidget *hour_entry; GtkWidget *minute_entry; GtkWidget *day_entry; GtkWidget *month_entry; GtkWidget *year_entry; gboolean editable; JanaGtkDateTimeEntryFormat format; gint timeout; gint fast_timeout; gint repeat; }; enum { PROP_TIME = 1, PROP_EDITABLE, PROP_ENTRY_FORMAT, PROP_TIMEOUT, PROP_FAST_TIMEOUT, PROP_REPEAT, }; enum { CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void refresh (JanaGtkDateTime *self); static void adjust_entry (GtkEntry *entry, gint direction) { gint min, max; gchar *new_text; const gchar *text = gtk_entry_get_text (entry); gint value = atoi (text); min = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "min")); max = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "max")); value += direction; if (value > max) value = min; if (value < min) value = max; new_text = g_strdup_printf ("%02d", value); gtk_entry_set_text (entry, new_text); g_free (new_text); } static void activate_button (GtkButton *button) { GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (button), "entry")); gint direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "direction")); adjust_entry (entry, direction); } static gboolean button_repeat_cb (GtkButton *button) { activate_button (button); return TRUE; } static gboolean button_start_fast_repeat_cb (GtkButton *button) { guint timeout; JanaGtkDateTime *self = (JanaGtkDateTime *)g_object_get_data ( G_OBJECT (button), "self"); JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); activate_button (button); timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "source")); g_source_remove (timeout); timeout = g_timeout_add (500 / priv->repeat, (GSourceFunc) button_repeat_cb, button); g_object_set_data (G_OBJECT (button), "source", GUINT_TO_POINTER (timeout)); g_object_set_data (G_OBJECT (button), "fast-source", GUINT_TO_POINTER (0)); return FALSE; } static gboolean button_start_repeat_cb (GtkButton *button) { guint timeout; JanaGtkDateTime *self = (JanaGtkDateTime *)g_object_get_data ( G_OBJECT (button), "self"); JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); activate_button (button); timeout = g_timeout_add (1000 / priv->repeat, (GSourceFunc) button_repeat_cb, button); g_object_set_data (G_OBJECT (button), "source", GUINT_TO_POINTER (timeout)); timeout = g_timeout_add (priv->fast_timeout, (GSourceFunc) button_start_fast_repeat_cb, button); g_object_set_data (G_OBJECT (button), "fast-source", GUINT_TO_POINTER (timeout)); return FALSE; } static void button_pressed_cb (GtkButton *button, JanaGtkDateTime *self) { guint timeout; activate_button (button); JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); timeout = g_timeout_add (priv->timeout, (GSourceFunc) button_start_repeat_cb, button); g_object_set_data (G_OBJECT (button), "source", GUINT_TO_POINTER (timeout)); } static void button_released_cb (GtkButton *button, JanaGtkDateTime *self) { guint timeout; timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "source")); if (timeout) { g_source_remove (timeout); g_object_set_data (G_OBJECT (button), "source", GUINT_TO_POINTER (0)); } timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "fast-source")); if (timeout) { g_source_remove (timeout); g_object_set_data (G_OBJECT (button), "fast-source", GUINT_TO_POINTER (0)); } } void insert_text_cb (GtkEditable *entry, gchar *new_text, gint new_text_length, gint *position, JanaGtkDateTime *self) { gint i; gchar *c; for (i = 0, c = new_text; c; c = g_utf8_find_next_char (c, (new_text_length != -1) ? (new_text + new_text_length) : NULL)) { if (*c < '0' || *c > '9') { g_signal_stop_emission (entry, g_signal_lookup ( "insert-text", GTK_TYPE_EDITABLE), 0); gdk_beep (); break; } } } static void minute_entry_changed_cb (GtkEntry *entry, JanaGtkDateTime *self) { gint value; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gchar *text = g_strstrip (g_strdup (gtk_entry_get_text (entry))); if ((!text) || (!priv->time) || (strcmp (text, "") == 0)) { g_free (text); return; } value = atoi (text); g_free (text); if (value != jana_time_get_minutes (priv->time)) { jana_time_set_minutes (priv->time, value); g_signal_emit (self, signals[CHANGED], 0); refresh (self); } } static void hour_entry_changed_cb (GtkEntry *entry, JanaGtkDateTime *self) { gint value; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gchar *text = g_strstrip (g_strdup (gtk_entry_get_text (entry))); if ((!text) || (!priv->time) || (strcmp (text, "") == 0)) { g_free (text); return; } value = atoi (text); g_free (text); if (value != jana_time_get_hours (priv->time)) { jana_time_set_hours (priv->time, value); g_signal_emit (self, signals[CHANGED], 0); refresh (self); } } static void day_entry_changed_cb (GtkEntry *entry, JanaGtkDateTime *self) { gint value; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gchar *text = g_strstrip (g_strdup (gtk_entry_get_text (entry))); if ((!text) || (!priv->time) || (strcmp (text, "") == 0)) { g_free (text); return; } value = atoi (text); g_free (text); if (value != jana_time_get_day (priv->time)) { jana_time_set_day (priv->time, value); g_signal_emit (self, signals[CHANGED], 0); refresh (self); } } static void month_entry_changed_cb (GtkEntry *entry, JanaGtkDateTime *self) { gint value; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gchar *text = g_strstrip (g_strdup (gtk_entry_get_text (entry))); if ((!text) || (!priv->time) || (strcmp (text, "") == 0)) { g_free (text); return; } value = atoi (text); g_free (text); if (value != jana_time_get_month (priv->time)) { jana_time_set_month (priv->time, value); /* Update max range of day entry */ g_object_set_data (G_OBJECT (priv->day_entry), "max", GINT_TO_POINTER ((gint)jana_utils_time_days_in_month ( jana_time_get_year (priv->time), jana_time_get_month (priv->time)))); g_signal_emit (self, signals[CHANGED], 0); refresh (self); } } static void year_entry_changed_cb (GtkEntry *entry, JanaGtkDateTime *self) { gint value; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gchar *text = g_strstrip (g_strdup (gtk_entry_get_text (entry))); if ((!text) || (!priv->time) || (strcmp (text, "") == 0)) { g_free (text); return; } value = atoi (text); g_free (text); if (value != jana_time_get_year (priv->time)) { jana_time_set_year (priv->time, value); /* Update max range of day entry */ g_object_set_data (G_OBJECT (priv->day_entry), "max", GINT_TO_POINTER ((gint)jana_utils_time_days_in_month ( jana_time_get_year (priv->time), jana_time_get_month (priv->time)))); g_signal_emit (self, signals[CHANGED], 0); refresh (self); } } static void create_edit_page (JanaGtkDateTime *self) { const gchar *date_separator_text = "/"; GtkWidget *date_table, *align, *header; GtkWidget *time_separator_label, *date_separator_label; GtkWidget *hour_up_button, *hour_up, *hour_down_button, *hour_down, *minute_up_button, *minute_up, *minute_down_button, *minute_down, *day_up_button, *day_up, *day_down_button, *day_down, *month_up_button, *month_up, *month_down_button, *month_down, *year_up_button, *year_up, *year_down_button, *year_down; GtkWidget *uleft, *umiddle, *uright, *left, *middle, *right, *lleft, *lmiddle, *lright; /* Taken and modified from Dates. Sorry for the awful quality :( */ JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); priv->edit_vbox = gtk_vbox_new (FALSE, 6); gtk_box_pack_end (GTK_BOX (self), priv->edit_vbox, FALSE, TRUE, 0); gtk_widget_set_no_show_all (priv->edit_vbox, TRUE); /* Time editing widgets */ /* Have time take up 2/3 of the space that date does, otherwise it * looks rubbish. */ align = gtk_alignment_new (0.5, 0.5, 0.66, 1); gtk_widget_show (align); priv->time_table = gtk_table_new (3, 3, FALSE); gtk_widget_show (priv->time_table); gtk_table_set_col_spacings (GTK_TABLE (priv->time_table), 6); priv->time_header = gtk_label_new ("Time"); gtk_widget_show (priv->time_header); gtk_container_add (GTK_CONTAINER (align), priv->time_table); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), priv->time_header, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), align, FALSE, TRUE, 0); /* Hours / minutes separator */ time_separator_label = gtk_label_new (":"); gtk_widget_show (time_separator_label); gtk_table_attach (GTK_TABLE (priv->time_table), time_separator_label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); /* Minute entry */ priv->minute_entry = gtk_entry_new (); gtk_entry_set_max_length (GTK_ENTRY (priv->minute_entry), 2); gtk_entry_set_activates_default (GTK_ENTRY (priv->minute_entry), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (priv->minute_entry), 1); gtk_widget_show (priv->minute_entry); gtk_table_attach (GTK_TABLE (priv->time_table), priv->minute_entry, 2, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); /* Hour increment button + arrow */ hour_up_button = gtk_button_new (); gtk_widget_show (hour_up_button); gtk_table_attach (GTK_TABLE (priv->time_table), hour_up_button, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); hour_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show (hour_up); gtk_container_add (GTK_CONTAINER (hour_up_button), hour_up); /* Hour decrement button + arrow */ hour_down_button = gtk_button_new (); gtk_widget_show (hour_down_button); gtk_table_attach (GTK_TABLE (priv->time_table), hour_down_button, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); hour_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (hour_down); gtk_container_add (GTK_CONTAINER (hour_down_button), hour_down); /* Minute increment button + arrow */ minute_up_button = gtk_button_new (); gtk_widget_show (minute_up_button); gtk_table_attach (GTK_TABLE (priv->time_table), minute_up_button, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); minute_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show (minute_up); gtk_container_add (GTK_CONTAINER (minute_up_button), minute_up); /* Left digit minute decrement button + arrow */ minute_down_button = gtk_button_new (); gtk_widget_show (minute_down_button); gtk_table_attach (GTK_TABLE (priv->time_table), minute_down_button, 2, 3, 2, 3, GTK_FILL, 0, 0, 0); minute_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (minute_down); gtk_container_add (GTK_CONTAINER (minute_down_button), minute_down); /* Hour entry */ priv->hour_entry = gtk_entry_new (); gtk_entry_set_max_length (GTK_ENTRY (priv->hour_entry), 2); gtk_entry_set_activates_default (GTK_ENTRY (priv->hour_entry), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (priv->hour_entry), 2); gtk_widget_show (priv->hour_entry); gtk_table_attach (GTK_TABLE (priv->time_table), priv->hour_entry, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); /* Date editing widgets */ date_table = gtk_table_new (3, 5, FALSE); gtk_widget_show (date_table); gtk_table_set_col_spacings (GTK_TABLE (date_table), 6); header = gtk_label_new ("Date"); gtk_widget_show (header); gtk_box_pack_start (GTK_BOX (priv->edit_vbox), header, FALSE, TRUE, 0); gtk_box_pack_end (GTK_BOX (priv->edit_vbox), date_table, FALSE, TRUE, 0); /* Separators */ date_separator_label = gtk_label_new (date_separator_text); gtk_widget_show (date_separator_label); gtk_table_attach (GTK_TABLE (date_table), date_separator_label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); date_separator_label = gtk_label_new (date_separator_text); gtk_widget_show (date_separator_label); gtk_table_attach (GTK_TABLE (date_table), date_separator_label, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0); /* Day increment button + arrow */ day_up_button = gtk_button_new (); gtk_widget_show (day_up_button); day_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show (day_up); gtk_container_add (GTK_CONTAINER (day_up_button), day_up); /* Day decrement button + arrow */ day_down_button = gtk_button_new (); gtk_widget_show (day_down_button); day_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (day_down); gtk_container_add (GTK_CONTAINER (day_down_button), day_down); /* Month increment button + arrow */ month_up_button = gtk_button_new (); gtk_widget_show (month_up_button); month_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show (month_up); gtk_container_add (GTK_CONTAINER (month_up_button), month_up); /* Month decrement button + arrow */ month_down_button = gtk_button_new (); gtk_widget_show (month_down_button); month_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (month_down); gtk_container_add (GTK_CONTAINER (month_down_button), month_down); /* Year increment button + arrow */ year_up_button = gtk_button_new (); gtk_widget_show (year_up_button); year_up = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show (year_up); gtk_container_add (GTK_CONTAINER (year_up_button), year_up); /* Year decrement button + arrow */ year_down_button = gtk_button_new (); gtk_widget_show (year_down_button); year_down = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (year_down); gtk_container_add (GTK_CONTAINER (year_down_button), year_down); /* Day entry */ priv->day_entry = gtk_entry_new (); gtk_entry_set_max_length (GTK_ENTRY (priv->day_entry), 2); gtk_entry_set_activates_default (GTK_ENTRY (priv->day_entry), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (priv->day_entry), 2); gtk_widget_show (priv->day_entry); /* Month entry */ priv->month_entry = gtk_entry_new (); gtk_entry_set_max_length (GTK_ENTRY (priv->month_entry), 2); gtk_entry_set_activates_default (GTK_ENTRY (priv->month_entry), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (priv->month_entry), 2); gtk_widget_show (priv->month_entry); /* Year entry */ priv->year_entry = gtk_entry_new (); gtk_entry_set_max_length (GTK_ENTRY (priv->year_entry), 4); gtk_entry_set_activates_default (GTK_ENTRY (priv->year_entry), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (priv->year_entry), 4); gtk_widget_show (priv->year_entry); switch (priv->format) { case JANA_GTK_DATE_TIME_MDY : left = priv->month_entry; middle = priv->day_entry; right = priv->year_entry; uleft = month_up_button; umiddle = day_up_button; uright = year_up_button; lleft = month_down_button; lmiddle = day_down_button; lright = year_down_button; break; case JANA_GTK_DATE_TIME_YMD : left = priv->year_entry; middle = priv->month_entry; right = priv->day_entry; uleft = year_up_button; umiddle = month_up_button; uright = day_up_button; lleft = year_down_button; lmiddle = month_down_button; lright = day_down_button; break; case JANA_GTK_DATE_TIME_DMY : default : left = priv->day_entry; middle = priv->month_entry; right = priv->year_entry; uleft = day_up_button; umiddle = month_up_button; uright = year_up_button; lleft = day_down_button; lmiddle = month_down_button; lright = year_down_button; break; } gtk_table_attach (GTK_TABLE (date_table), uleft, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), umiddle, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), uright, 4, 5, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), left, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), middle, 2, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), right, 4, 5, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), lleft, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), lmiddle, 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (date_table), lright, 4, 5, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); /* Sort out signals */ g_object_set_data (G_OBJECT (hour_up_button), "self", self); g_object_set_data (G_OBJECT (hour_up_button), "direction", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (hour_up_button), "entry", priv->hour_entry); g_object_set_data (G_OBJECT (hour_down_button), "self", self); g_object_set_data (G_OBJECT (hour_down_button), "direction", GINT_TO_POINTER (-1)); g_object_set_data (G_OBJECT (hour_down_button), "entry", priv->hour_entry); g_object_set_data (G_OBJECT (minute_up_button), "self", self); g_object_set_data (G_OBJECT (minute_up_button), "direction", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (minute_up_button), "entry", priv->minute_entry); g_object_set_data (G_OBJECT (minute_down_button), "self", self); g_object_set_data (G_OBJECT (minute_down_button), "direction", GINT_TO_POINTER (-1)); g_object_set_data (G_OBJECT (minute_down_button), "entry", priv->minute_entry); g_object_set_data (G_OBJECT (day_up_button), "self", self); g_object_set_data (G_OBJECT (day_up_button), "direction", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (day_up_button), "entry", priv->day_entry); g_object_set_data (G_OBJECT (day_down_button), "self", self); g_object_set_data (G_OBJECT (day_down_button), "direction", GINT_TO_POINTER (-1)); g_object_set_data (G_OBJECT (day_down_button), "entry", priv->day_entry); g_object_set_data (G_OBJECT (month_up_button), "self", self); g_object_set_data (G_OBJECT (month_up_button), "direction", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (month_up_button), "entry", priv->month_entry); g_object_set_data (G_OBJECT (month_down_button), "self", self); g_object_set_data (G_OBJECT (month_down_button), "direction", GINT_TO_POINTER (-1)); g_object_set_data (G_OBJECT (month_down_button), "entry", priv->month_entry); g_object_set_data (G_OBJECT (year_up_button), "self", self); g_object_set_data (G_OBJECT (year_up_button), "direction", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (year_up_button), "entry", priv->year_entry); g_object_set_data (G_OBJECT (year_down_button), "self", self); g_object_set_data (G_OBJECT (year_down_button), "direction", GINT_TO_POINTER (-1)); g_object_set_data (G_OBJECT (year_down_button), "entry", priv->year_entry); g_object_set_data (G_OBJECT (priv->hour_entry), "max", GINT_TO_POINTER (23)); g_object_set_data (G_OBJECT (priv->minute_entry), "max", GINT_TO_POINTER (59)); g_object_set_data (G_OBJECT (priv->day_entry), "min", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (priv->day_entry), "max", GINT_TO_POINTER (31)); g_object_set_data (G_OBJECT (priv->month_entry), "min", GINT_TO_POINTER (1)); g_object_set_data (G_OBJECT (priv->month_entry), "max", GINT_TO_POINTER (12)); g_object_set_data (G_OBJECT (priv->year_entry), "min", GINT_TO_POINTER (1900)); g_object_set_data (G_OBJECT (priv->year_entry), "max", GINT_TO_POINTER (G_MAXUINT16)); g_signal_connect (hour_up_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (hour_down_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (minute_up_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (minute_down_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (day_up_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (day_down_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (month_up_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (month_down_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (year_up_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (year_down_button, "pressed", G_CALLBACK (button_pressed_cb), self); g_signal_connect (hour_up_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (hour_down_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (minute_up_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (minute_down_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (day_up_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (day_down_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (month_up_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (month_down_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (year_up_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (year_down_button, "released", G_CALLBACK (button_released_cb), self); g_signal_connect (priv->hour_entry, "insert-text", G_CALLBACK (insert_text_cb), self); g_signal_connect (priv->minute_entry, "insert-text", G_CALLBACK (insert_text_cb), self); g_signal_connect (priv->day_entry, "insert-text", G_CALLBACK (insert_text_cb), self); g_signal_connect (priv->month_entry, "insert-text", G_CALLBACK (insert_text_cb), self); g_signal_connect (priv->year_entry, "insert-text", G_CALLBACK (insert_text_cb), self); g_signal_connect (priv->minute_entry, "changed", G_CALLBACK (minute_entry_changed_cb), self); g_signal_connect (priv->hour_entry, "changed", G_CALLBACK (hour_entry_changed_cb), self); g_signal_connect (priv->day_entry, "changed", G_CALLBACK (day_entry_changed_cb), self); g_signal_connect (priv->month_entry, "changed", G_CALLBACK (month_entry_changed_cb), self); g_signal_connect (priv->year_entry, "changed", G_CALLBACK (year_entry_changed_cb), self); } static void refresh (JanaGtkDateTime *self) { gchar *text; JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); switch (priv->format) { case JANA_GTK_DATE_TIME_MDY : if (jana_time_get_isdate (priv->time)) text = g_strdup_printf ("%02d/%02d/%04d", jana_time_get_month (priv->time), jana_time_get_day (priv->time), jana_time_get_year (priv->time)); else text = g_strdup_printf ("%02d:%02d %02d/%02d/%04d", jana_time_get_hours (priv->time), jana_time_get_minutes (priv->time), jana_time_get_month (priv->time), jana_time_get_day (priv->time), jana_time_get_year (priv->time)); break; case JANA_GTK_DATE_TIME_YMD : if (jana_time_get_isdate (priv->time)) text = g_strdup_printf ("%04d/%02d/%02d", jana_time_get_year (priv->time), jana_time_get_month (priv->time), jana_time_get_day (priv->time)); else text = g_strdup_printf ("%02d:%02d %04d/%02d/%02d", jana_time_get_hours (priv->time), jana_time_get_minutes (priv->time), jana_time_get_year (priv->time), jana_time_get_month (priv->time), jana_time_get_day (priv->time)); break; case JANA_GTK_DATE_TIME_DMY : default : if (jana_time_get_isdate (priv->time)) text = g_strdup_printf ("%02d/%02d/%04d", jana_time_get_day (priv->time), jana_time_get_month (priv->time), jana_time_get_year (priv->time)); else text = g_strdup_printf ("%02d:%02d %02d/%02d/%04d", jana_time_get_hours (priv->time), jana_time_get_minutes (priv->time), jana_time_get_day (priv->time), jana_time_get_month (priv->time), jana_time_get_year (priv->time)); break; } gtk_label_set_text (GTK_LABEL (priv->label), text); g_free (text); if (!priv->hour_entry) return; if (!jana_time_get_isdate (priv->time)) { text = g_strdup_printf ( "%02d", jana_time_get_hours (priv->time)); gtk_entry_set_text (GTK_ENTRY (priv->hour_entry), text); g_free (text); text = g_strdup_printf ( "%02d", jana_time_get_minutes (priv->time)); gtk_entry_set_text (GTK_ENTRY (priv->minute_entry), text); g_free (text); gtk_widget_show (priv->time_header); gtk_widget_show (priv->time_table); } else { gtk_widget_hide (priv->time_header); gtk_widget_hide (priv->time_table); } text = g_strdup_printf ("%02d", jana_time_get_day (priv->time)); gtk_entry_set_text (GTK_ENTRY (priv->day_entry), text); g_free (text); text = g_strdup_printf ("%02d", jana_time_get_month (priv->time)); gtk_entry_set_text (GTK_ENTRY (priv->month_entry), text); g_free (text); text = g_strdup_printf ("%04d", jana_time_get_year (priv->time)); gtk_entry_set_text (GTK_ENTRY (priv->year_entry), text); g_free (text); } static void clear (JanaGtkDateTime *self) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); gtk_label_set_text (GTK_LABEL (priv->label), ""); if (!priv->hour_entry) return; gtk_entry_set_text (GTK_ENTRY (priv->hour_entry), "00"); gtk_entry_set_text (GTK_ENTRY (priv->minute_entry), "00"); gtk_entry_set_text (GTK_ENTRY (priv->day_entry), "01"); gtk_entry_set_text (GTK_ENTRY (priv->month_entry), "01"); /* TODO: Maybe set today's year rather than leaving it? */ /*gtk_entry_set_text (GTK_ENTRY (priv->year_entry), "");*/ } static void jana_gtk_date_time_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (object); switch (property_id) { case PROP_TIME : if (priv->time) g_value_take_object (value, jana_time_duplicate (priv->time)); break; case PROP_EDITABLE : g_value_set_boolean (value, priv->editable); break; case PROP_ENTRY_FORMAT : g_value_set_int (value, priv->format); break; case PROP_TIMEOUT : g_value_set_int (value, priv->timeout); break; case PROP_FAST_TIMEOUT : g_value_set_int (value, priv->fast_timeout); break; case PROP_REPEAT : g_value_set_int (value, priv->repeat); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_date_time_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (object); switch (property_id) { case PROP_TIME : jana_gtk_date_time_set_time (JANA_GTK_DATE_TIME (object), g_value_get_object (value)); break; case PROP_EDITABLE : jana_gtk_date_time_set_editable (JANA_GTK_DATE_TIME (object), g_value_get_boolean (value)); break; case PROP_ENTRY_FORMAT : priv->format = g_value_get_int (value); if (priv->time) refresh (JANA_GTK_DATE_TIME (object)); break; case PROP_TIMEOUT : priv->timeout = g_value_get_int (value); break; case PROP_FAST_TIMEOUT : priv->fast_timeout = g_value_get_int (value); break; case PROP_REPEAT : priv->repeat = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_date_time_dispose (GObject *object) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (object); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; } if (G_OBJECT_CLASS (jana_gtk_date_time_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_date_time_parent_class)-> dispose (object); } static void jana_gtk_date_time_finalize (GObject *object) { G_OBJECT_CLASS (jana_gtk_date_time_parent_class)->finalize (object); } static GObject * jana_gtk_date_time_constructor (GType type, guint n_properties, GObjectConstructParam *properties) { GObjectClass *gobject_class; GObject *obj; gobject_class = G_OBJECT_CLASS (jana_gtk_date_time_parent_class); obj = gobject_class->constructor (type, n_properties, properties); create_edit_page (JANA_GTK_DATE_TIME (obj)); return obj; } static void jana_gtk_date_time_class_init (JanaGtkDateTimeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkDateTimePrivate)); object_class->constructor = jana_gtk_date_time_constructor; object_class->get_property = jana_gtk_date_time_get_property; object_class->set_property = jana_gtk_date_time_set_property; object_class->dispose = jana_gtk_date_time_dispose; object_class->finalize = jana_gtk_date_time_finalize; g_object_class_install_property ( object_class, PROP_TIME, g_param_spec_object ( "time", "Time", "The JanaTime represented by this widget.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_EDITABLE, g_param_spec_boolean ( "editable", "Editable", "Whether the JanaTime can be edited or not.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_ENTRY_FORMAT, g_param_spec_int ( "entry-format", "Entry format", "The order in which day, month and year are shown.", JANA_GTK_DATE_TIME_DMY, JANA_GTK_DATE_TIME_YMD, JANA_GTK_DATE_TIME_DMY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_TIMEOUT, g_param_spec_int ( "timeout", "Key-repeat time-out", "The amount of milliseconds before key-repeat starts.", 0, G_MAXINT, 500, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_FAST_TIMEOUT, g_param_spec_int ( "fast-timeout", "Secondary key-repeat time-out", "The amount of milliseconds after key-repeat starts, " "before the key-repeat rate is doubled.", 0, G_MAXINT, 1000, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_REPEAT, g_param_spec_int ( "repeat", "Key-repeat", "The amount of times per second the key will be " "activated after pressing, after the initial timeout.", 0, G_MAXINT, 8, G_PARAM_READWRITE)); signals[CHANGED] = g_signal_new ("changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkDateTimeClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void jana_gtk_date_time_init (JanaGtkDateTime *self) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); priv->format = JANA_GTK_DATE_TIME_DMY; priv->timeout = 500; priv->fast_timeout = 1000; priv->repeat = 8; priv->label = gtk_label_new (NULL); gtk_widget_show (priv->label); gtk_box_pack_start (GTK_BOX (self), priv->label, FALSE, TRUE, 0); gtk_widget_set_no_show_all (priv->label, TRUE); } GtkWidget* jana_gtk_date_time_new (JanaTime *time) { /* TODO: Use locale to select correct date format */ return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_DATE_TIME, "entry-format", JANA_GTK_DATE_TIME_DMY, "time", time, NULL)); } void jana_gtk_date_time_set_editable (JanaGtkDateTime *self, gboolean editable) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); priv->editable = editable; if (priv->editable) { gtk_widget_hide (priv->label); gtk_widget_show (priv->edit_vbox); } else { gtk_widget_hide (priv->edit_vbox); gtk_widget_show (priv->label); } } gboolean jana_gtk_date_time_get_editable (JanaGtkDateTime *self) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); return priv->editable; } JanaTime * jana_gtk_date_time_get_time (JanaGtkDateTime *self) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); return priv->time ? jana_time_duplicate (priv->time) : NULL; } void jana_gtk_date_time_set_time (JanaGtkDateTime *self, JanaTime *time) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (self); if (priv->time) { g_object_unref (priv->time); priv->time = NULL; clear (self); } if (time) { priv->time = jana_time_duplicate (time); refresh (self); } g_signal_emit (self, signals[CHANGED], 0); } #ifdef HAVE_GLADE void jana_gtk_date_time_glade_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { JanaGtkDateTimePrivate *priv = DATE_TIME_PRIVATE (object); gtk_label_set_text (GTK_LABEL (priv->label), "Time display"); } #endif jana/libjana-gtk/jana-gtk-note-store.h0000644000175000017500000000472111327631152020031 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_NOTE_STORE_H #define _JANA_GTK_NOTE_STORE_H #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_NOTE_STORE jana_gtk_note_store_get_type() #define JANA_GTK_NOTE_STORE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_NOTE_STORE, JanaGtkNoteStore)) #define JANA_GTK_NOTE_STORE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_NOTE_STORE, JanaGtkNoteStoreClass)) #define JANA_GTK_IS_NOTE_STORE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_NOTE_STORE)) #define JANA_GTK_IS_NOTE_STORE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_NOTE_STORE)) #define JANA_GTK_NOTE_STORE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_NOTE_STORE, JanaGtkNoteStoreClass)) typedef struct { GtkListStore parent; } JanaGtkNoteStore; typedef struct { GtkListStoreClass parent_class; } JanaGtkNoteStoreClass; enum { JANA_GTK_NOTE_STORE_COL_UID, JANA_GTK_NOTE_STORE_COL_CATEGORIES, JANA_GTK_NOTE_STORE_COL_AUTHOR, JANA_GTK_NOTE_STORE_COL_RECIPIENT, JANA_GTK_NOTE_STORE_COL_BODY, JANA_GTK_NOTE_STORE_COL_CREATED, JANA_GTK_NOTE_STORE_COL_MODIFIED, JANA_GTK_NOTE_STORE_COL_LAST }; GType jana_gtk_note_store_get_type (void); GtkTreeModel * jana_gtk_note_store_new (void); GtkTreeModel * jana_gtk_note_store_new_full (JanaStoreView *view); void jana_gtk_note_store_set_view (JanaGtkNoteStore *store, JanaStoreView *view); JanaStoreView * jana_gtk_note_store_get_view (JanaGtkNoteStore *store); JanaStore * jana_gtk_note_store_get_store (JanaGtkNoteStore *store); G_END_DECLS #endif /* _JANA_GTK_NOTE_STORE_H */ jana/libjana-gtk/jana-gtk-clock.h0000644000175000017500000000520211327631152017020 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_CLOCK_H #define _JANA_GTK_CLOCK_H #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_CLOCK jana_gtk_clock_get_type() #define JANA_GTK_CLOCK(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_CLOCK, JanaGtkClock)) #define JANA_GTK_CLOCK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_CLOCK, JanaGtkClockClass)) #define JANA_GTK_IS_CLOCK(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_CLOCK)) #define JANA_GTK_IS_CLOCK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_CLOCK)) #define JANA_GTK_CLOCK_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_CLOCK, JanaGtkClockClass)) typedef struct { GtkEventBox parent; } JanaGtkClock; typedef struct { GtkEventBoxClass parent_class; /* Signals */ void (*render_start) (JanaGtkClock *self); void (*render_stop) (JanaGtkClock *self); void (*clicked) (JanaGtkClock *self, GdkEventButton *event); } JanaGtkClockClass; GType jana_gtk_clock_get_type (void); GtkWidget * jana_gtk_clock_new (void); void jana_gtk_clock_set_time (JanaGtkClock *self, JanaTime *time); JanaTime *jana_gtk_clock_get_time (JanaGtkClock *self); void jana_gtk_clock_set_digital (JanaGtkClock *self, gboolean digital); gboolean jana_gtk_clock_get_digital (JanaGtkClock *self); void jana_gtk_clock_set_show_seconds (JanaGtkClock *self, gboolean show_seconds); gboolean jana_gtk_clock_get_show_seconds (JanaGtkClock *self); void jana_gtk_clock_set_buffer_time (JanaGtkClock *self, gboolean buffer_time); gboolean jana_gtk_clock_get_buffer_time (JanaGtkClock *self); void jana_gtk_clock_set_draw_shadow (JanaGtkClock *self, gboolean draw_shadow); gboolean jana_gtk_clock_get_draw_shadow (JanaGtkClock *self); G_END_DECLS #endif /* _JANA_GTK_CLOCK_H */ jana/libjana-gtk/jana-gtk-world-map.h0000644000175000017500000000634411327631152017637 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_WORLD_MAP_H #define _JANA_GTK_WORLD_MAP_H #include #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_WORLD_MAP jana_gtk_world_map_get_type() #define JANA_GTK_WORLD_MAP(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_WORLD_MAP, JanaGtkWorldMap)) #define JANA_GTK_WORLD_MAP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_WORLD_MAP, JanaGtkWorldMapClass)) #define JANA_GTK_IS_WORLD_MAP(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_WORLD_MAP)) #define JANA_GTK_IS_WORLD_MAP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_WORLD_MAP)) #define JANA_GTK_WORLD_MAP_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_WORLD_MAP, JanaGtkWorldMapClass)) typedef struct { GtkEventBox parent; } JanaGtkWorldMap; typedef struct { GtkEventBoxClass parent_class; /* Signals */ void (*render_start) (JanaGtkWorldMap *self); void (*render_stop) (JanaGtkWorldMap *self); void (*clicked) (JanaGtkWorldMap *self, GdkEventButton *event); } JanaGtkWorldMapClass; GType jana_gtk_world_map_get_type (void); GtkWidget * jana_gtk_world_map_new (void); void jana_gtk_world_map_set_time (JanaGtkWorldMap *self, JanaTime *time); void jana_gtk_world_map_get_latlon (JanaGtkWorldMap *self, gint x, gint y, gdouble *lat, gdouble *lon); void jana_gtk_world_map_get_xy (JanaGtkWorldMap *self, gdouble lat, gdouble lon, gint *x, gint *y); JanaGtkWorldMapMarker * jana_gtk_world_map_add_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *mark, gdouble lat, gdouble lon); void jana_gtk_world_map_remove_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *mark); void jana_gtk_world_map_move_marker (JanaGtkWorldMap *self, JanaGtkWorldMapMarker *mark, gdouble lat, gdouble lon); GList * jana_gtk_world_map_get_markers (JanaGtkWorldMap *self); void jana_gtk_world_map_set_static (JanaGtkWorldMap *self, gboolean set_static); gboolean jana_gtk_world_map_get_static (JanaGtkWorldMap *self); void jana_gtk_world_map_set_width (JanaGtkWorldMap *self, gint width); gint jana_gtk_world_map_get_width (JanaGtkWorldMap *self); void jana_gtk_world_map_set_height (JanaGtkWorldMap *self, gint height); gint jana_gtk_world_map_get_height (JanaGtkWorldMap *self); G_END_DECLS #endif /* _JANA_GTK_WORLD_MAP_H */ jana/libjana-gtk/jana-gtk-day-view.h0000644000175000017500000001043711327631152017460 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _JANA_GTK_DAY_VIEW_H #define _JANA_GTK_DAY_VIEW_H #include #include #include #include G_BEGIN_DECLS #define JANA_GTK_TYPE_DAY_VIEW jana_gtk_day_view_get_type() #define JANA_GTK_DAY_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_GTK_TYPE_DAY_VIEW, JanaGtkDayView)) #define JANA_GTK_DAY_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ JANA_GTK_TYPE_DAY_VIEW, JanaGtkDayViewClass)) #define JANA_GTK_IS_DAY_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_GTK_TYPE_DAY_VIEW)) #define JANA_GTK_IS_DAY_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ JANA_GTK_TYPE_DAY_VIEW)) #define JANA_GTK_DAY_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ JANA_GTK_TYPE_DAY_VIEW, JanaGtkDayViewClass)) typedef struct { GtkEventBox parent; } JanaGtkDayView; typedef struct { GtkEventBoxClass parent_class; void (*set_scroll_adjustments) (JanaGtkDayView *self, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); /* Signals */ void (*selection_changed) (JanaGtkDayView *self, JanaDuration *range); void (*event_selected) (JanaGtkDayView *self, GtkTreeRowReference *event); void (*event_activated) (JanaGtkDayView *self, GtkTreeRowReference *event); } JanaGtkDayViewClass; enum { JANA_GTK_DAY_VIEW_COL_ROW, JANA_GTK_DAY_VIEW_COL_LAST }; GType jana_gtk_day_view_get_type (void); GtkWidget * jana_gtk_day_view_new (JanaDuration *range, guint cells); void jana_gtk_day_view_add_store (JanaGtkDayView *self, JanaGtkEventStore *store); void jana_gtk_day_view_remove_store (JanaGtkDayView *self, JanaGtkEventStore *store); void jana_gtk_day_view_scroll_to_cell (JanaGtkDayView *self, guint x, guint y); void jana_gtk_day_view_scroll_to_time (JanaGtkDayView *self, JanaTime *time); JanaGtkCellRendererEvent * jana_gtk_day_view_get_cell_renderer (JanaGtkDayView *self); JanaGtkCellRendererEvent * jana_gtk_day_view_get_24hr_cell_renderer(JanaGtkDayView *self); void jana_gtk_day_view_set_range (JanaGtkDayView *self, JanaDuration *range); JanaDuration * jana_gtk_day_view_get_range (JanaGtkDayView *self); void jana_gtk_day_view_set_cells (JanaGtkDayView *self, guint cells); guint jana_gtk_day_view_get_cells (JanaGtkDayView *self); void jana_gtk_day_view_set_spacing (JanaGtkDayView *self, guint spacing); guint jana_gtk_day_view_get_spacing (JanaGtkDayView *self); JanaDuration * jana_gtk_day_view_get_selection (JanaGtkDayView *self); void jana_gtk_day_view_set_selection (JanaGtkDayView *self, JanaDuration *selection); void jana_gtk_day_view_set_visible_ratio (JanaGtkDayView *self, gdouble xratio, gdouble yratio); void jana_gtk_day_view_get_visible_ratio (JanaGtkDayView *self, gdouble *xratio, gdouble *yratio); GtkTreeRowReference * jana_gtk_day_view_get_selected_event (JanaGtkDayView *self); void jana_gtk_day_view_set_selected_event (JanaGtkDayView *self, GtkTreeRowReference *row); void jana_gtk_day_view_set_visible_func (JanaGtkDayView *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data); void jana_gtk_day_view_refilter (JanaGtkDayView *self); void jana_gtk_day_view_set_highlighted_time (JanaGtkDayView *self, JanaTime *time); void jana_gtk_day_view_set_active_range (JanaGtkDayView *self, JanaDuration *range); G_END_DECLS #endif /* _JANA_GTK_DAY_VIEW_H */ jana/libjana-gtk/jana-gtk-day-view.c0000644000175000017500000021220711327631152017452 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include "jana-gtk-day-view.h" G_DEFINE_TYPE (JanaGtkDayView, jana_gtk_day_view, GTK_TYPE_EVENT_BOX) #define DAY_VIEW_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_DAY_VIEW, \ JanaGtkDayViewPrivate)) typedef struct _JanaGtkDayViewPrivate JanaGtkDayViewPrivate; struct _JanaGtkDayViewPrivate { GtkWidget *vbox; GtkWidget *alignment; GtkWidget *viewport; GtkWidget *layout; GtkWidget *alignment24hr; GtkWidget *viewport24hr; GtkWidget *layout24hr; GtkCellRenderer *event_renderer; GtkCellRenderer *event_renderer24hr; GtkAllocation allocation; PangoLayout **time_layouts; PangoLayout **day_layouts; PangoLayout *week_layout; guint col0_width; guint row0_height; JanaDuration *range; gint visible_days; gint cell_minutes; JanaTime *day; JanaDuration *selection; GtkTreeRowReference *selected_event; guint cells; gchar *style_hint; guint spacing; gdouble xratio; gdouble yratio; JanaDuration *active_range; JanaTime *highlighted_time; gint selection_start_x; gint selection_start_y; gint selection_end_x; gint selection_end_y; gint active_range_start_x; gint active_range_start_y; gint active_range_end_x; gint active_range_end_y; gint highlighted_time_x; gint highlighted_time_y; gdouble highlighted_time_pos; }; enum { PROP_RANGE = 1, PROP_SELECTION, PROP_SELECTED_EVENT, PROP_CELLS, PROP_SPACING, PROP_STYLE_HINT, PROP_RATIO_X, PROP_RATIO_Y, PROP_ACTIVE_RANGE, PROP_HIGHLIGHTED_TIME, }; enum { SELECTION_CHANGED, EVENT_SELECTED, EVENT_ACTIVATED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void relayout (JanaGtkDayView *self); static gboolean compare_selection (JanaGtkDayView *self, GtkTreeRowReference *row); static void set_alignments (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); gtk_alignment_set_padding (GTK_ALIGNMENT (priv->alignment), 0, 0, priv->col0_width, 0); gtk_alignment_set_padding (GTK_ALIGNMENT (priv->alignment24hr), 0, 0, priv->col0_width, 0); } static void create_layouts (JanaGtkDayView *self) { gint x, text_width, text_height; gchar week_string[4]; JanaTime *time, *end; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((!jana_duration_valid (priv->range)) || (priv->cells == 0)) return; /* Work out how many minutes there are per cell */ /* TODO: This is an extremely slow way of working * this out, but this isn't a speed critical * section of code. Resolve in the future. */ time = jana_time_duplicate (priv->range->start); end = jana_time_duplicate (time); jana_time_set_hours (end, jana_time_get_hours (priv->range->end)); jana_time_set_minutes (end, jana_time_get_minutes (priv->range->end)); if (jana_utils_time_compare (time, end, FALSE) >= 0) jana_time_set_day (end, jana_time_get_day (end) + 1); for (priv->cell_minutes = 0; jana_utils_time_compare (time, end, FALSE) < 0; jana_time_set_minutes (time, jana_time_get_minutes (time) + priv->cells), priv->cell_minutes ++) { if (jana_time_get_day (time) != jana_time_get_day (priv->range->start)) break; } g_object_unref (end); g_object_unref (time); priv->row0_height = 0; priv->day_layouts = g_slice_alloc ( sizeof (PangoLayout *) * priv->visible_days); time = jana_time_duplicate (priv->range->start); for (x = 0; x < priv->visible_days; x++) { GDateWeekday day; gchar day_markup[48]; gboolean active; /* Draw the highlighted day in bold */ if (priv->highlighted_time && (jana_utils_time_compare ( time, priv->highlighted_time, TRUE) == 0)) active = TRUE; else active = FALSE; day = jana_utils_time_day_of_week (time); snprintf (day_markup, 48, "%s%s\n%d/%d%s", active ? "" : "", jana_utils_ab_day (day - 1), jana_time_get_day (time), jana_time_get_month (time), active ? "" : ""); priv->day_layouts[x] = gtk_widget_create_pango_layout ( GTK_WIDGET (self), NULL); pango_layout_set_markup (priv->day_layouts[x], day_markup, -1); pango_layout_set_alignment ( priv->day_layouts[x], PANGO_ALIGN_CENTER); pango_layout_get_pixel_size ( priv->day_layouts[x], &text_width, &text_height); /* Set the height of the first row */ priv->row0_height = MAX (priv->row0_height, text_height + (priv->spacing * 2)); jana_time_set_day (time, jana_time_get_day (time) + 1); } g_object_unref (time); priv->col0_width = 0; priv->time_layouts = g_slice_alloc ( sizeof (PangoLayout *) * priv->cells); time = jana_time_duplicate (priv->range->start); for (x = 0; x < priv->cells; x++) { gchar time_string[6]; snprintf (time_string, 6, "%02d:%02d", jana_time_get_hours (time), jana_time_get_minutes (time)); priv->time_layouts[x] = gtk_widget_create_pango_layout ( GTK_WIDGET (self), time_string); pango_layout_get_pixel_size ( priv->time_layouts[x], &text_width, &text_height); /* Set the width of the first column */ priv->col0_width = MAX (priv->col0_width, text_width + (priv->spacing * 2)); jana_time_set_minutes (time, jana_time_get_minutes (time) + priv->cell_minutes); } g_object_unref (time); snprintf (week_string, 4, "W%02d", jana_utils_time_week_of_year (priv->range->start, TRUE)); priv->week_layout = gtk_widget_create_pango_layout ( GTK_WIDGET (self), NULL); pango_layout_set_text (priv->week_layout, week_string, -1); pango_layout_get_pixel_size (priv->week_layout, &text_width, &text_height); /* Check the widths/heights, just in case */ priv->col0_width = MAX (priv->col0_width, text_width); priv->row0_height = MAX (priv->row0_height, text_height); /* Set the alignments on the tree layouts */ set_alignments (self); } static void free_layouts (JanaGtkDayView *self) { gint i; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->day_layouts) { for (i = 0; i < priv->visible_days; i++) g_object_unref (priv->day_layouts[i]); g_slice_free1 (sizeof (PangoLayout*) * priv->visible_days, priv->day_layouts); priv->day_layouts = NULL; } if (priv->time_layouts) { for (i = 0; i < priv->cells; i++) g_object_unref (priv->time_layouts[i]); g_slice_free1 (sizeof (PangoLayout*) * priv->cells, priv->time_layouts); } if (priv->week_layout) { g_object_unref (priv->week_layout); priv->week_layout = NULL; } } static void time_to_cell_coords (JanaGtkDayView *self, JanaTime *time, gint *x, gint *y) { JanaTime *counter; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); counter = jana_time_duplicate (priv->range->start); jana_time_set_offset (counter, jana_time_get_offset (time)); /* Find out what column the time is */ if (x) { for (*x = 0; jana_utils_time_compare (counter, time, TRUE) < 0; jana_time_set_day (counter, jana_time_get_day (counter) + 1)) (*x)++; } if (y) { for (*y = 0; jana_utils_time_compare (counter, time, FALSE) < 0; jana_time_set_minutes (counter, jana_time_get_minutes (counter) + priv->cell_minutes)) (*y)++; } g_object_unref (counter); } static void jana_gtk_day_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (object); switch (property_id) { case PROP_RANGE : g_value_set_boxed (value, priv->range); break; case PROP_SPACING : g_value_set_uint (value, priv->spacing); break; case PROP_CELLS : g_value_set_uint (value, priv->cells); break; case PROP_STYLE_HINT : g_value_set_string (value, priv->style_hint); break; case PROP_SELECTION : g_value_set_boxed (value, priv->selection); break; case PROP_SELECTED_EVENT : g_value_set_boxed (value, priv->selected_event); break; case PROP_RATIO_X : g_value_set_double (value, priv->xratio); break; case PROP_RATIO_Y : g_value_set_double (value, priv->yratio); break; case PROP_ACTIVE_RANGE : g_value_set_boxed (value, priv->active_range); break; case PROP_HIGHLIGHTED_TIME : if (priv->highlighted_time) g_value_take_object (value, jana_time_duplicate (priv->highlighted_time)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_day_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (object); switch (property_id) { case PROP_RANGE : jana_gtk_day_view_set_range (JANA_GTK_DAY_VIEW (object), g_value_get_boxed (value)); break; case PROP_SPACING : jana_gtk_day_view_set_spacing (JANA_GTK_DAY_VIEW (object), g_value_get_uint (value)); break; case PROP_CELLS : jana_gtk_day_view_set_cells (JANA_GTK_DAY_VIEW (object), g_value_get_uint (value)); break; case PROP_STYLE_HINT : if (priv->style_hint) { g_free (priv->style_hint); priv->style_hint = NULL; } priv->style_hint = g_value_dup_string (value); gtk_widget_queue_draw (GTK_WIDGET (object)); break; case PROP_SELECTION : jana_gtk_day_view_set_selection (JANA_GTK_DAY_VIEW (object), g_value_get_boxed (value)); break; case PROP_SELECTED_EVENT : jana_gtk_day_view_set_selected_event ( JANA_GTK_DAY_VIEW (object), g_value_get_boxed (value)); break; case PROP_RATIO_X : priv->xratio = g_value_get_double (value); gtk_widget_queue_resize (GTK_WIDGET (object)); break; case PROP_RATIO_Y : priv->yratio = g_value_get_double (value); gtk_widget_queue_resize (GTK_WIDGET (object)); break; case PROP_HIGHLIGHTED_TIME : jana_gtk_day_view_set_highlighted_time ( JANA_GTK_DAY_VIEW (object), g_value_get_object (value)); break; case PROP_ACTIVE_RANGE : jana_gtk_day_view_set_active_range ( JANA_GTK_DAY_VIEW (object), g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_day_view_dispose (GObject *object) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (object); if (priv->event_renderer) { g_object_unref (priv->event_renderer); priv->event_renderer = NULL; } if (priv->event_renderer24hr) { g_object_unref (priv->event_renderer24hr); priv->event_renderer24hr = NULL; } if (G_OBJECT_CLASS (jana_gtk_day_view_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_day_view_parent_class)-> dispose (object); } static void jana_gtk_day_view_finalize (GObject *object) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (object); if (priv->range) { jana_duration_free (priv->range); priv->range = NULL; } if (priv->selection) { jana_duration_free (priv->selection); priv->selection = NULL; } if (priv->style_hint) { g_free (priv->style_hint); priv->style_hint = NULL; } if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } if (priv->active_range) { jana_duration_free (priv->active_range); priv->active_range = NULL; } free_layouts (JANA_GTK_DAY_VIEW (object)); G_OBJECT_CLASS (jana_gtk_day_view_parent_class)->finalize (object); } static void paint_box (GtkStyle *style, GdkWindow *window, GtkStateType state_type, GtkShadowType shadow_type, GdkRectangle *area, GtkWidget *widget, const gchar *detail, gint x, gint y, gint width, gint height) { gtk_paint_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); } static gboolean layout_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, JanaGtkDayView *self) { gint x, y, box_x, box_y, row_height, col_width, selection_direction; GtkStyle *style; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((!jana_duration_valid (priv->range)) || (priv->cells == 0)) return FALSE; /* Draw background */ /* Make a style with base as bg */ style = gtk_style_copy (widget->style); style->bg[GTK_STATE_NORMAL] = style->base[GTK_STATE_NORMAL]; style->bg[GTK_STATE_SELECTED] = style->base[GTK_STATE_SELECTED]; style = gtk_style_attach (style, widget->window); /* Draw event boxes */ row_height = widget->allocation.height / priv->cells; col_width = widget->allocation.width / priv->visible_days; if ((priv->selection_start_x < priv->selection_end_x) || ((priv->selection_start_x == priv->selection_end_x) && (priv->selection_start_y < priv->selection_end_y))) selection_direction = 1; else selection_direction = 0; box_x = 0; for (x = 0; x < priv->visible_days; x++) { box_y = 0; for (y = 0; y < priv->cells; y++) { GtkStateType state = GTK_STATE_NORMAL; if (priv->active_range) { if ((x < priv->active_range_start_x) || (x >= priv->active_range_end_x) || (y < priv->active_range_start_y) || (y >= priv->active_range_end_y)) state = GTK_STATE_INSENSITIVE; } if (priv->selection) { gint start_x, start_y, end_x, end_y; if (selection_direction) { start_x = priv->selection_start_x; start_y = priv->selection_start_y; end_x = priv->selection_end_x; end_y = priv->selection_end_y; } else { start_x = priv->selection_end_x; start_y = priv->selection_end_y - 1; end_x = priv->selection_start_x; end_y = priv->selection_start_y + 1; } /* These can be combined, but you end * up with a horrible unreadable mess. */ if ((x > start_x) && (x < end_x)) state = GTK_STATE_SELECTED; else if ((x == start_x) && (x < end_x) && (y >= start_y)) state = GTK_STATE_SELECTED; else if ((x == end_x) && (x > start_x) && (y < end_y)) state = GTK_STATE_SELECTED; else if ((x == start_x) && (x == end_x) && (y >= start_y) && (y < end_y)) state = GTK_STATE_SELECTED; } paint_box (style, widget->window, state, GTK_SHADOW_IN, &event->area, widget, priv->style_hint, box_x, box_y, col_width, row_height); if (priv->highlighted_time && (x == priv->highlighted_time_x) && (y == priv->highlighted_time_y)) { /* Draw time line */ gtk_paint_hline (style, widget->window, GTK_STATE_SELECTED, &event->area, widget, priv->style_hint, box_x, box_x + col_width, (gdouble)row_height * (gdouble)priv->cells * priv->highlighted_time_pos); } box_y += row_height; } box_x += col_width; } gtk_style_detach (style); return FALSE; } static gboolean layout24hr_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, JanaGtkDayView *self) { gint x, box_x, col_width, text_width, text_height; GtkStyle *dark_style; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((!jana_duration_valid (priv->range)) || (priv->cells == 0)) return FALSE; col_width = priv->layout->allocation.width / priv->visible_days; /* Draw headers */ /* Create darker style */ dark_style = gtk_style_copy (widget->style); dark_style->bg[GTK_STATE_NORMAL] = dark_style->bg[GTK_STATE_ACTIVE]; dark_style->fg[GTK_STATE_NORMAL] = dark_style->fg[GTK_STATE_ACTIVE]; dark_style = gtk_style_attach (dark_style, widget->window); /* Week/day headers */ for (x = 0, box_x = 0; x < priv->visible_days; x++) { PangoLayout *layout = priv->day_layouts[x]; pango_layout_get_pixel_size (layout, &text_width, &text_height); paint_box (dark_style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, &event->area, widget, priv->style_hint, box_x, 0, col_width, priv->layout24hr->allocation.height); gtk_paint_layout (dark_style, widget->window, GTK_STATE_NORMAL, FALSE, &event->area, widget, priv->style_hint, box_x + (col_width / 2) - (text_width / 2), (priv->row0_height / 2) - (text_height / 2), layout); box_x += col_width; } gtk_style_detach (dark_style); return FALSE; } static gboolean jana_gtk_day_view_expose_event (GtkWidget *widget, GdkEventExpose *event) { gint y, box_y, row_height, col_width, row_offset, text_width, text_height; GtkAdjustment *adjustment; GtkStyle *dark_style; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (widget); if ((!jana_duration_valid (priv->range)) || (priv->cells == 0)) return FALSE; row_height = priv->layout->allocation.height / priv->cells; col_width = priv->layout->allocation.width / priv->visible_days; /* Draw headers */ /* Create darker style */ dark_style = gtk_style_copy (widget->style); dark_style->bg[GTK_STATE_NORMAL] = dark_style->bg[GTK_STATE_ACTIVE]; dark_style->fg[GTK_STATE_NORMAL] = dark_style->fg[GTK_STATE_ACTIVE]; dark_style = gtk_style_attach (dark_style, widget->window); /* Calculate header offsets */ adjustment = gtk_viewport_get_vadjustment ( GTK_VIEWPORT (priv->viewport)); row_offset = (gint)(((adjustment->value - adjustment->lower) / (adjustment->upper - adjustment->lower)) * (gdouble)priv->layout->allocation.height); /* Time headers */ box_y = priv->layout24hr->allocation.height - row_offset; for (y = 0; y < priv->cells; y++) { PangoLayout *layout = priv->time_layouts[y]; pango_layout_get_pixel_size (layout, &text_width, &text_height); paint_box (dark_style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, &event->area, widget, priv->style_hint, 0, box_y, priv->col0_width, row_height); gtk_paint_layout (dark_style, widget->window, GTK_STATE_NORMAL, FALSE, &event->area, widget, priv->style_hint, (priv->col0_width / 2) - (text_width / 2), box_y + (row_height / 2) - (text_height / 2), layout); box_y += row_height; } /* Week */ paint_box (widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, &event->area, widget, priv->style_hint, 0, 0, priv->col0_width, priv->layout24hr->allocation.height); pango_layout_get_pixel_size (priv->week_layout, &text_width, &text_height); gtk_paint_layout (widget->style, widget->window, GTK_STATE_NORMAL, FALSE, &event->area, widget, priv->style_hint, (priv->col0_width / 2) - (text_width / 2), (priv->row0_height / 2) - (text_height / 2), priv->week_layout); gtk_style_detach (dark_style); return FALSE; } static void relayout (JanaGtkDayView *self) { JanaTime *time; GList *cell, *cells; gint cell_width, min_time, max_time, alloc_height, event_y, day, max_event_y; gfloat min_per_pixel; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((!jana_duration_valid (priv->range)) || (priv->cells == 0)) return; cell_width = priv->layout->allocation.width / priv->visible_days; min_time = (jana_time_get_hours (priv->range->start) * 60) + jana_time_get_minutes (priv->range->start); max_time = ((jana_time_get_hours (priv->range->end) ? jana_time_get_hours (priv->range->end) : 24) * 60) + jana_time_get_minutes (priv->range->end); /* TODO: Use integer math for this */ alloc_height = priv->layout->allocation.height - (priv->layout->allocation.height % priv->cells); min_per_pixel = (gfloat)alloc_height / (gfloat)(max_time - min_time); cells = jana_gtk_tree_layout_get_cells ( JANA_GTK_TREE_LAYOUT (priv->layout)); for (cell = g_list_last (cells); cell; cell = cell->prev) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaTime *start, *end, *time; gint day; /* Work out what day the cell is in */ model = gtk_tree_row_reference_get_model (info->row); path = gtk_tree_row_reference_get_path (info->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start, JANA_GTK_EVENT_STORE_COL_END, &end, -1); if (!start) { if (end) g_object_unref (end); continue; } if (!end) { end = jana_time_duplicate (start); jana_time_set_minutes ( end, jana_time_get_minutes (end) + 30); } /* Get to the correct day */ for (time = jana_time_duplicate (priv->range->start), day = 0; jana_utils_time_compare (time, start, TRUE) < 0; jana_time_set_day (time, jana_time_get_day (time) + 1), day ++); if (jana_utils_time_compare (time, start, TRUE) == 0) { GList *prev_cell; JanaGtkTreeLayoutCellInfo *ovl_info = NULL; gint x, y, width, height, minutes; x = (cell_width * day) + priv->spacing; width = cell_width - (priv->spacing * 2); minutes = (jana_time_get_hours (start) * 60) + jana_time_get_minutes (start); minutes -= min_time; y = min_per_pixel * minutes; minutes = (((jana_time_get_hours (end) || jana_time_get_minutes (end)) ? jana_time_get_hours (end) : 24) * 60) + jana_time_get_minutes (end); minutes -= min_time; height = (min_per_pixel * minutes) - y; if (y < 0) { height += y; y = 0; } if ((width <= 0) || (height <= 0) || (y > alloc_height)) { /* Hide off-screen events */ x = y = width = height = 0; } else if (cell->next) { /* Check if we've overlapped with any previous * events in this day. */ for (prev_cell = cell->next; prev_cell; prev_cell = prev_cell->next) { JanaGtkTreeLayoutCellInfo *prev_info = (JanaGtkTreeLayoutCellInfo *) prev_cell->data; /* Check if info is on a previous day */ if (prev_info->x < x) break; /* Check if event is hidden */ if ((prev_info->width == 0) || (prev_info->height == 0)) continue; /* Check if we're overlapping */ if (y < (prev_info->y + prev_info->height)) { ovl_info = prev_info; break; } } } /* Resize on overlap */ if (ovl_info) { /* 1/2 event width is enough room to squeeze * it in without resizing the last event. */ if (ovl_info->x >= (x + width/2)) { width = ovl_info->x - x - priv->spacing; } else { /* Reduce the size of the last event * and shuffle this event along * slightly. */ width = (ovl_info->width * 2)/3; x = ovl_info->x + (ovl_info->width - width); ovl_info->width = width; /* Resize overlapped event */ jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT ( priv->layout), ovl_info->row, ovl_info->x, ovl_info->y, ovl_info->width, ovl_info->height); } } jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT (priv->layout), info->row, x, y, width, height); } else { /* Hide out-of-range events */ jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT (priv->layout), info->row, 0, 0, 0, 0); } g_object_unref (time); g_object_unref (start); g_object_unref (end); } g_list_free (cells); /* Relayout the 24-hour events */ cells = jana_gtk_tree_layout_get_cells ( JANA_GTK_TREE_LAYOUT (priv->layout24hr)); time = jana_time_duplicate (priv->range->start); day = 0; max_event_y = priv->row0_height; event_y = priv->spacing + priv->row0_height; for (cell = g_list_last (cells); cell; cell = cell->prev) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaTime *start; gint height; GdkRectangle area; /* Work out what day the cell is in */ model = gtk_tree_row_reference_get_model (info->row); path = gtk_tree_row_reference_get_path (info->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start, -1); if (!start) continue; if (!jana_utils_duration_contains (priv->range, start)) { /* Hide out-of-range events */ jana_gtk_tree_layout_move_cell ( JANA_GTK_TREE_LAYOUT (priv->layout24hr), info->row, 0, 0, 0, 0); g_object_unref (start); continue; } /* Get to the correct day */ for (;jana_utils_time_compare (time, start, TRUE) < 0; jana_time_set_day (time, jana_time_get_day (time) + 1), day ++) { event_y = priv->spacing + priv->row0_height; } g_object_unref (start); /* Place event */ area.x = (day * cell_width) + priv->spacing; area.y = 0; area.width = cell_width - (priv->spacing * 2); area.height = G_MAXINT; jana_gtk_tree_layout_move_cell ( (JanaGtkTreeLayout *)priv->layout24hr, info->row, area.x, event_y, area.width, -1); g_object_set (G_OBJECT (priv->event_renderer24hr), "row", info->row, NULL); gtk_cell_renderer_get_size (priv->event_renderer24hr, priv->layout24hr, NULL, NULL, NULL, NULL, &height); event_y += height + priv->spacing; max_event_y = MAX (event_y, max_event_y); } gtk_widget_set_size_request (priv->alignment24hr, priv->layout->allocation.width + priv->col0_width, max_event_y); g_list_free (cells); g_object_unref (time); } static void size_request_cb (GtkWidget *widget, GtkRequisition *requisition, JanaGtkDayView *self) { requisition->width = 0; requisition->height = 0; } static void size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((allocation->width != priv->allocation.width) || (allocation->height != priv->allocation.height)) { priv->allocation.width = allocation->width; priv->allocation.height = allocation->height; relayout (self); } } /*static void redraw_cell (JanaGtkDayView *self, gint x, gint y) { GdkRectangle rect; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); rect.width = priv->layout->allocation.width / priv->visible_days; rect.height = priv->layout->allocation.height / priv->cells; rect.x = x - (x % rect.width); rect.y = y - (y % rect.height); gdk_window_invalidate_rect (priv->layout->window, &rect, TRUE); }*/ static void start_selection (JanaGtkDayView *self, gint x, gint y) { JanaTime *start, *end; gint alloc_height; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); alloc_height = priv->layout->allocation.height - (priv->layout->allocation.height % priv->cells); x = x + 1; y = MIN (y, alloc_height - 1); priv->selection_start_x = (x * priv->visible_days) / priv->layout->allocation.width; priv->selection_start_y = (y * priv->cells) / alloc_height; priv->selection_end_x = priv->selection_start_x; priv->selection_end_y = priv->selection_start_y + 1; start = jana_time_duplicate (priv->range->start); jana_time_set_day (start, jana_time_get_day (start) + priv->selection_start_x); jana_time_set_minutes (start, jana_time_get_minutes (start) + (priv->selection_start_y * priv->cell_minutes)); end = jana_time_duplicate (start); jana_time_set_minutes (end, jana_time_get_minutes (end) + priv->cell_minutes); if (priv->selection) jana_duration_free (priv->selection); priv->selection = jana_duration_new (start, end); g_object_unref (start); g_object_unref (end); } static void end_selection (JanaGtkDayView *self, gint x, gint y) { static gint last_day_offset = 0, last_minute_offset = 0; gint alloc_height; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); alloc_height = priv->layout->allocation.height - (priv->layout->allocation.height % priv->cells); x = MAX (MIN (x + 1, priv->layout->allocation.width), 0); y = MAX (MIN (y + 1, alloc_height), 0); /* Check against the last end offset so we don't change/redraw the * selection unnecessarily. */ priv->selection_end_x = (x * priv->visible_days) / priv->layout->allocation.width; priv->selection_end_y = (((y * priv->cells) / alloc_height) + 1); if ((priv->selection_end_x == last_day_offset) && (priv->selection_end_y == last_minute_offset)) return; last_day_offset = priv->selection_end_x; last_minute_offset = priv->selection_end_y; jana_time_set_day (priv->selection->end, jana_time_get_day (priv->range->start) + priv->selection_end_x); jana_time_set_hours (priv->selection->end, jana_time_get_hours (priv->range->start)); jana_time_set_minutes (priv->selection->end, jana_time_get_minutes (priv->range->start) + (priv->selection_end_y * priv->cell_minutes)); if (jana_utils_time_compare ( priv->selection->end, priv->selection->start, FALSE) <= 0) jana_time_set_minutes (priv->selection->end, jana_time_get_minutes (priv->selection->end) - priv->cell_minutes); gtk_widget_queue_draw (priv->layout); } static gboolean button_press_event_cb (GtkWidget *layout, GdkEventButton *event, JanaGtkDayView *self) { GList *selection; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((event->button != 1) || (!jana_duration_valid (priv->range)) || (priv->cells == 0)) return FALSE; if (priv->selection) { jana_duration_free (priv->selection); priv->selection = NULL; gtk_widget_queue_draw (GTK_WIDGET (self)); } selection = jana_gtk_tree_layout_get_selection ( JANA_GTK_TREE_LAYOUT (layout)); if (!selection) { start_selection (self, event->x, event->y); gtk_widget_queue_draw (layout); } else { g_list_free (selection); } jana_gtk_tree_layout_set_selection ( JANA_GTK_TREE_LAYOUT (priv->layout24hr), NULL); return FALSE; } static gboolean button_release_event_cb (GtkWidget *layout, GdkEventButton *event, JanaGtkDayView *self) { gint result; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((event->button != 1) || (!priv->selection)) return FALSE; end_selection (self, event->x, event->y); /* Swap start/end if end is before start */ result = jana_utils_time_compare (priv->selection->end, priv->selection->start, FALSE); if (result <= 0) { JanaTime *start; start = priv->selection->start; priv->selection->start = priv->selection->end; priv->selection->end = start; jana_time_set_minutes (priv->selection->end, jana_time_get_minutes (priv->selection->end) + priv->cell_minutes); } gtk_widget_queue_draw (layout); g_signal_emit (self, signals[SELECTION_CHANGED], 0, priv->selection); return FALSE; } static gboolean motion_notify_event_cb (GtkWidget *layout, GdkEventMotion *event, JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if ((event->state & GDK_BUTTON1_MASK) && (priv->selection)) { end_selection (self, event->x, event->y); } /* Request more motion events */ #if GTK_CHECK_VERSION(2, 12, 0) gdk_event_request_motions (event); #else gdk_window_get_pointer (layout->window, NULL, NULL, NULL); #endif return FALSE; } static void adjustment_changed_cb (GtkAdjustment *adjustment, JanaGtkDayView *self) { GdkRectangle rect; JanaGtkDayViewPrivate *priv; if (!GTK_WIDGET (self)->window) return; priv = DAY_VIEW_PRIVATE (self); /* Invalidate the headers */ rect.x = 0; rect.y = 0; rect.width = GTK_WIDGET (self)->allocation.width; rect.height = priv->row0_height; gdk_window_invalidate_rect (GTK_WIDGET (self)->window, &rect, FALSE); rect.width = priv->col0_width; rect.height = GTK_WIDGET (self)->allocation.height; gdk_window_invalidate_rect (GTK_WIDGET (self)->window, &rect, FALSE); gdk_window_process_updates (GTK_WIDGET (self)->window, FALSE); } static void jana_gtk_day_view_set_scroll_adjustments (JanaGtkDayView *self, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); GtkAdjustment *adjustment; adjustment = gtk_viewport_get_hadjustment ( GTK_VIEWPORT (priv->viewport)); if (adjustment) { g_signal_handlers_disconnect_by_func (adjustment, adjustment_changed_cb, self); } adjustment = gtk_viewport_get_vadjustment ( GTK_VIEWPORT (priv->viewport)); if (adjustment) { g_signal_handlers_disconnect_by_func (adjustment, adjustment_changed_cb, self); } gtk_viewport_set_hadjustment ( GTK_VIEWPORT (priv->viewport24hr), hadjustment); gtk_viewport_set_hadjustment ( GTK_VIEWPORT (priv->viewport), hadjustment); gtk_viewport_set_vadjustment ( GTK_VIEWPORT (priv->viewport), vadjustment); if (hadjustment) { g_signal_connect (hadjustment, "changed", G_CALLBACK (adjustment_changed_cb), self); g_signal_connect (hadjustment, "value-changed", G_CALLBACK (adjustment_changed_cb), self); } if (vadjustment) { g_signal_connect (vadjustment, "changed", G_CALLBACK (adjustment_changed_cb), self); g_signal_connect (vadjustment, "value-changed", G_CALLBACK (adjustment_changed_cb), self); } } /* Generated with glib-genmarshal and tidied */ static void marshal_VOID__OBJECT_OBJECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) ( gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2); register GMarshalFunc_VOID__OBJECT_OBJECT callback; register GCClosure *cc = (GCClosure*) closure; register gpointer data1, data2; g_return_if_fail (n_param_values == 3); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); callback (data1, g_value_get_object (param_values + 1), g_value_get_object (param_values + 2), data2); } static void jana_gtk_day_view_size_request (GtkWidget *widget, GtkRequisition *requisition) { GTK_WIDGET_CLASS (jana_gtk_day_view_parent_class)-> size_request (widget, requisition); requisition->width = 0; requisition->height = 0; } static void jana_gtk_day_view_class_init (JanaGtkDayViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkDayViewPrivate)); object_class->get_property = jana_gtk_day_view_get_property; object_class->set_property = jana_gtk_day_view_set_property; object_class->dispose = jana_gtk_day_view_dispose; object_class->finalize = jana_gtk_day_view_finalize; widget_class->size_request = jana_gtk_day_view_size_request; widget_class->expose_event = jana_gtk_day_view_expose_event; widget_class->set_scroll_adjustments_signal = g_signal_new ("set_scroll_adjustments", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (JanaGtkDayViewClass, set_scroll_adjustments), NULL, NULL, marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); klass->set_scroll_adjustments = jana_gtk_day_view_set_scroll_adjustments; g_object_class_install_property ( object_class, PROP_RANGE, g_param_spec_boxed ( "range", "Range", "The range shown by this day-view, as a JanaDuration.", JANA_TYPE_DURATION, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CELLS, g_param_spec_uint ( "cells", "Cells", "Amount of cells to partition time into, per day.", 0, G_MAXUINT, 0, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SPACING, g_param_spec_uint ( "spacing", "Spacing", "Spacing to use inside day boxes.", 0, G_MAXUINT, 2, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_STYLE_HINT, g_param_spec_string ( "style_hint", "Style hint", "The style hint to use when drawing.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SELECTION, g_param_spec_boxed ( "selection", "Selection", "The currently selected range, as a JanaDuration.", JANA_TYPE_DURATION, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SELECTED_EVENT, g_param_spec_boxed ( "selected_event", "Selected event", "A reference to the currently selected event in a " "JanaGtkEventStore.", GTK_TYPE_TREE_ROW_REFERENCE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_RATIO_X, g_param_spec_double ( "xratio", "X-ratio", "The proportion of the calendar that should be " "visible, on the x-axis.", G_MINDOUBLE, 1.0, 1.0, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_RATIO_Y, g_param_spec_double ( "yratio", "Y-ratio", "The proportion of the calendar that should be " "visible, on the y-axis.", G_MINDOUBLE, 1.0, 1.0, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_TIME, g_param_spec_object ( "highlighted_time", "Highlighted time", "A time that should be highlighted, " "for example, the current time.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_ACTIVE_RANGE, g_param_spec_boxed ( "active_range", "Active range", "The range that should be considered 'active'.", JANA_TYPE_DURATION, G_PARAM_READWRITE)); signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkDayViewClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, JANA_TYPE_DURATION); signals[EVENT_SELECTED] = g_signal_new ("event_selected", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkDayViewClass, event_selected), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GTK_TYPE_TREE_ROW_REFERENCE); signals[EVENT_ACTIVATED] = g_signal_new ("event_activated", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaGtkDayViewClass, event_activated), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GTK_TYPE_TREE_ROW_REFERENCE); } static gint sort_cells_cb (JanaGtkTreeLayoutCellInfo *info_a, JanaGtkTreeLayoutCellInfo *info_b) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; JanaTime *start_a, *end_a, *start_b, *end_b; gchar *summary_a, *summary_b; gint result = 0; model = gtk_tree_row_reference_get_model (info_a->row); path = gtk_tree_row_reference_get_path (info_a->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start_a, JANA_GTK_EVENT_STORE_COL_END, &end_a, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary_a, -1); model = gtk_tree_row_reference_get_model (info_b->row); path = gtk_tree_row_reference_get_path (info_b->row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_START, &start_b, JANA_GTK_EVENT_STORE_COL_END, &end_b, JANA_GTK_EVENT_STORE_COL_SUMMARY, &summary_b, -1); if (start_a && start_b) result = jana_utils_time_compare (start_b, start_a, FALSE); if (result == 0) { if (end_a && end_b) result = jana_utils_time_compare (end_a, end_b, FALSE); if ((result == 0) && summary_a && summary_b) result = g_utf8_collate (summary_b, summary_a); } g_free (summary_a); g_free (summary_b); if (start_a) g_object_unref (start_a); if (start_b) g_object_unref (start_b); if (end_a) g_object_unref (end_a); if (end_b) g_object_unref (end_b); return result; } static void adjustment_changed_after_size_allocate_cb (GtkAdjustment *adjustment, JanaGtkDayView *self) { gdouble lower, upper, diff1, diff2; /* FIXME: Do this in a more sane way */ /* It's ok to call this as the signals we want will already be in * the queue when we get here (it seems) */ g_signal_handlers_disconnect_by_func (adjustment, adjustment_changed_after_size_allocate_cb, self); lower = *((gdouble *)g_object_get_data ( G_OBJECT (adjustment), "lower")); upper = *((gdouble *)g_object_get_data ( G_OBJECT (adjustment), "upper")); /* If the adjustment really has changed, change the value to * reflect the new visible size */ diff1 = upper - lower; diff2 = adjustment->upper - adjustment->lower; if (diff1 != diff2) { gtk_adjustment_set_value (adjustment, adjustment->value * (diff2 / diff1)); } } static void viewport_size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, JanaGtkDayView *self) { static gdouble hlower, hupper, vlower, vupper; gint size_x, size_y; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); size_x = (gint)((gdouble)allocation->width / priv->xratio); size_y = (gint)((gdouble)allocation->height / priv->yratio); if ((priv->layout->allocation.width != size_x) || (priv->layout->allocation.height != size_y)) { GtkAdjustment *hadjustment, *vadjustment; hadjustment = gtk_viewport_get_hadjustment ( GTK_VIEWPORT (widget)); vadjustment = gtk_viewport_get_vadjustment ( GTK_VIEWPORT (widget)); hlower = hadjustment->lower; hupper = hadjustment->upper; vlower = vadjustment->lower; vupper = vadjustment->upper; g_object_set_data (G_OBJECT (hadjustment), "lower", &hlower); g_object_set_data (G_OBJECT (hadjustment), "upper", &hupper); g_object_set_data (G_OBJECT (vadjustment), "lower", &vlower); g_object_set_data (G_OBJECT (vadjustment), "upper", &vupper); g_signal_connect (hadjustment, "changed", G_CALLBACK (adjustment_changed_after_size_allocate_cb), self); g_signal_connect (vadjustment, "changed", G_CALLBACK (adjustment_changed_after_size_allocate_cb), self); gtk_widget_set_size_request (priv->layout, size_x, size_y); gtk_widget_set_size_request (priv->layout24hr, size_x, -1); } } static gboolean compare_selection (JanaGtkDayView *self, GtkTreeRowReference *row) { GtkTreePath *old_path, *path; gboolean result = TRUE; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); old_path = gtk_tree_row_reference_get_path (priv->selected_event); path = gtk_tree_row_reference_get_path (row); if ((gtk_tree_row_reference_get_model (row) != gtk_tree_row_reference_get_model (priv->selected_event)) || (gtk_tree_path_compare (path, old_path) != 0)) result = FALSE; gtk_tree_path_free (path); gtk_tree_path_free (old_path); return result; } static void layout_selection_changed_cb (JanaGtkTreeLayout *layout, JanaGtkDayView *self) { GList *info_list; JanaGtkTreeLayoutCellInfo *info; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); info_list = jana_gtk_tree_layout_get_selection (layout); if (!info_list) { if (priv->selected_event) { gtk_tree_row_reference_free (priv->selected_event); priv->selected_event = NULL; g_signal_emit (self, signals[EVENT_SELECTED], 0, NULL); } return; } info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if ((!priv->selected_event) || (!compare_selection (self, info->row))) { if (priv->selected_event) gtk_tree_row_reference_free (priv->selected_event); priv->selected_event = gtk_tree_row_reference_copy (info->row); g_signal_emit (self, signals[EVENT_SELECTED], 0, priv->selected_event); } g_list_free (info_list); } static void layout24hr_selection_changed_cb (JanaGtkTreeLayout *layout, JanaGtkDayView *self) { GList *info_list; JanaGtkTreeLayoutCellInfo *info; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); info_list = jana_gtk_tree_layout_get_selection (layout); if (!info_list) { if (priv->selected_event) { gtk_tree_row_reference_free (priv->selected_event); priv->selected_event = NULL; g_signal_emit (self, signals[EVENT_SELECTED], 0, NULL); } jana_gtk_tree_layout_set_selection ( JANA_GTK_TREE_LAYOUT (priv->layout), NULL); return; } /* Get rid of cell selection */ if (priv->selection) { jana_duration_free (priv->selection); priv->selection = NULL; gtk_widget_queue_draw (priv->layout); g_signal_emit (self, signals[SELECTION_CHANGED], 0, NULL); } info = (JanaGtkTreeLayoutCellInfo *)info_list->data; if ((!priv->selected_event) || (!compare_selection (self, info->row))) { if (priv->selected_event) gtk_tree_row_reference_free (priv->selected_event); priv->selected_event = NULL; /* Clear selection on other layout */ jana_gtk_tree_layout_set_selection ( JANA_GTK_TREE_LAYOUT (priv->layout), NULL); priv->selected_event = gtk_tree_row_reference_copy (info->row); g_signal_emit (self, signals[EVENT_SELECTED], 0, priv->selected_event); } g_list_free (info_list); } static void cell_activated_cb (JanaGtkTreeLayout *layout, const JanaGtkTreeLayoutCellInfo *info, JanaGtkDayView *self) { g_signal_emit (self, signals[EVENT_ACTIVATED], 0, info->row); } static void jana_gtk_day_view_init (JanaGtkDayView *self) { static gboolean locale_set = FALSE; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (!locale_set) { setlocale (LC_TIME, ""); locale_set = TRUE; } priv->spacing = 2; priv->xratio = 1.0; priv->yratio = 1.0; priv->vbox = gtk_vbox_new (FALSE, 0); priv->alignment = gtk_alignment_new (0.5, 0.5, 1, 1); priv->viewport = gtk_viewport_new (NULL, NULL); gtk_viewport_set_shadow_type ( GTK_VIEWPORT (priv->viewport), GTK_SHADOW_NONE); priv->alignment24hr = gtk_alignment_new (0.5, 0.5, 1, 1); priv->viewport24hr = gtk_viewport_new (NULL, NULL); gtk_viewport_set_shadow_type ( GTK_VIEWPORT (priv->viewport24hr), GTK_SHADOW_NONE); gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); priv->layout = jana_gtk_tree_layout_new (); g_object_set (G_OBJECT (priv->layout), "sort_cb", sort_cells_cb, "select_mode", GTK_SELECTION_SINGLE, NULL); gtk_widget_add_events (priv->layout, GDK_POINTER_MOTION_HINT_MASK); priv->layout24hr = jana_gtk_tree_layout_new (); g_object_set (G_OBJECT (priv->layout24hr), "sort_cb", sort_cells_cb, "select_mode", GTK_SELECTION_SINGLE, NULL); gtk_container_add (GTK_CONTAINER (priv->viewport), priv->layout); gtk_container_add (GTK_CONTAINER (priv->alignment), priv->viewport); gtk_container_add (GTK_CONTAINER (priv->viewport24hr), priv->layout24hr); gtk_container_add (GTK_CONTAINER (priv->alignment24hr), priv->viewport24hr); gtk_box_pack_start (GTK_BOX (priv->vbox), priv->alignment24hr, FALSE, TRUE, 0); gtk_box_pack_end (GTK_BOX (priv->vbox), priv->alignment, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (self), priv->vbox); gtk_widget_show (priv->alignment); gtk_widget_show (priv->viewport); gtk_widget_show (priv->layout); gtk_widget_show (priv->alignment24hr); gtk_widget_show (priv->viewport24hr); gtk_widget_show (priv->layout24hr); gtk_widget_show (priv->vbox); gtk_widget_set_no_show_all (priv->vbox, TRUE); priv->event_renderer = g_object_ref_sink ( jana_gtk_cell_renderer_event_new ()); priv->event_renderer24hr = g_object_ref_sink ( jana_gtk_cell_renderer_event_new ()); g_object_set (G_OBJECT (priv->event_renderer24hr), "draw_detail", FALSE, NULL); /* Resizing events */ g_signal_connect (priv->layout, "size-request", G_CALLBACK (size_request_cb), self); g_signal_connect (priv->layout24hr, "size-request", G_CALLBACK (size_request_cb), self); g_signal_connect (priv->layout, "size-allocate", G_CALLBACK (size_allocate_cb), self); g_signal_connect (priv->viewport, "size-allocate", G_CALLBACK (viewport_size_allocate_cb), self); /* Selection callbacks */ g_signal_connect_after (priv->layout, "button-press-event", G_CALLBACK (button_press_event_cb), self); g_signal_connect (priv->layout, "button-release-event", G_CALLBACK (button_release_event_cb), self); g_signal_connect (priv->layout, "motion-notify-event", G_CALLBACK (motion_notify_event_cb), self); g_signal_connect (priv->layout, "selection_changed", G_CALLBACK (layout_selection_changed_cb), self); g_signal_connect (priv->layout24hr, "selection_changed", G_CALLBACK (layout24hr_selection_changed_cb), self); g_signal_connect (priv->layout24hr, "cell_activated", G_CALLBACK (cell_activated_cb), self); g_signal_connect (priv->layout, "cell_activated", G_CALLBACK (cell_activated_cb), self); /* Drawing callbacks */ g_signal_connect (priv->layout, "expose-event", G_CALLBACK (layout_expose_event_cb), self); g_signal_connect (priv->layout24hr, "expose-event", G_CALLBACK (layout24hr_expose_event_cb), self); } /** * jana_gtk_day_view_new: * @range: The visible range on the day view * @cells: How many cells to use vertically * * Creates a new #JanaGtkDayView, which is a view of a single or multiple * days on any amount of #JanaGtkEventStore objects. @range will be used to * determine a rectangular viewing area, where the start of the duration is * used to determine the earliest visible time each day, and the end of the * duration is used to determine the latest visible time each day. * * Returns: A new #JanaGtkDayView. */ GtkWidget * jana_gtk_day_view_new (JanaDuration *range, guint cells) { return GTK_WIDGET (g_object_new (JANA_GTK_TYPE_DAY_VIEW, "range", range, "cells", cells, NULL)); } static void row_changed_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkDayView *self) { GtkTreeRowReference *row; JanaGtkTreeLayout *layout, *old_layout; gboolean first, last; JanaTime *start, *end; GtkCellRenderer *renderer; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); gtk_tree_model_get (tree_model, iter, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, &first, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, &last, JANA_GTK_EVENT_STORE_COL_START, &start, JANA_GTK_EVENT_STORE_COL_END, &end, -1); if (((!last) || ((end && jana_time_get_hours (end) == 0) && (jana_time_get_minutes (end) == 0) && (jana_time_get_seconds (end) == 0))) && ((!first) || ((start && jana_time_get_hours (start) == 0) && (jana_time_get_minutes (start) == 0) && (jana_time_get_seconds (start) == 0)))) { layout = JANA_GTK_TREE_LAYOUT (priv->layout24hr); old_layout = JANA_GTK_TREE_LAYOUT (priv->layout); renderer = priv->event_renderer24hr; } else { layout = JANA_GTK_TREE_LAYOUT (priv->layout); old_layout = JANA_GTK_TREE_LAYOUT (priv->layout24hr); renderer = priv->event_renderer; } if (start) g_object_unref (start); if (end) g_object_unref (end); row = gtk_tree_row_reference_new (tree_model, path); if (!jana_gtk_tree_layout_get_cell (layout, row)) { jana_gtk_tree_layout_remove_cell (old_layout, row); jana_gtk_tree_layout_add_cell (layout, row, 0, 0, 0, 0, renderer, "uid", JANA_GTK_EVENT_STORE_COL_UID, "categories", JANA_GTK_EVENT_STORE_COL_CATEGORIES, "summary", JANA_GTK_EVENT_STORE_COL_SUMMARY, "description", JANA_GTK_EVENT_STORE_COL_DESCRIPTION, "start", JANA_GTK_EVENT_STORE_COL_START, "end", JANA_GTK_EVENT_STORE_COL_END, "first_instance", JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, "last_instance", JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, "has_recurrences", JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, "has_alarm", JANA_GTK_EVENT_STORE_COL_HAS_ALARM, NULL); } gtk_tree_row_reference_free (row); relayout (self); } static void row_inserted_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkDayView *self) { JanaGtkTreeLayout *layout; gboolean first, last; JanaTime *start, *end; GtkTreeRowReference *row; GtkCellRenderer *renderer; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); gtk_tree_model_get (tree_model, iter, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, &first, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, &last, JANA_GTK_EVENT_STORE_COL_START, &start, JANA_GTK_EVENT_STORE_COL_END, &end, -1); if (((!last) || ((end && jana_time_get_hours (end) == 0) && (jana_time_get_minutes (end) == 0) && (jana_time_get_seconds (end) == 0))) && ((!first) || ((start && jana_time_get_hours (start) == 0) && (jana_time_get_minutes (start) == 0) && (jana_time_get_seconds (start) == 0)))) { layout = JANA_GTK_TREE_LAYOUT (priv->layout24hr); renderer = priv->event_renderer24hr; } else { layout = JANA_GTK_TREE_LAYOUT (priv->layout); renderer = priv->event_renderer; } if (start) g_object_unref (start); if (end) g_object_unref (end); /* Add row to layout */ row = gtk_tree_row_reference_new (tree_model, path); jana_gtk_tree_layout_add_cell (layout, row, 0, 0, 0, 0, renderer, "uid", JANA_GTK_EVENT_STORE_COL_UID, "categories", JANA_GTK_EVENT_STORE_COL_CATEGORIES, "summary", JANA_GTK_EVENT_STORE_COL_SUMMARY, "location", JANA_GTK_EVENT_STORE_COL_LOCATION, "description", JANA_GTK_EVENT_STORE_COL_DESCRIPTION, "start", JANA_GTK_EVENT_STORE_COL_START, "end", JANA_GTK_EVENT_STORE_COL_END, "first_instance", JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, "last_instance", JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, "has_recurrences", JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, "has_alarm", JANA_GTK_EVENT_STORE_COL_HAS_ALARM, NULL); gtk_tree_row_reference_free (row); relayout (self); } static void row_deleted_cb (GtkTreeModel *tree_model, GtkTreePath *path, JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->selected_event && (!gtk_tree_row_reference_valid (priv->selected_event))) { gtk_tree_row_reference_free (priv->selected_event); priv->selected_event = NULL; g_signal_emit (self, signals[EVENT_SELECTED], 0, NULL); } relayout (self); } static void insert_rows (JanaGtkDayView *self, JanaGtkEventStore *store) { GtkTreeIter iter; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) do { GtkTreePath *path = gtk_tree_model_get_path ( (GtkTreeModel *)store, &iter); row_inserted_cb ((GtkTreeModel *)store, path, &iter, self); gtk_tree_path_free (path); } while (gtk_tree_model_iter_next ((GtkTreeModel *)store, &iter)); } static void remove_rows (JanaGtkDayView *self, JanaGtkEventStore *store) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); GList *cell, *cells = jana_gtk_tree_layout_get_cells ( JANA_GTK_TREE_LAYOUT (priv->layout)); for (cell = cells; cell; cell = cell->next) { JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; if (gtk_tree_row_reference_get_model (info->row) == (GtkTreeModel *)store) jana_gtk_tree_layout_remove_cell ( (JanaGtkTreeLayout *)self, info->row); } g_list_free (cells); } /** * jana_gtk_day_view_add_store: * @self: A #JanaGtkDayView * @store: The #JanaGtkEventStore * * Adds a #JanaGtkEventStore to the view. Added stores will be monitored and * visualised events will be kept up-to-date. */ void jana_gtk_day_view_add_store (JanaGtkDayView *self, JanaGtkEventStore *store) { insert_rows (self, store); g_signal_connect (store, "row-inserted", G_CALLBACK (row_inserted_cb), self); g_signal_connect_after (store, "row-changed", G_CALLBACK (row_changed_cb), self); g_signal_connect_after (store, "row-deleted", G_CALLBACK (row_deleted_cb), self); } /** * jana_gtk_day_view_remove_store: * @self: A #JanaGtkDayView * @store: The #JanaGtkEventStore * * Removes a #JanaGtkEventStore from the view. */ void jana_gtk_day_view_remove_store (JanaGtkDayView *self, JanaGtkEventStore *store) { g_signal_handlers_disconnect_by_func (store, row_inserted_cb, self); g_signal_handlers_disconnect_by_func (store, row_changed_cb, self); g_signal_handlers_disconnect_by_func (store, row_deleted_cb, self); remove_rows (self, store); } /** * jana_gtk_day_view_scroll_to_cell: * @self: A #JanaGtkDayView * @x: The cell's x coordinate * @y: The cell's y coordinate * * Sets adjustments on @self so that the cell at @x , @y is visible. */ void jana_gtk_day_view_scroll_to_cell (JanaGtkDayView *self, guint x, guint y) { GtkAdjustment *hadjustment, *vadjustment; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); hadjustment = gtk_viewport_get_hadjustment ( GTK_VIEWPORT (priv->viewport)); vadjustment = gtk_viewport_get_vadjustment ( GTK_VIEWPORT (priv->viewport)); x *= (priv->layout->allocation.width - (priv->layout->allocation.width % priv->visible_days)) / priv->visible_days; y *= (priv->layout->allocation.height - (priv->layout->allocation.width % priv->cells)) / priv->cells; hadjustment->value = MIN (x, hadjustment->upper - hadjustment->page_size); vadjustment->value = MIN (y + vadjustment->lower, vadjustment->upper - vadjustment->page_size); gtk_adjustment_value_changed (hadjustment); gtk_adjustment_value_changed (vadjustment); } /** * jana_gtk_day_view_scroll_to_time: * @self: A #JanaGtkDayView * @time: The #JanaTime to scroll to * * Sets adjustments on @self so that @time is visible, assuming that @time is * in the visible range. */ void jana_gtk_day_view_scroll_to_time (JanaGtkDayView *self, JanaTime *time) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); gint x, hours, y; /* Check if the time is visible */ if ((jana_utils_time_compare (time, priv->range->start, FALSE) < 0) || (jana_utils_time_compare (time, priv->range->end, FALSE) >= 0)) return; if (jana_time_get_hours (time) < jana_time_get_hours (priv->range->start)) return; if ((jana_time_get_hours (time) == jana_time_get_hours (priv->range->start)) && (jana_time_get_minutes (time) < jana_time_get_minutes (priv->range->start))) return; hours = jana_time_get_hours (priv->range->end); if (hours == 0) hours = 24; if (jana_time_get_hours (time) > hours) return; if ((jana_time_get_hours (time) == hours) && (jana_time_get_minutes (time) >= jana_time_get_minutes (priv->range->end))) return; time_to_cell_coords (self, time, &x, &y); jana_gtk_day_view_scroll_to_cell (self, x, y); } /** * jana_gtk_day_view_get_cell_renderer: * @self: A #JanaGtkDayView * * Retrieves the #JanaGtkCellRendererEvent used to draw standard events. * * Returns: the #JanaGtkCellRendererEvent used to draw standard events. */ JanaGtkCellRendererEvent * jana_gtk_day_view_get_cell_renderer (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return (JanaGtkCellRendererEvent *)priv->event_renderer; } /** * jana_gtk_day_view_get_24hr_cell_renderer: * @self: A #JanaGtkDayView * * Retrieves the #JanaGtkCellRendererEvent used to draw all-day events. * * Returns: the #JanaGtkCellRendererEvent used to draw all-day events. */ JanaGtkCellRendererEvent * jana_gtk_day_view_get_24hr_cell_renderer (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return (JanaGtkCellRendererEvent *)priv->event_renderer24hr; } static void recalculate_cell_coords (JanaGtkDayView *self, gboolean active, gboolean selection, gboolean highlight) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->range && priv->cell_minutes) { if (priv->active_range) { time_to_cell_coords (self, priv->active_range->start, &priv->active_range_start_x, &priv->active_range_start_y); time_to_cell_coords (self, priv->active_range->end, &priv->active_range_end_x, &priv->active_range_end_y); } if (priv->selection) { time_to_cell_coords (self, priv->selection->start, &priv->selection_start_x, &priv->selection_start_y); time_to_cell_coords (self, priv->selection->end, &priv->selection_end_x, &priv->selection_end_y); } if (priv->highlighted_time) { gint days, mins, mins_in_day, alloc_height; /* Get how many minutes into the day the highlighted * time is, how many minutes there are per day visible, * and the height of the layout, so we can find out * where the time-line should occur. */ jana_utils_time_diff (priv->range->start, priv->highlighted_time, NULL, NULL, &days, NULL, &mins, NULL); jana_utils_time_diff (priv->range->start, priv->range->end, NULL, NULL, &days, NULL, &mins_in_day, NULL); if (!mins_in_day) mins_in_day = 24 * 60; alloc_height = priv->layout->allocation.height - (priv->layout->allocation.height % priv->cells); time_to_cell_coords (self, priv->highlighted_time, &priv->highlighted_time_x, &priv->highlighted_time_y); priv->highlighted_time_pos = (gdouble)mins / (gdouble)mins_in_day; } } } /** * jana_gtk_day_view_set_range: * @self: A #JanaGtkDayView * @range: The visible range * * Set the rectangular viewing area, where the start of @range is * used to determine the earliest visible time each day, and the end * is used to determine the latest visible time each day. */ void jana_gtk_day_view_set_range (JanaGtkDayView *self, JanaDuration *range) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); free_layouts (self); if (priv->range) { jana_duration_free (priv->range); priv->range = NULL; } if (range) { JanaTime *time; priv->range = jana_duration_copy (range); jana_time_set_isdate (priv->range->start, FALSE); jana_time_set_isdate (priv->range->end, FALSE); /* Count visible days */ for (priv->visible_days = 0, time = jana_time_duplicate (priv->range->start); jana_utils_time_compare ( time, priv->range->end, TRUE) < 0; jana_time_set_day ( time, jana_time_get_day (time) + 1), priv->visible_days ++); g_object_unref (time); } if (priv->selection) { jana_duration_free (priv->selection); priv->selection = NULL; g_signal_emit (self, signals[SELECTION_CHANGED], 0, NULL); } create_layouts (self); relayout (self); recalculate_cell_coords (self, TRUE, TRUE, TRUE); gtk_widget_queue_draw (GTK_WIDGET (self)); } /** * jana_gtk_day_view_get_range: * @self: A #JanaGtkDayView * * Get the visible time-range, as a #JanaDuration. * See jana_gtk_day_view_set_range(). * * Returns: The visible range. */ JanaDuration * jana_gtk_day_view_get_range (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return priv->range ? jana_duration_copy (priv->range) : NULL; } /** * jana_gtk_day_view_get_selection: * @self: A #JanaGtkDayView * * Get the selected time-range, as a #JanaDuration. * See jana_gtk_day_view_set_selection(). * * Returns: The selected time-range, or %NULL if no range is selected. */ JanaDuration * jana_gtk_day_view_get_selection (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return priv->selection ? jana_duration_copy (priv->selection) : NULL; } /** * jana_gtk_day_view_set_selection: * @self: A #JanaGtkDayView * @selection: The time-range to select * * Sets the selected time range. */ void jana_gtk_day_view_set_selection (JanaGtkDayView *self, JanaDuration *selection) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->selection) { jana_duration_free (priv->selection); priv->selection = NULL; } if (selection) { priv->selection = jana_duration_copy (selection); jana_time_set_isdate (priv->selection->start, FALSE); jana_time_set_isdate (priv->selection->end, FALSE); recalculate_cell_coords (self, FALSE, TRUE, FALSE); } g_signal_emit (self, signals[SELECTION_CHANGED], 0, priv->selection); gtk_widget_queue_draw (GTK_WIDGET (self)); } /** * jana_gtk_day_view_set_spacing: * @self: A #JanaGtkDayView * @spacing: Spacing, in pixels * * Sets the spacing used around events and text, in pixels. */ void jana_gtk_day_view_set_spacing (JanaGtkDayView *self, guint spacing) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); priv->row0_height -= (priv->spacing * 2); priv->col0_width -= (priv->spacing * 2); priv->spacing = spacing; priv->row0_height += (priv->spacing * 2); priv->col0_width += (priv->spacing * 2); set_alignments (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } /** * jana_gtk_day_view_set_cells: * @self: A #JanaGtkDayView * @cells: Amount of cells to use, vertically. * * Sets the amount of cells to divide time up into, per day; i.e. the amount * of cells to display vertically. */ void jana_gtk_day_view_set_cells (JanaGtkDayView *self, guint cells) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); priv->cells = cells; free_layouts (self); create_layouts (self); relayout (self); recalculate_cell_coords (self, TRUE, TRUE, TRUE); gtk_widget_queue_draw (GTK_WIDGET (self)); } /** * jana_gtk_day_view_get_cells: * @self: A #JanaGtkDayView * * Gets the amount of cells used vertically. * See jana_gtk_day_view_set_cells(). * * Returns: Amount of cells used vertically. */ guint jana_gtk_day_view_get_cells (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return priv->cells; } /** * jana_gtk_day_view_get_spacing: * @self: A #JanaGtkDayView * * Gets the spacing used around events and text. * See jana_gtk_day_view_set_spacing(). * * Returns: Spacing used around events and text, in pixels. */ guint jana_gtk_day_view_get_spacing (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return priv->spacing; } /** * jana_gtk_day_view_set_visible_ratio: * @self: A #JanaGtkDayView * @xratio: The fraction of the set visible range that should be visible * without scrolling, on the x-axis. * @yratio: The fraction of the set visible range that should be visible * without scrolling, on the y-axis. * * Sets the amount of the visible range that should be viewable at once, * without scrolling. This is represented as a fraction, from G_MINFLOAT to * 1.0, inclusive. If, for example, a #JanaGtkDayView was placed in a * #GtkScrolledWindow, and the xratio and yratio were set to 1.0 and 0.5, * respectively, a horizontal scroll-bar would not be required, but the * #JanaGtkDayView would size itself so that only half of itself were visible * and a vertical scroll-bar would be required. Ratios below 1.0 must not be * set when the scrolling policy of the containing widget disallows scrolling. */ void jana_gtk_day_view_set_visible_ratio (JanaGtkDayView *self, gdouble xratio, gdouble yratio) { g_object_set (G_OBJECT (self), "xratio", xratio, "yratio", yratio, NULL); } /** * jana_gtk_day_view_get_visible_ratio: * @self: A #JanaGtkDayView * @xratio: Return location for xratio, or %NULL * @yratio: Return location for yratio, or %NULL * * Retrieves the amount of the visible range that should be viewable at once, * on each axis. See jana_gtk_day_view_set_visible_ratio(). */ void jana_gtk_day_view_get_visible_ratio (JanaGtkDayView *self, gdouble *xratio, gdouble *yratio) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (xratio) *xratio = priv->xratio; if (yratio) *yratio = priv->yratio; } /** * jana_gtk_day_view_get_selected_event: * @self: A #JanaGtkDayView * * Retrieves the selected event, returned as a #GtkTreeRowReference on a * #JanaGtkEventStore. See jana_gtk_day_view_set_selected_event(). * * Returns: the selected event, as a row reference on a #JanaGtkEventStore. */ GtkTreeRowReference * jana_gtk_day_view_get_selected_event (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); return priv->selected_event ? gtk_tree_row_reference_copy (priv->selected_event) : NULL; } /** * jana_gtk_day_view_set_selected_event: * @self: A #JanaGtkDayView * @row: A #GtkTreeRowReference on a #JanaGtkEventStore * * Sets the selected event, if the specified @row is visible on @self. */ void jana_gtk_day_view_set_selected_event (JanaGtkDayView *self, GtkTreeRowReference *row) { const JanaGtkTreeLayoutCellInfo *info; JanaGtkTreeLayout *layout; JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (row && compare_selection (self, row)) return; if (row) { layout = JANA_GTK_TREE_LAYOUT (priv->layout); info = jana_gtk_tree_layout_get_cell (layout, row); if (!info) { layout = JANA_GTK_TREE_LAYOUT (priv->layout24hr); info = jana_gtk_tree_layout_get_cell (layout, row); } if (info) { GList *selection = g_list_prepend ( NULL, (gpointer)info); jana_gtk_tree_layout_set_selection ( layout, selection); g_list_free (selection); return; } } jana_gtk_tree_layout_set_selection ( JANA_GTK_TREE_LAYOUT (priv->layout), NULL); jana_gtk_tree_layout_set_selection ( JANA_GTK_TREE_LAYOUT (priv->layout24hr), NULL); } void jana_gtk_day_view_set_visible_func (JanaGtkDayView *self, GtkTreeModelFilterVisibleFunc visible_cb, gpointer data) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); jana_gtk_tree_layout_set_visible_func ( JANA_GTK_TREE_LAYOUT (priv->layout), visible_cb, data); jana_gtk_tree_layout_set_visible_func ( JANA_GTK_TREE_LAYOUT (priv->layout24hr), visible_cb, data); } void jana_gtk_day_view_refilter (JanaGtkDayView *self) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); jana_gtk_tree_layout_refilter (JANA_GTK_TREE_LAYOUT (priv->layout)); jana_gtk_tree_layout_refilter (JANA_GTK_TREE_LAYOUT (priv->layout24hr)); } void jana_gtk_day_view_set_highlighted_time (JanaGtkDayView *self, JanaTime *time) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->highlighted_time) { g_object_unref (priv->highlighted_time); priv->highlighted_time = NULL; } if (time) { priv->highlighted_time = jana_time_duplicate (time); if (priv->range) { recalculate_cell_coords (self, FALSE, FALSE, TRUE); } } free_layouts (self); create_layouts (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } void jana_gtk_day_view_set_active_range (JanaGtkDayView *self, JanaDuration *range) { JanaGtkDayViewPrivate *priv = DAY_VIEW_PRIVATE (self); if (priv->active_range) { jana_duration_free (priv->active_range); priv->active_range = NULL; } if (range) { priv->active_range = jana_duration_copy (range); if (priv->range) { recalculate_cell_coords (self, TRUE, FALSE, FALSE); } } gtk_widget_queue_draw (priv->layout); } jana/libjana-gtk/doc/0000755000175000017500000000000011327631152014630 5ustar paulliupaulliujana/libjana-gtk/doc/Makefile.am0000644000175000017500000000002211327631152016656 0ustar paulliupaulliuSUBDIRS=reference jana/libjana-gtk/doc/reference/0000755000175000017500000000000011327631152016566 5ustar paulliupaulliujana/libjana-gtk/doc/reference/libjana-gtk-docs.sgml0000644000175000017500000000231711327631152022566 0ustar paulliupaulliu libjana-gtk Reference Manual libjana-gtk jana/libjana-gtk/doc/reference/libjana-gtk.types0000644000175000017500000000071011327631152022035 0ustar paulliupaulliujana_gtk_event_list_get_type jana_gtk_recurrence_get_type jana_gtk_day_view_get_type jana_gtk_cell_renderer_note_get_type jana_gtk_world_map_marker_get_type jana_gtk_month_view_get_type jana_gtk_world_map_get_type jana_gtk_world_map_marker_get_type jana_gtk_cell_renderer_event_get_type jana_gtk_year_view_get_type jana_gtk_date_time_get_type jana_gtk_clock_get_type jana_gtk_tree_layout_get_type jana_gtk_event_store_get_type jana_gtk_note_store_get_type jana/libjana-gtk/doc/reference/Makefile.am0000644000175000017500000000541611327631152020630 0ustar paulliupaulliu## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libjana-gtk # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=../../ # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/libjana-gtk/*.h CFILE_GLOB=$(top_srcdir)/libjana-gtk/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES= # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) INCLUDES=-I$(top_srcdir)/src -I$(top_builddir) $(GOBJECT_CFLAGS) $(GTK_CFLAGS) GTKDOC_LIBS=$(top_srcdir)/libjana-gtk/libjana-gtk.la $(GOBJECT_LIBS) $(GTK_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = version.xml.in jana/libjana-gtk/doc/reference/tmpl/0000755000175000017500000000000011327631152017542 5ustar paulliupaulliujana/libjana-gtk/doc/reference/tmpl/dummy.sgml0000644000175000017500000000000011327631152021547 0ustar paulliupaulliujana/libjana-gtk/doc/reference/version.xml.in0000644000175000017500000000001211327631152021373 0ustar paulliupaulliu@VERSION@ jana/libjana-gtk/doc/reference/libjana-gtk-sections.txt0000644000175000017500000002072211327631152023342 0ustar paulliupaulliu
jana-gtk-event-list JanaGtkEventList JanaGtkEventList jana_gtk_event_list_new jana_gtk_event_list_add_store jana_gtk_event_list_remove_store jana_gtk_event_list_get_filter jana_gtk_event_list_refilter jana_gtk_event_list_set_show_headers jana_gtk_event_list_get_show_headers JANA_GTK_EVENT_LIST JANA_GTK_IS_EVENT_LIST JANA_GTK_TYPE_EVENT_LIST jana_gtk_event_list_get_type JANA_GTK_EVENT_LIST_CLASS JANA_GTK_IS_EVENT_LIST_CLASS JANA_GTK_EVENT_LIST_GET_CLASS
jana-gtk-recurrence JanaGtkRecurrence JanaGtkRecurrence jana_gtk_recurrence_new jana_gtk_recurrence_set_recur jana_gtk_recurrence_set_editable jana_gtk_recurrence_set_time jana_gtk_recurrence_get_recur jana_gtk_recurrence_get_editable jana_gtk_recurrence_get_time JANA_GTK_RECURRENCE JANA_GTK_IS_RECURRENCE JANA_GTK_TYPE_RECURRENCE jana_gtk_recurrence_get_type JANA_GTK_RECURRENCE_CLASS JANA_GTK_IS_RECURRENCE_CLASS JANA_GTK_RECURRENCE_GET_CLASS
jana-gtk-day-view JanaGtkDayView JanaGtkDayView jana_gtk_day_view_new jana_gtk_day_view_add_store jana_gtk_day_view_remove_store jana_gtk_day_view_scroll_to_cell jana_gtk_day_view_scroll_to_time jana_gtk_day_view_get_cell_renderer jana_gtk_day_view_get_24hr_cell_renderer jana_gtk_day_view_set_range jana_gtk_day_view_get_range jana_gtk_day_view_set_cells jana_gtk_day_view_get_cells jana_gtk_day_view_set_spacing jana_gtk_day_view_get_spacing jana_gtk_day_view_get_selection jana_gtk_day_view_set_selection jana_gtk_day_view_set_visible_ratio jana_gtk_day_view_get_visible_ratio jana_gtk_day_view_get_selected_event jana_gtk_day_view_set_selected_event jana_gtk_day_view_set_visible_func jana_gtk_day_view_refilter jana_gtk_day_view_set_highlighted_time jana_gtk_day_view_set_active_range JANA_GTK_DAY_VIEW JANA_GTK_IS_DAY_VIEW JANA_GTK_TYPE_DAY_VIEW jana_gtk_day_view_get_type JANA_GTK_DAY_VIEW_CLASS JANA_GTK_IS_DAY_VIEW_CLASS JANA_GTK_DAY_VIEW_GET_CLASS
jana-gtk-cell-renderer-note JanaGtkCellRendererNote JanaGtkCellRendererNote jana_gtk_cell_renderer_note_new JANA_GTK_CELL_RENDERER_NOTE JANA_GTK_IS_CELL_RENDERER_NOTE JANA_GTK_TYPE_CELL_RENDERER_NOTE jana_gtk_cell_renderer_note_get_type JANA_GTK_CELL_RENDERER_NOTE_CLASS JANA_GTK_IS_CELL_RENDERER_NOTE_CLASS JANA_GTK_CELL_RENDERER_NOTE_GET_CLASS
jana-gtk-world-map-marker JanaGtkWorldMapMarker JanaGtkWorldMapMarker jana_gtk_world_map_marker_new jana_gtk_world_map_marker_render JANA_GTK_WORLD_MAP_MARKER JANA_GTK_IS_WORLD_MAP_MARKER JANA_GTK_TYPE_WORLD_MAP_MARKER jana_gtk_world_map_marker_get_type JANA_GTK_WORLD_MAP_MARKER_CLASS JANA_GTK_IS_WORLD_MAP_MARKER_CLASS JANA_GTK_WORLD_MAP_MARKER_GET_CLASS
jana-gtk-month-view JanaGtkMonthView JanaGtkMonthView jana_gtk_month_view_new jana_gtk_month_view_add_store jana_gtk_month_view_remove_store jana_gtk_month_view_get_cell_renderer jana_gtk_month_view_set_month jana_gtk_month_view_get_month jana_gtk_month_view_set_spacing jana_gtk_month_view_get_spacing jana_gtk_month_view_set_selection jana_gtk_month_view_get_selection jana_gtk_month_view_set_visible_func jana_gtk_month_view_refilter jana_gtk_month_view_set_highlighted_time JANA_GTK_MONTH_VIEW JANA_GTK_IS_MONTH_VIEW JANA_GTK_TYPE_MONTH_VIEW jana_gtk_month_view_get_type JANA_GTK_MONTH_VIEW_CLASS JANA_GTK_IS_MONTH_VIEW_CLASS JANA_GTK_MONTH_VIEW_GET_CLASS
jana-gtk-world-map JanaGtkWorldMap JanaGtkWorldMap jana_gtk_world_map_new jana_gtk_world_map_set_time jana_gtk_world_map_get_latlon jana_gtk_world_map_get_xy jana_gtk_world_map_add_marker jana_gtk_world_map_remove_marker jana_gtk_world_map_move_marker jana_gtk_world_map_get_markers jana_gtk_world_map_set_static jana_gtk_world_map_get_static jana_gtk_world_map_set_width jana_gtk_world_map_get_width jana_gtk_world_map_set_height jana_gtk_world_map_get_height JANA_GTK_WORLD_MAP JANA_GTK_IS_WORLD_MAP JANA_GTK_TYPE_WORLD_MAP jana_gtk_world_map_get_type JANA_GTK_WORLD_MAP_CLASS JANA_GTK_IS_WORLD_MAP_CLASS JANA_GTK_WORLD_MAP_GET_CLASS
jana-gtk-world-map-marker-pixbuf JanaGtkWorldMapMarkerPixbuf JanaGtkWorldMapMarkerPixbuf jana_gtk_world_map_marker_pixbuf_new JANA_GTK_WORLD_MAP_MARKER_PIXBUF JANA_GTK_IS_WORLD_MAP_MARKER_PIXBUF JANA_GTK_TYPE_WORLD_MAP_MARKER_PIXBUF jana_gtk_world_map_marker_get_type JANA_GTK_WORLD_MAP_MARKER_PIXBUF_CLASS JANA_GTK_IS_WORLD_MAP_MARKER_PIXBUF_CLASS JANA_GTK_WORLD_MAP_MARKER_PIXBUF_GET_CLASS
jana-gtk-cell-renderer-event JanaGtkCellRendererEvent JanaGtkCellRendererEvent jana_gtk_cell_renderer_event_new JANA_GTK_CELL_RENDERER_EVENT JANA_GTK_IS_CELL_RENDERER_EVENT JANA_GTK_TYPE_CELL_RENDERER_EVENT jana_gtk_cell_renderer_event_get_type JANA_GTK_CELL_RENDERER_EVENT_CLASS JANA_GTK_IS_CELL_RENDERER_EVENT_CLASS JANA_GTK_CELL_RENDERER_EVENT_GET_CLASS
jana-gtk-year-view JanaGtkYearView JanaGtkYearView jana_gtk_year_view_new jana_gtk_year_view_add_store jana_gtk_year_view_remove_store jana_gtk_year_view_set_year jana_gtk_year_view_get_year jana_gtk_year_view_set_months_per_row jana_gtk_year_view_get_selected_month jana_gtk_year_view_set_selected_month jana_gtk_year_view_set_highlighted_time JANA_GTK_YEAR_VIEW JANA_GTK_IS_YEAR_VIEW JANA_GTK_TYPE_YEAR_VIEW jana_gtk_year_view_get_type JANA_GTK_YEAR_VIEW_CLASS JANA_GTK_IS_YEAR_VIEW_CLASS JANA_GTK_YEAR_VIEW_GET_CLASS
jana-gtk-date-time JanaGtkDateTime JanaGtkDateTime jana_gtk_date_time_new jana_gtk_date_time_get_time jana_gtk_date_time_set_time jana_gtk_date_time_set_editable jana_gtk_date_time_get_editable JANA_GTK_DATE_TIME JANA_GTK_IS_DATE_TIME JANA_GTK_TYPE_DATE_TIME jana_gtk_date_time_get_type JANA_GTK_DATE_TIME_CLASS JANA_GTK_IS_DATE_TIME_CLASS JANA_GTK_DATE_TIME_GET_CLASS
jana-gtk-clock JanaGtkClock JanaGtkClock jana_gtk_clock_new jana_gtk_clock_set_time jana_gtk_clock_get_time jana_gtk_clock_set_digital jana_gtk_clock_get_digital jana_gtk_clock_set_show_seconds jana_gtk_clock_get_show_seconds jana_gtk_clock_set_buffer_time jana_gtk_clock_get_buffer_time jana_gtk_clock_set_draw_shadow jana_gtk_clock_get_draw_shadow JANA_GTK_CLOCK JANA_GTK_IS_CLOCK JANA_GTK_TYPE_CLOCK jana_gtk_clock_get_type JANA_GTK_CLOCK_CLASS JANA_GTK_IS_CLOCK_CLASS JANA_GTK_CLOCK_GET_CLASS
jana-gtk-tree-layout JanaGtkTreeLayoutCellInfo JanaGtkTreeLayout JanaGtkTreeLayout jana_gtk_tree_layout_new jana_gtk_tree_layout_add_cell jana_gtk_tree_layout_move_cell jana_gtk_tree_layout_remove_cell jana_gtk_tree_layout_clear jana_gtk_tree_layout_get_selection jana_gtk_tree_layout_get_cells jana_gtk_tree_layout_set_selection jana_gtk_tree_layout_get_cell jana_gtk_tree_layout_set_cell_sensitive jana_gtk_tree_layout_set_visible_func jana_gtk_tree_layout_refilter JANA_GTK_TREE_LAYOUT JANA_GTK_IS_TREE_LAYOUT JANA_GTK_TYPE_TREE_LAYOUT jana_gtk_tree_layout_get_type JANA_GTK_TREE_LAYOUT_CLASS JANA_GTK_IS_TREE_LAYOUT_CLASS JANA_GTK_TREE_LAYOUT_GET_CLASS
jana-gtk-event-store JanaGtkEventStore JanaGtkEventStore jana_gtk_event_store_new jana_gtk_event_store_new_full jana_gtk_event_store_set_view jana_gtk_event_store_get_view jana_gtk_event_store_get_store jana_gtk_event_store_set_offset JANA_GTK_EVENT_STORE JANA_GTK_IS_EVENT_STORE JANA_GTK_TYPE_EVENT_STORE jana_gtk_event_store_get_type JANA_GTK_EVENT_STORE_CLASS JANA_GTK_IS_EVENT_STORE_CLASS JANA_GTK_EVENT_STORE_GET_CLASS
jana-gtk-note-store JanaGtkNoteStore JanaGtkNoteStore jana_gtk_note_store_new jana_gtk_note_store_new_full jana_gtk_note_store_set_view jana_gtk_note_store_get_view jana_gtk_note_store_get_store JANA_GTK_NOTE_STORE JANA_GTK_IS_NOTE_STORE JANA_GTK_TYPE_NOTE_STORE jana_gtk_note_store_get_type JANA_GTK_NOTE_STORE_CLASS JANA_GTK_IS_NOTE_STORE_CLASS JANA_GTK_NOTE_STORE_GET_CLASS
jana-gtk-utils jana_gtk_utils_treeview_resize
jana-gtk
jana/libjana-gtk/jana-gtk-cell-renderer-event.c0000644000175000017500000006716011327631152021575 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "jana-gtk-event-store.h" #include "jana-gtk-cell-renderer-event.h" G_DEFINE_TYPE (JanaGtkCellRendererEvent, jana_gtk_cell_renderer_event, \ GTK_TYPE_CELL_RENDERER) #define CELL_RENDERER_EVENT_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_CELL_RENDERER_EVENT, \ JanaGtkCellRendererEventPrivate)) typedef struct _JanaGtkCellRendererEventPrivate JanaGtkCellRendererEventPrivate; struct _JanaGtkCellRendererEventPrivate { gchar *style_hint; gchar *uid; gchar **categories; gchar *summary; gchar *location; gchar *description; JanaTime *start; JanaTime *end; gboolean first_instance; gboolean last_instance; gboolean has_recurrences; gboolean has_alarm; gboolean draw_text; gboolean draw_detail; gboolean draw_time; gboolean draw_box; gboolean draw_resize; guint xpadi; guint ypadi; gint cell_width; GHashTable *category_color_hash; }; enum { PROP_STYLE_HINT = 1, PROP_UID, PROP_CATEGORIES, PROP_SUMMARY, PROP_LOCATION, PROP_DESCRIPTION, PROP_START, PROP_END, PROP_FIRST_INSTANCE, PROP_LAST_INSTANCE, PROP_HAS_RECURRENCES, PROP_HAS_ALARM, PROP_DRAW_TEXT, PROP_DRAW_DETAIL, PROP_DRAW_TIME, PROP_DRAW_BOX, PROP_DRAW_RESIZE, PROP_ROW, PROP_XPAD_INNER, PROP_YPAD_INNER, PROP_CELL_WIDTH, PROP_CATEGORY_COLOR_HASH, }; static void cell_renderer_event_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags); static void cell_renderer_event_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void jana_gtk_cell_renderer_event_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (object); switch (property_id) { case PROP_STYLE_HINT : g_value_set_string (value, priv->style_hint); break; case PROP_UID : g_value_set_string (value, priv->uid); break; case PROP_CATEGORIES : g_value_set_boxed (value, priv->categories); break; case PROP_SUMMARY : g_value_set_string (value, priv->summary); break; case PROP_LOCATION : g_value_set_string (value, priv->location); break; case PROP_DESCRIPTION : g_value_set_string (value, priv->description); break; case PROP_START : g_value_set_object (value, priv->start); break; case PROP_END : g_value_set_object (value, priv->end); break; case PROP_FIRST_INSTANCE : g_value_set_boolean (value, priv->first_instance); break; case PROP_LAST_INSTANCE : g_value_set_boolean (value, priv->last_instance); break; case PROP_HAS_RECURRENCES : g_value_set_boolean (value, priv->has_recurrences); break; case PROP_HAS_ALARM : g_value_set_boolean (value, priv->has_alarm); break; case PROP_DRAW_TEXT : g_value_set_boolean (value, priv->draw_text); break; case PROP_DRAW_DETAIL : g_value_set_boolean (value, priv->draw_detail); break; case PROP_DRAW_TIME : g_value_set_boolean (value, priv->draw_time); break; case PROP_DRAW_BOX : g_value_set_boolean (value, priv->draw_box); break; case PROP_DRAW_RESIZE : g_value_set_boolean (value, priv->draw_resize); break; case PROP_XPAD_INNER : g_value_set_uint (value, priv->xpadi); break; case PROP_YPAD_INNER : g_value_set_uint (value, priv->ypadi); break; case PROP_CELL_WIDTH : g_value_set_int (value, priv->cell_width); break; case PROP_CATEGORY_COLOR_HASH : g_value_set_boxed (value, priv->category_color_hash); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_cell_renderer_event_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (object); switch (property_id) { case PROP_STYLE_HINT : if (priv->style_hint) g_free (priv->style_hint); priv->style_hint = g_value_dup_string (value); break; case PROP_UID : if (priv->uid) g_free (priv->uid); priv->uid = g_value_dup_string (value); break; case PROP_CATEGORIES : if (priv->categories) g_strfreev (priv->categories); priv->categories = g_value_dup_boxed (value); break; case PROP_SUMMARY : if (priv->summary) g_free (priv->summary); priv->summary = g_value_dup_string (value); break; case PROP_LOCATION : if (priv->location) g_free (priv->location); priv->location = g_value_dup_string (value); break; case PROP_DESCRIPTION : if (priv->description) g_free (priv->description); priv->description = g_value_dup_string (value); break; case PROP_START : if (priv->start) g_object_unref (priv->start); priv->start = JANA_TIME (g_value_dup_object (value)); break; case PROP_END : if (priv->end) g_object_unref (priv->end); priv->end = JANA_TIME (g_value_dup_object (value)); break; case PROP_FIRST_INSTANCE : priv->first_instance = g_value_get_boolean (value); break; case PROP_LAST_INSTANCE : priv->last_instance = g_value_get_boolean (value); break; case PROP_HAS_RECURRENCES : priv->has_recurrences = g_value_get_boolean (value); break; case PROP_HAS_ALARM : priv->has_alarm = g_value_get_boolean (value); break; case PROP_DRAW_TEXT : priv->draw_text = g_value_get_boolean (value); break; case PROP_DRAW_DETAIL : priv->draw_detail = g_value_get_boolean (value); break; case PROP_DRAW_TIME : priv->draw_time = g_value_get_boolean (value); break; case PROP_DRAW_BOX : priv->draw_box = g_value_get_boolean (value); break; case PROP_DRAW_RESIZE : priv->draw_resize = g_value_get_boolean (value); break; case PROP_ROW : { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; GtkTreeRowReference *row = g_value_get_pointer (value); g_object_set (object, "uid", NULL, "categories", NULL, "summary", NULL, "location", NULL, "description", NULL, "start", NULL, "end", NULL, NULL); if (!row) break; model = gtk_tree_row_reference_get_model (row); path = gtk_tree_row_reference_get_path (row); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_STORE_COL_UID, &priv->uid, JANA_GTK_EVENT_STORE_COL_CATEGORIES, &priv->categories, JANA_GTK_EVENT_STORE_COL_SUMMARY, &priv->summary, JANA_GTK_EVENT_STORE_COL_LOCATION, &priv->location, JANA_GTK_EVENT_STORE_COL_DESCRIPTION, &priv->description, JANA_GTK_EVENT_STORE_COL_START, &priv->start, JANA_GTK_EVENT_STORE_COL_END, &priv->end, JANA_GTK_EVENT_STORE_COL_FIRST_INSTANCE, &priv->first_instance, JANA_GTK_EVENT_STORE_COL_LAST_INSTANCE, &priv->last_instance, JANA_GTK_EVENT_STORE_COL_HAS_RECURRENCES, &priv->has_recurrences, JANA_GTK_EVENT_STORE_COL_HAS_ALARM, &priv->has_alarm, -1); break; } case PROP_XPAD_INNER : priv->xpadi = g_value_get_uint (value); break; case PROP_YPAD_INNER : priv->ypadi = g_value_get_uint (value); break; case PROP_CELL_WIDTH : priv->cell_width = g_value_get_int (value); break; case PROP_CATEGORY_COLOR_HASH : if (priv->category_color_hash) g_hash_table_unref (priv->category_color_hash); priv->category_color_hash = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_cell_renderer_event_dispose (GObject *object) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (object); if (priv->start) { g_object_unref (priv->start); priv->start = NULL; } if (priv->end) { g_object_unref (priv->end); priv->end = NULL; } if (G_OBJECT_CLASS (jana_gtk_cell_renderer_event_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_cell_renderer_event_parent_class)-> dispose (object); } static void jana_gtk_cell_renderer_event_finalize (GObject *object) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (object); g_free (priv->style_hint); g_free (priv->uid); g_free (priv->summary); g_free (priv->location); g_free (priv->description); if (priv->category_color_hash) g_hash_table_unref (priv->category_color_hash); G_OBJECT_CLASS (jana_gtk_cell_renderer_event_parent_class)-> finalize (object); } static void jana_gtk_cell_renderer_event_class_init (JanaGtkCellRendererEventClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkCellRendererClass *renderer_class = GTK_CELL_RENDERER_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkCellRendererEventPrivate)); object_class->get_property = jana_gtk_cell_renderer_event_get_property; object_class->set_property = jana_gtk_cell_renderer_event_set_property; object_class->dispose = jana_gtk_cell_renderer_event_dispose; object_class->finalize = jana_gtk_cell_renderer_event_finalize; renderer_class->get_size = cell_renderer_event_get_size; renderer_class->render = cell_renderer_event_render; g_object_class_install_property ( object_class, PROP_STYLE_HINT, g_param_spec_string ( "style_hint", "gchar *", "The style hint to use when drawing.", "button", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_UID, g_param_spec_string ( "uid", "gchar *", "The UID of the represented event.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CATEGORIES, g_param_spec_boxed ( "categories", "gchar **", "A list of category strings.", G_TYPE_STRV, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_SUMMARY, g_param_spec_string ( "summary", "gchar *", "The summary of the represented event.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_LOCATION, g_param_spec_string ( "location", "gchar *", "The location of the represented event.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DESCRIPTION, g_param_spec_string ( "description", "gchar *", "The description of the represented event.", NULL, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_START, g_param_spec_object ( "start", "JanaTime *", "The starting time of the represented event.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_END, g_param_spec_object ( "end", "JanaTime *", "The ending time of the represented event.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_FIRST_INSTANCE, g_param_spec_boolean ( "first-instance", "gboolean", "If this is the first instance of this event.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_LAST_INSTANCE, g_param_spec_boolean ( "last-instance", "gboolean", "If this is the last instance of this event.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HAS_RECURRENCES, g_param_spec_boolean ( "has_recurrences", "gboolean", "Whether the represented event has recurrences.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HAS_ALARM, g_param_spec_boolean ( "has_alarm", "gboolean", "Whether the represented event has an alarm.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_TEXT, g_param_spec_boolean ( "draw_text", "gboolean", "Whether to draw text.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_DETAIL, g_param_spec_boolean ( "draw_detail", "gboolean", "Whether to draw description.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_TIME, g_param_spec_boolean ( "draw_time", "gboolean", "Whether to draw the time of the represented event " "textually.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_BOX, g_param_spec_boolean ( "draw_box", "gboolean", "Whether to draw a box around the represented event.", TRUE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_DRAW_RESIZE, g_param_spec_boolean ( "draw_resize", "gboolean", "Whether to draw a resize grip.", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_ROW, g_param_spec_pointer ( "row", "GtkTreeRowReference *", "A reference to a row in a JanaGtkEventStore to get " "data from.", G_PARAM_WRITABLE)); g_object_class_install_property ( object_class, PROP_XPAD_INNER, g_param_spec_uint ( "xpad_inner", "gint", "Inner padding on the x-axis, in pixels.", 0, G_MAXUINT, 3, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_YPAD_INNER, g_param_spec_uint ( "ypad_inner", "gint", "Inner padding on the y-axis, in pixels.", 0, G_MAXUINT, 3, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CELL_WIDTH, g_param_spec_int ( "cell_width", "gint", "Width the cell should try to size itself for.", -G_MAXINT, G_MAXINT, -1, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_CATEGORY_COLOR_HASH, g_param_spec_boxed ( "category_color_hash", "GHashTable *", "A mapping of category strings to GdkColors.", G_TYPE_HASH_TABLE, G_PARAM_READWRITE)); } static void jana_gtk_cell_renderer_event_init (JanaGtkCellRendererEvent *self) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (self); priv->style_hint = g_strdup ("button"); priv->draw_text = TRUE; priv->draw_detail = TRUE; priv->draw_box = TRUE; priv->xpadi = 3; priv->ypadi = 3; priv->cell_width = -1; priv->first_instance = TRUE; priv->last_instance = TRUE; } static PangoLayout * get_summary_layout (JanaGtkCellRendererEvent *cell, GtkWidget *widget, GdkRectangle *area) { gchar *string, *time_string; PangoLayout *layout; JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (cell); if ((!priv->summary) && (!priv->draw_time)) return NULL; if (priv->draw_time) { if (priv->start && priv->first_instance) { if (priv->end && priv->last_instance) { time_string = g_strdup_printf ( "" "[%02d:%02d]-[%02d:%02d]" " ", jana_time_get_hours (priv->start), jana_time_get_minutes (priv->start), jana_time_get_hours (priv->end), jana_time_get_minutes (priv->end)); } else { time_string = g_strdup_printf ( "" "[%02d:%02d]-[...]" " ", jana_time_get_hours (priv->start), jana_time_get_minutes (priv->start)); } } else { if (priv->end && priv->last_instance) { time_string = g_strdup_printf ( "" "[...]-[%02d:%02d]" " ", jana_time_get_hours (priv->end), jana_time_get_minutes (priv->end)); } else { time_string = g_strdup_printf ( "" "[...] "); } } } else { time_string = NULL; } string = g_strconcat (time_string ? time_string : "", priv->summary ? priv->summary : "", NULL); layout = gtk_widget_create_pango_layout (widget, NULL); pango_layout_set_width (layout, area->width * PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); pango_layout_set_markup (layout, string, -1); return layout; } static PangoLayout * get_description_layout (JanaGtkCellRendererEvent *cell, GtkWidget *widget, GdkRectangle *area) { gint el_width, height; PangoLayout *layout; PangoAttrList *attrs; PangoAttribute *size; JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (cell); if (((!priv->description) && (!priv->location)) || (!priv->draw_detail)) return NULL; /* Make Pango attribute list for small text */ attrs = pango_attr_list_new (); size = pango_attr_size_new (pango_font_description_get_size ( widget->style->font_desc) * PANGO_SCALE_SMALL); size->start_index = 0; size->end_index = G_MAXUINT; pango_attr_list_change (attrs, size); /* Measure the width of the '...' string */ layout = gtk_widget_create_pango_layout (widget, "..."); pango_layout_set_attributes (layout, attrs); pango_layout_get_pixel_size (layout, &el_width, NULL); g_object_unref (layout); /* Make the description layout */ if (priv->location) { gchar *string = g_strdup_printf ("%s%s%s", priv->location, priv->description ? "\n" : "", priv->description ? priv->description : ""); layout = gtk_widget_create_pango_layout (widget, string); g_free (string); } else { layout = gtk_widget_create_pango_layout ( widget, priv->description); } pango_layout_set_attributes (layout, attrs); pango_attr_list_unref (attrs); pango_layout_set_width (layout, area->width * PANGO_SCALE); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); /* Manual ellipsis for multiple-line layouts */ /* TODO: Width for height, natural size */ pango_layout_get_pixel_size (layout, NULL, &height); if (height > area->height) { PangoLayoutIter *iter = pango_layout_get_iter (layout); gint line_n = 0; height = 0; if (pango_layout_get_line_count (layout) <= 1) { pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); } else do { PangoRectangle rect; PangoLayoutLine *line = pango_layout_iter_get_line_readonly (iter); gint descent; pango_layout_line_get_pixel_extents (line, NULL, &rect); height += rect.height; descent = PANGO_DESCENT (rect); if (descent < 0) descent = 0; if (height + descent > area->height) { gchar *string_short, *string_ellip, *end_string; gint width; if (line_n == 0) { pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); break; } /* Get previous line */ line = pango_layout_get_line (layout, line_n - 1); pango_layout_line_ref (line); /* Do ellipsis */ end_string = priv->description + line->start_index + line->length; pango_layout_line_get_pixel_extents (line, NULL, &rect); /* Find out if the line wrapped */ if (area->width - (rect.x + rect.width) <= el_width) { do { gint length; /* FIXME: Something faster..? */ /* Cut off characters from the * end of the string until we * have enough space to append * ellipsis. */ /* Cut off a character */ end_string = g_utf8_offset_to_pointer ( end_string, -1); length = (priv->description + line->start_index + line->length) - end_string; /* Safe-guard - if we reach * the start of the line, break */ if (length <= 1) break; /* Measure the string we've * cut off. */ pango_layout_set_text (layout, end_string, length); pango_layout_get_pixel_extents ( layout, NULL, &rect); width = rect.width; } while (width <= el_width); } pango_layout_line_unref (line); if (end_string <= priv->description) { pango_layout_iter_free (iter); g_object_unref (layout); return NULL; } string_short = g_strndup (priv->description, end_string - priv->description); string_ellip = g_strconcat ( string_short, "...", NULL); pango_layout_set_text ( layout, string_ellip, -1); g_free (string_short); g_free (string_ellip); break; } line_n ++; } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); } return layout; } static void cell_renderer_event_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) { GtkStateType state; guint xpad, ypad; gint w, h, x, y; GtkStyle *style; PangoLayout *layout; GdkRectangle text_clip; JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (cell); if ((!priv->draw_box) && (!priv->draw_text)) return; if (flags & GTK_CELL_RENDERER_INSENSITIVE) state = GTK_STATE_INSENSITIVE; else if (flags & GTK_CELL_RENDERER_SELECTED) state = GTK_STATE_ACTIVE; else if (flags & GTK_CELL_RENDERER_PRELIT) state = GTK_STATE_PRELIGHT; else state = GTK_STATE_NORMAL; g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL); /* Check if there's enough allocated space to draw in */ w = cell_area->width - (xpad * 2); h = cell_area->height - (ypad * 2); x = cell_area->x + xpad; y = cell_area->y + ypad; if ((w <= 0) || (h <= 0)) return; if ((!priv->draw_box) || (!priv->category_color_hash) || (!priv->categories) || (!priv->categories[0])) { style = widget->style; } else { GdkColor *color; color = g_hash_table_lookup ( priv->category_color_hash, priv->categories[0]); style = gtk_style_copy (widget->style); if (color) { gint intensity, avg; style->bg[state] = *color; switch (state) { case GTK_STATE_INSENSITIVE : /* De-saturated */ avg = (((gint)color->red*3)+ ((gint)color->green*6)+ (gint)color->blue)/10; style->bg[state].red = (style->bg[state].red + avg)/2; style->bg[state].green = (style->bg[state].green + avg)/2; style->bg[state].blue = (style->bg[state].blue + avg)/2; break; case GTK_STATE_ACTIVE : /* Darkened */ style->bg[state].red = ((gint)style->bg[state].red*4)/5; style->bg[state].green = ((gint)style->bg[state].green*4)/5; style->bg[state].blue = ((gint)style->bg[state].blue*4)/5; break; case GTK_STATE_PRELIGHT : /* Brightened */ avg = G_MAXUINT16; style->bg[state].red = (style->bg[state].red + avg)/2; style->bg[state].green = (style->bg[state].green + avg)/2; style->bg[state].blue = (style->bg[state].blue + avg)/2; break; default : break; } /* Grey out text if it's insensitive */ if (state == GTK_STATE_INSENSITIVE) { style->fg[state].red = G_MAXUINT16/2; style->fg[state].green = G_MAXUINT16/2; style->fg[state].blue = G_MAXUINT16/2; } else { /* Choose text colour (black/white) based on * rough background colour intensity */ intensity = (((gint)style->bg[state].red)+ ((gint)style->bg[state].green)+ (gint)style->bg[state].blue)/3; if (intensity > G_MAXUINT16/2) { style->fg[state] = style->black; } else { style->fg[state] = style->white; } } } style = gtk_style_attach (style, widget->window); } /* Draw event box */ if (priv->draw_box) { gtk_paint_box (style, window, state, (state == GTK_STATE_ACTIVE) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, expose_area, widget, priv->style_hint, x, y, w, h); } /* Draw event text */ if (priv->draw_text) { text_clip.x = x + priv->xpadi; text_clip.y = y + priv->ypadi; text_clip.width = w - (priv->xpadi * 2); text_clip.height = h - (priv->ypadi * 2); if ((text_clip.height > 0) && (text_clip.width > 0) && (layout = get_summary_layout ( JANA_GTK_CELL_RENDERER_EVENT (cell), widget, &text_clip))) { gtk_paint_layout (style, window, state, !priv->draw_box, &text_clip, widget, priv->style_hint, text_clip.x, text_clip.y, layout); pango_layout_get_pixel_size (layout, NULL, &h); text_clip.y += h; text_clip.height -= h; g_object_unref (layout); } if ((text_clip.height > 0) && (text_clip.width > 0) && (priv->draw_detail) && (layout = get_description_layout ( JANA_GTK_CELL_RENDERER_EVENT (cell), widget, &text_clip))) { gtk_paint_layout (style, window, state, !priv->draw_box, &text_clip, widget, priv->style_hint, text_clip.x, text_clip.y, layout); g_object_unref (layout); } } if ((priv->draw_box) && (priv->draw_resize)) { /* Draw resize grip */ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); x = cell_area->x + cell_area->width - w - xpad - (priv->xpadi/2); y = cell_area->y + cell_area->height - h - ypad - (priv->ypadi/2); if ((w + xpad + (priv->xpadi/2) <= cell_area->width) && (h + ypad + (priv->ypadi/2) <= cell_area->height)) gtk_paint_resize_grip (style, window, state, expose_area, widget, priv->style_hint, GDK_WINDOW_EDGE_SOUTH_EAST, x, y, w, h); } if (priv->draw_box && priv->category_color_hash && priv->categories && priv->categories[0]) { gtk_style_detach (style); } } static void cell_renderer_event_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { JanaGtkCellRendererEventPrivate *priv = CELL_RENDERER_EVENT_PRIVATE (cell); guint xpad, ypad; gint text_width, text_height/*, icon_width, icon_height*/; GdkRectangle area; PangoLayout *layout; if ((!priv->draw_box) && (!priv->draw_text)) { if (width) *width = 0; if (height) *height = 0; if (x_offset) *x_offset = 0; if (y_offset) *y_offset = 0; return; } if (cell_area) { /* TODO: Alignment? */ if (x_offset) *x_offset = 0; if (y_offset) *y_offset = 0; } /* Ask for at least enough room to draw the box with inner padding */ g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL); if (width) *width = ((priv->xpadi + xpad)*2); if (height) *height = ((priv->ypadi + ypad) * 2); if (!priv->draw_text) return; /* TODO: Width for height, natural size */ area.x = 0; area.y = 0; g_object_get (G_OBJECT (cell), "width", &area.width, NULL); if (area.width < 0) { if (cell_area) { area.width = cell_area->width; } else if (priv->cell_width >= 0) { area.width = priv->cell_width - (priv->xpadi + xpad) * 2; } else { area.width = G_MAXINT; } } else area.width -= (priv->xpadi + xpad) * 2; area.height = (cell_area && (cell_area->height >= 0)) ? cell_area->height : G_MAXINT; if ((layout = get_summary_layout (JANA_GTK_CELL_RENDERER_EVENT (cell), widget, &area))) { pango_layout_get_pixel_size (layout, &text_width, &text_height); if (height) *height += text_height; if (area.width == G_MAXINT) { area.width = text_width; if (width) *width += text_width; } g_object_unref (layout); } /* TODO: Alarm / recurrence icons */ /*gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height);*/ if (!priv->draw_detail) return; if ((layout = get_description_layout ( JANA_GTK_CELL_RENDERER_EVENT (cell), widget, &area))) { pango_layout_get_pixel_size (layout, &text_width, &text_height); if (height) *height += text_height; g_object_unref (layout); } } GtkCellRenderer* jana_gtk_cell_renderer_event_new (void) { return g_object_new (JANA_GTK_TYPE_CELL_RENDERER_EVENT, NULL); } jana/libjana-gtk/jana-gtk-note-store.c0000644000175000017500000002356711327631152020035 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "jana-gtk-note-store.h" G_DEFINE_TYPE (JanaGtkNoteStore, jana_gtk_note_store, GTK_TYPE_LIST_STORE) #define NOTE_STORE_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_GTK_TYPE_NOTE_STORE, \ JanaGtkNoteStorePrivate)) typedef struct _JanaGtkNoteStorePrivate JanaGtkNoteStorePrivate; struct _JanaGtkNoteStorePrivate { GHashTable *notes_hash; JanaStoreView *view; }; enum { PROP_VIEW = 1, }; static void jana_gtk_note_store_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (object); switch (property_id) { case PROP_VIEW : g_value_set_object (value, priv->view); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_note_store_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_VIEW : jana_gtk_note_store_set_view (JANA_GTK_NOTE_STORE (object), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_gtk_note_store_dispose (GObject *object) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (object); if (priv->view) { g_object_unref (priv->view); priv->view = NULL; } if (G_OBJECT_CLASS (jana_gtk_note_store_parent_class)->dispose) G_OBJECT_CLASS (jana_gtk_note_store_parent_class)->dispose ( object); } static void jana_gtk_note_store_finalize (GObject *object) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (object); g_hash_table_destroy (priv->notes_hash); G_OBJECT_CLASS (jana_gtk_note_store_parent_class)->finalize (object); } static void jana_gtk_note_store_class_init (JanaGtkNoteStoreClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaGtkNoteStorePrivate)); object_class->get_property = jana_gtk_note_store_get_property; object_class->set_property = jana_gtk_note_store_set_property; object_class->dispose = jana_gtk_note_store_dispose; object_class->finalize = jana_gtk_note_store_finalize; g_object_class_install_property ( object_class, PROP_VIEW, g_param_spec_object ( "view", "JanaStoreView *", "The JanaStoreView monitored.", G_TYPE_OBJECT, G_PARAM_READWRITE)); } static void note_store_free_iter (gpointer data) { g_slice_free (GtkTreeIter, data); } static gint jana_gtk_note_store_compare (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { JanaTime *created1, *created2; JanaGtkNoteStore *store = JANA_GTK_NOTE_STORE (user_data); gint result = 0; gtk_tree_model_get (GTK_TREE_MODEL (store), a, JANA_GTK_NOTE_STORE_COL_CREATED, &created1, -1); gtk_tree_model_get (GTK_TREE_MODEL (store), b, JANA_GTK_NOTE_STORE_COL_CREATED, &created2, -1); if (created1 && created2) result = jana_utils_time_compare (created1, created2, FALSE); if (created1) g_object_unref (created1); if (created2) g_object_unref (created2); return result; } static void jana_gtk_note_store_init (JanaGtkNoteStore *self) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (self); priv->view = NULL; priv->notes_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, note_store_free_iter); gtk_list_store_set_column_types (GTK_LIST_STORE (self), JANA_GTK_NOTE_STORE_COL_LAST, (GType []){G_TYPE_STRING, /* UID */ G_TYPE_STRV, /* CATEGORIES */ G_TYPE_STRING, /* AUTHOR */ G_TYPE_STRING, /* RECIPIENT */ G_TYPE_STRING, /* BODY */ G_TYPE_OBJECT, /* CREATED */ G_TYPE_OBJECT, /* MODIFIED */ }); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (self), JANA_GTK_NOTE_STORE_COL_CREATED, jana_gtk_note_store_compare, self, NULL); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self), JANA_GTK_NOTE_STORE_COL_CREATED, GTK_SORT_ASCENDING); } GtkTreeModel * jana_gtk_note_store_new (void) { return (GtkTreeModel *)g_object_new (JANA_GTK_TYPE_NOTE_STORE, NULL); } GtkTreeModel * jana_gtk_note_store_new_full (JanaStoreView *view) { return (GtkTreeModel *)g_object_new (JANA_GTK_TYPE_NOTE_STORE, "view", view, NULL); } static void note_store_added_cb (JanaStoreView *view, GList *components, JanaGtkNoteStore *store) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (store); for (; components; components = components->next) { gchar *uid, **categories, *author, *recipient, *body; JanaTime *creation, *modified; JanaNote *note; GtkTreeIter *iter; if (jana_component_get_component_type (JANA_COMPONENT ( components->data)) != JANA_COMPONENT_NOTE) { g_warning ("Non-note component encountered"); continue; } note = JANA_NOTE (components->data); iter = g_slice_new (GtkTreeIter); uid = jana_component_get_uid (JANA_COMPONENT (note)); categories = jana_component_get_categories ( JANA_COMPONENT (note)); author = jana_note_get_author (note); recipient = jana_note_get_recipient (note); body = jana_note_get_body (note); creation = jana_note_get_creation_time (note); modified = jana_note_get_modified_time (note); gtk_list_store_insert_with_values ( GTK_LIST_STORE (store), iter, 0, JANA_GTK_NOTE_STORE_COL_UID, uid, JANA_GTK_NOTE_STORE_COL_CATEGORIES, categories, JANA_GTK_NOTE_STORE_COL_AUTHOR, author, JANA_GTK_NOTE_STORE_COL_RECIPIENT, recipient, JANA_GTK_NOTE_STORE_COL_BODY, body, JANA_GTK_NOTE_STORE_COL_CREATED, creation, JANA_GTK_NOTE_STORE_COL_MODIFIED, modified, -1); g_hash_table_insert (priv->notes_hash, uid, iter); g_strfreev (categories); g_free (author); g_free (recipient); g_free (body); if (creation) g_object_unref (creation); if (modified) g_object_unref (modified); } } static void note_store_modified_cb (JanaStoreView *view, GList *components, JanaGtkNoteStore *store) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (store); for (; components; components = components->next) { gchar *uid, **categories, *author, *recipient, *body; JanaTime *creation, *modified; JanaNote *note; GtkTreeIter *iter; uid = jana_component_get_uid ( JANA_COMPONENT (components->data)); if (!(iter = g_hash_table_lookup (priv->notes_hash, uid))) { GList *one_comp; g_free (uid); g_warning ("Encountered unrecognised component, adding " "to local store"); one_comp = g_list_prepend (NULL, components->data); note_store_added_cb (view, one_comp, store); continue; } note = JANA_NOTE (components->data); categories = jana_component_get_categories ( JANA_COMPONENT (note)); author = jana_note_get_author (note); recipient = jana_note_get_recipient (note); body = jana_note_get_body (note); creation = jana_note_get_creation_time (note); modified = jana_note_get_modified_time (note); gtk_list_store_set (GTK_LIST_STORE (store), iter, JANA_GTK_NOTE_STORE_COL_CATEGORIES, categories, JANA_GTK_NOTE_STORE_COL_AUTHOR, author, JANA_GTK_NOTE_STORE_COL_RECIPIENT, recipient, JANA_GTK_NOTE_STORE_COL_BODY, body, JANA_GTK_NOTE_STORE_COL_CREATED, creation, JANA_GTK_NOTE_STORE_COL_MODIFIED, modified, -1); g_free (uid); g_strfreev (categories); g_free (author); g_free (recipient); g_free (body); if (creation) g_object_unref (creation); if (modified) g_object_unref (modified); } } static void note_store_removed_cb (JanaStoreView *view, GList *uids, JanaGtkNoteStore *store) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (store); for (; uids; uids = uids->next) { GtkTreeIter *iter; const gchar *uid = (const gchar *)uids->data; if (!(iter = g_hash_table_lookup (priv->notes_hash, uid))) { g_warning ("Unrecognised component removed from view"); continue; } gtk_list_store_remove (GTK_LIST_STORE (store), iter); g_hash_table_remove (priv->notes_hash, uid); } } void jana_gtk_note_store_set_view (JanaGtkNoteStore *store, JanaStoreView *view) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (store); if (priv->view) { g_signal_handlers_disconnect_by_func ( priv->view, note_store_added_cb, store); g_signal_handlers_disconnect_by_func ( priv->view, note_store_modified_cb, store); g_signal_handlers_disconnect_by_func ( priv->view, note_store_removed_cb, store); g_object_unref (priv->view); priv->view = NULL; g_hash_table_remove_all (priv->notes_hash); gtk_list_store_clear (GTK_LIST_STORE (store)); } if (view) { priv->view = g_object_ref (view); g_signal_connect (priv->view, "added", G_CALLBACK (note_store_added_cb), store); g_signal_connect (priv->view, "modified", G_CALLBACK (note_store_modified_cb), store); g_signal_connect (priv->view, "removed", G_CALLBACK (note_store_removed_cb), store); } } JanaStoreView * jana_gtk_note_store_get_view (JanaGtkNoteStore *store) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (store); return priv->view ? g_object_ref (priv->view) : NULL; } JanaStore * jana_gtk_note_store_get_store (JanaGtkNoteStore *self) { JanaGtkNoteStorePrivate *priv = NOTE_STORE_PRIVATE (self); if (priv->view) { return jana_store_view_get_store (priv->view); } else return NULL; } jana/libjana/0000755000175000017500000000000011327631152013300 5ustar paulliupaulliujana/libjana/jana-time.h0000644000175000017500000001020111327631152015310 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_TIME_H #define JANA_TIME_H #include #define JANA_TYPE_TIME (jana_time_get_type ()) #define JANA_TIME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_TIME, JanaTime)) #define JANA_IS_TIME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_TIME)) #define JANA_TIME_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_TIME, JanaTimeInterface)) #define JANA_TYPE_DURATION (jana_duration_get_type ()) typedef struct _JanaDuration JanaDuration; /** * JanaTime: * * The #JanaTime struct contains only private data. */ typedef struct _JanaTime JanaTime; /* dummy object */ typedef struct _JanaTimeInterface JanaTimeInterface; struct _JanaTimeInterface { GTypeInterface parent; guint8 (*get_seconds) (JanaTime *self); guint8 (*get_minutes) (JanaTime *self); guint8 (*get_hours) (JanaTime *self); guint8 (*get_day) (JanaTime *self); guint8 (*get_month) (JanaTime *self); guint16 (*get_year) (JanaTime *self); gboolean (*get_isdate) (JanaTime *self); gboolean (*get_daylight)(JanaTime *self); gchar * (*get_tzname) (JanaTime *self); glong (*get_offset) (JanaTime *self); void (*set_seconds) (JanaTime *self, gint seconds); void (*set_minutes) (JanaTime *self, gint minutes); void (*set_hours) (JanaTime *self, gint hours); void (*set_day) (JanaTime *self, gint day); void (*set_month) (JanaTime *self, gint month); void (*set_year) (JanaTime *self, gint year); void (*set_isdate) (JanaTime *self, gboolean isdate); void (*set_tzname) (JanaTime *self, const gchar *tzname); void (*set_offset) (JanaTime *self, glong offset); JanaTime * (*duplicate) (JanaTime *self); }; /** * JanaDuration: * @start: The start of the duration * @end: The end of the duration * * This struct specifies a time period. **/ struct _JanaDuration { JanaTime *start; JanaTime *end; }; GType jana_time_get_type (void); GType jana_duration_get_type (void); guint8 jana_time_get_seconds (JanaTime *self); guint8 jana_time_get_minutes (JanaTime *self); guint8 jana_time_get_hours (JanaTime *self); guint8 jana_time_get_day (JanaTime *self); guint8 jana_time_get_month (JanaTime *self); guint16 jana_time_get_year (JanaTime *self); gboolean jana_time_get_isdate (JanaTime *self); gboolean jana_time_get_daylight (JanaTime *self); gchar * jana_time_get_tzname (JanaTime *self); glong jana_time_get_offset (JanaTime *self); void jana_time_set_seconds (JanaTime *self, gint seconds); void jana_time_set_minutes (JanaTime *self, gint minutes); void jana_time_set_hours (JanaTime *self, gint hours); void jana_time_set_day (JanaTime *self, gint day); void jana_time_set_month (JanaTime *self, gint month); void jana_time_set_year (JanaTime *self, gint year); void jana_time_set_isdate (JanaTime *self, gboolean isdate); void jana_time_set_tzname (JanaTime *self, const gchar *tzname); void jana_time_set_offset (JanaTime *self, glong offset); JanaTime * jana_time_duplicate (JanaTime *self); JanaDuration * jana_duration_new (JanaTime *start, JanaTime *end); JanaDuration * jana_duration_copy (JanaDuration *duration); void jana_duration_set_start (JanaDuration *self, JanaTime *start); void jana_duration_set_end (JanaDuration *self, JanaTime *end); gboolean jana_duration_valid (JanaDuration *self); void jana_duration_free (JanaDuration *self); #endif /*JANA_TIME_H*/ jana/libjana/jana-component.c0000644000175000017500000001614711327631152016366 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-component * @short_description: A basic store component interface * * #JanaComponent is the basic interface for a component in a #JanaStore. * A component is uniquely identifiable, has a type and optionally, can store * custom properties as key-value pairs. */ #include "jana-component.h" static void jana_component_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } } GType jana_component_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaComponentInterface), jana_component_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaComponent", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } /** * jana_component_get_component_type: * @self: A #JanaComponent * * Get the #JanaComponentType of @self. The component type will * tell you if the component can be cast to a more specific type. * * Returns: The #JanaComponentType of @self. */ JanaComponentType jana_component_get_component_type (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)->get_component_type (self); } /** * jana_component_is_fully_represented: * @self: A #JanaComponent * * Determines whether the underlying data of @self is fully * represented by the libjana interface. If it isn't, there may be data * in the component that is not reachable via libjana and modifying the * object may destroy this data. * * Returns: %TRUE if the underlying data of @self is fully represented by the * libjana interface. */ gboolean jana_component_is_fully_represented (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)->is_fully_represented (self); } /** * jana_component_get_uid: * @self: A #JanaComponent * * Get a unique identifying string for @self. This can be used as the * key in a hash table and does not change when modifying the component. A * #JanaComponent that is not a part of a #JanaStore may not have a uid. * * This function returns a newly allocated string. To avoid this allocation * please use jana_component_peek_uid(). * * Returns: The unique identifier of @self. */ gchar * jana_component_get_uid (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)->get_uid (self); } /** * jana_component_peek_uid: * @self: A #JanaComponent * * Get a unique identifying string for @self. This can be used as the * key in a hash table and does not change when modifying the component. A * #JanaComponent that is not a part of a #JanaStore may not have a uid. * * Unlike jana_component_get_uid() this function does not return a newly * allocated string. It is owned internally and must not be freed or * modified. * * Returns: The unique identifier of @self. */ const gchar * jana_component_peek_uid (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)->peek_uid (self); } /** * jana_component_get_categories: * @self: A #JanaComponent * * Retrieves the list of categories this component is filed under. See * jana_component_set_categories(). * * Returns: A newly allocated, NULL-terminated string array, containing the * component categories, to be freed with g_strfreev(). */ gchar ** jana_component_get_categories (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)->get_categories (self); } /** * jana_component_set_categories: * @self: A #JanaComponent * @categories: A %NULL-terminated array of strings, or %NULL * * Sets or clears the component's category list, overriding any previous set. * list. @categories should be an array of %NULL-terminated UTF-8 strings, and * the final member of the array should be %NULL. */ void jana_component_set_categories (JanaComponent *self, const gchar **categories) { JANA_COMPONENT_GET_INTERFACE (self)->set_categories (self, categories); } /** * jana_component_supports_custom_props: * @self: A #JanaComponent * * Determines whether @self supports the setting and retrieval * of custom properties. * * Returns: %TRUE if @self supports custom properties, %FALSE otherwise. */ gboolean jana_component_supports_custom_props (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)-> supports_custom_props (self); } /** * jana_component_get_custom_props_list: * @self: A #JanaComponent * * Get a #GList of properties set on @self. The data component of each * list element contains an array of two strings. The first string is the * property name, the second the value. This list can be freed using * jana_component_props_list_free(). * * Returns: A #GList containing the properties set on @self. */ GList * jana_component_get_custom_props_list (JanaComponent *self) { return JANA_COMPONENT_GET_INTERFACE (self)-> get_custom_props_list (self); } /** * jana_component_get_custom_prop: * @self: A #JanaComponent * @name: The key name of the property * * Retrieve a custom property set on @self. * * Returns: A string associated with the custom property, @name, or %NULL * if the property has not been set. */ gchar * jana_component_get_custom_prop (JanaComponent *self, const gchar *name) { return JANA_COMPONENT_GET_INTERFACE (self)-> get_custom_prop (self, name); } /** * jana_component_set_custom_prop: * @self: A #JanaComponent * @name: The key name of the property * @value: The value of the property * * Set a property on @self. If the property has been set previously, the value * will be overwritten. Implementations of #JanaComponent may require that * property names conform to a particular specification. * * Returns: %TRUE if the property was set successfully, %FALSE otherwise. */ gboolean jana_component_set_custom_prop (JanaComponent *self, const gchar *name, const gchar *value) { return JANA_COMPONENT_GET_INTERFACE (self)-> set_custom_prop (self, name, value); } /** * jana_component_props_list_free: * @props: A property list returned by jana_component_get_custom_props_list() * * Frees a #JanaComponent property list, returned by * jana_component_get_custom_props_list(). */ void jana_component_props_list_free (GList *props) { while (props) { gchar **prop = (gchar **)props->data; g_free (prop[0]); g_free (prop[1]); g_free (prop); props = g_list_delete_link (props, props); } } jana/libjana/jana-note.c0000644000175000017500000001043711327631152015325 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-note * @short_description: A note/memo/journal component interface * @see_also: #JanaComponent * * #JanaNote is the interface for components that store miscellaneus textual * information. */ #include "jana-note.h" static void jana_note_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } } GType jana_note_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaNoteInterface), jana_note_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaNote", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } /** * jana_note_get_author: * @note: A #JanaNote * * Retrieves the author of the note. * * Returns: A newly allocated string containing the author of the note, * or %NULL. */ gchar * jana_note_get_author (JanaNote *note) { return JANA_NOTE_GET_INTERFACE (note)->get_author (note); } /** * jana_note_get_recipient: * @note: A #JanaNote * * Retrieves the recipient of the note. * * Returns: A newly allocated string containing the recipient of the note, * or %NULL. */ gchar * jana_note_get_recipient (JanaNote *note) { return JANA_NOTE_GET_INTERFACE (note)->get_recipient (note); } /** * jana_note_get_body: * @note: A #JanaNote * * Retrieves the note body. * * Returns: A newly allocated string containing the body of the note, or %NULL. */ gchar * jana_note_get_body (JanaNote *note) { return JANA_NOTE_GET_INTERFACE (note)->get_body (note); } /** * jana_note_get_creation_time: * @note: A #JanaNote * * Retrieves the creation time of the note. * * Returns: A #JanaTime filled with the creation time of the note. */ JanaTime * jana_note_get_creation_time (JanaNote *note) { return JANA_NOTE_GET_INTERFACE (note)->get_creation_time (note); } /** * jana_note_get_modified_time: * @note: A #JanaNote * * Retrieves the time of the last modification to this note. * * Returns: A #JanaTime filled with the last modification time of the note. */ JanaTime * jana_note_get_modified_time (JanaNote *note) { return JANA_NOTE_GET_INTERFACE (note)->get_modified_time (note); } /** * jana_note_set_author: * @note: A #JanaNote * @author: The author of the note, or %NULL * * Sets the author of the note. */ void jana_note_set_author (JanaNote *note, const gchar *author) { JANA_NOTE_GET_INTERFACE (note)->set_author (note, author); } /** * jana_note_set_recipient: * @note: A #JanaNote * @recipient: The recipient of the note, or %NULL * * Sets the recipient of the note. */ void jana_note_set_recipient (JanaNote *note, const gchar *recipient) { JANA_NOTE_GET_INTERFACE (note)->set_recipient (note, recipient); } /** * jana_note_set_body: * @note: A #JanaNote * @body: The note body * * Sets the body of the note. */ void jana_note_set_body (JanaNote *note, const gchar *body) { JANA_NOTE_GET_INTERFACE (note)->set_body (note, body); } /** * jana_note_set_creation_time: * @note: A #JanaNote * @time: A #JanaTime * * Sets the creation time of the note. The creation time is automatically set * to the current local time when created, but this allows it to be overridden. * This can be useful to back-date notes, for example, or to set a particular * timezone on a note. */ void jana_note_set_creation_time (JanaNote *note, JanaTime *time) { JANA_NOTE_GET_INTERFACE (note)->set_creation_time (note, time); } jana/libjana/jana-store-view.h0000644000175000017500000001034411327631152016466 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_STORE_VIEW_H #define JANA_STORE_VIEW_H #include #define JANA_TYPE_STORE_VIEW (jana_store_view_get_type ()) #define JANA_STORE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_STORE_VIEW,\ JanaStoreView)) #define JANA_IS_STORE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_STORE_VIEW)) #define JANA_STORE_VIEW_GET_INTERFACE(inst)\ (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_STORE_VIEW,\ JanaStoreViewInterface)) /** * JanaStoreView: * * The #JanaStoreView struct contains only private data. */ typedef struct _JanaStoreView JanaStoreView; /* Dummy object */ typedef struct _JanaStoreViewInterface JanaStoreViewInterface; #include #include /** * JanaStoreViewField: * @JANA_STORE_VIEW_SUMMARY: An event summary * @JANA_STORE_VIEW_LOCATION: An event location * @JANA_STORE_VIEW_DESCRIPTION: An event description * @JANA_STORE_VIEW_AUTHOR: A note author * @JANA_STORE_VIEW_RECIPIENT: A note recipient * @JANA_STORE_VIEW_BODY: A note body * @JANA_STORE_VIEW_CATEGORY: A component category * @JANA_STORE_VIEW_ANYFIELD: Match any field * * Enum values for different types of field to use in the * jana_store_view_set_match() function. Using field values for incorrect * #JanaComponent types can have undefined results. **/ typedef enum { JANA_STORE_VIEW_SUMMARY, JANA_STORE_VIEW_LOCATION, JANA_STORE_VIEW_DESCRIPTION, JANA_STORE_VIEW_AUTHOR, JANA_STORE_VIEW_RECIPIENT, JANA_STORE_VIEW_BODY, JANA_STORE_VIEW_CATEGORY, JANA_STORE_VIEW_ANYFIELD, } JanaStoreViewField; /** * JanaStoreViewMatch: * @field: The #JanaStoreViewField to match against * @data: The string to match with * * struct that represents a matching query, returned by * jana_store_view_add_match(). */ typedef struct { JanaStoreViewField field; gchar *data; } JanaStoreViewMatch; struct _JanaStoreViewInterface { GTypeInterface parent; void (*get_range) (JanaStoreView *self, JanaTime **start, JanaTime **end); void (*set_range) (JanaStoreView *self, JanaTime *start, JanaTime *end); JanaStoreViewMatch * (*add_match) (JanaStoreView *self, JanaStoreViewField field, const gchar *data); GList * (*get_matches) (JanaStoreView *self); void (*remove_match) (JanaStoreView *self, JanaStoreViewMatch *match); void (*clear_matches)(JanaStoreView *self); void (*start) (JanaStoreView *self); JanaStore * (*get_store) (JanaStoreView *self); /* Signals */ void (*added) (JanaStoreView *self, GList *components); void (*modified) (JanaStoreView *self, GList *components); void (*removed) (JanaStoreView *self, GList *uids); void (*progress) (JanaStoreView *self, gint percent); }; GType jana_store_view_get_type (void); void jana_store_view_get_range (JanaStoreView *self, JanaTime **start, JanaTime **end); void jana_store_view_set_range (JanaStoreView *self, JanaTime *start, JanaTime *end); JanaStoreViewMatch *jana_store_view_add_match (JanaStoreView *self, JanaStoreViewField field, const gchar *data); GList * jana_store_view_get_matches (JanaStoreView *self); void jana_store_view_remove_match (JanaStoreView *self, JanaStoreViewMatch *match); void jana_store_view_clear_matches (JanaStoreView *self); void jana_store_view_start (JanaStoreView *self); JanaStore * jana_store_view_get_store (JanaStoreView *self); #endif /* JANA_STORE_VIEW_H */ jana/libjana/jana-note.h0000644000175000017500000000507311327631152015332 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_NOTE_H #define JANA_NOTE_H #include #include #define JANA_TYPE_NOTE (jana_note_get_type ()) #define JANA_NOTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_NOTE, JanaNote)) #define JANA_IS_NOTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_NOTE)) #define JANA_NOTE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_NOTE, JanaNoteInterface)) /** * JanaNote: * * The #JanaNote struct contains only private data. */ typedef struct _JanaNote JanaNote; /* Dummy object */ typedef struct _JanaNoteInterface JanaNoteInterface; struct _JanaNoteInterface { GTypeInterface parent; /* Getter functions */ gchar * (*get_author) (JanaNote *self); gchar * (*get_recipient) (JanaNote *self); gchar * (*get_body) (JanaNote *self); JanaTime * (*get_creation_time) (JanaNote *self); JanaTime * (*get_modified_time) (JanaNote *self); /* Setter functions */ void (*set_author) (JanaNote *self, const gchar *author); void (*set_recipient)(JanaNote *self, const gchar *recipient); void (*set_body) (JanaNote *self, const gchar *body); void (*set_creation_time) (JanaNote *self, JanaTime *time); }; GType jana_note_get_type (void); gchar *jana_note_get_author (JanaNote *note); gchar *jana_note_get_recipient (JanaNote *note); gchar *jana_note_get_body (JanaNote *note); JanaTime *jana_note_get_creation_time (JanaNote *note); JanaTime *jana_note_get_modified_time (JanaNote *note); void jana_note_set_author (JanaNote *note, const gchar *author); void jana_note_set_recipient (JanaNote *note, const gchar *recipient); void jana_note_set_body (JanaNote *note, const gchar *body); void jana_note_set_creation_time (JanaNote *note, JanaTime *time); #endif /* JANA_NOTE_H */ jana/libjana/Makefile.am0000644000175000017500000000127311327631152015337 0ustar paulliupaulliuSUBDIRS = . doc localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" $(GOBJECT_CFLAGS) -Wall AM_LDFLAGS = $(GOBJECT_LIBS) -lm source_c = jana-component.c \ jana-event.c \ jana-note.c \ jana-store.c \ jana-store-view.c \ jana-task.c \ jana-time.c \ jana-utils.c source_h = jana.h \ jana-component.h \ jana-event.h \ jana-note.h \ jana-store.h \ jana-store-view.h \ jana-task.h \ jana-time.h \ jana-utils.h lib_LTLIBRARIES = libjana.la libjana_la_SOURCES = $(source_c) $(source_h) library_includedir=$(includedir)/jana/libjana library_include_HEADERS = $(source_h) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libjana.pc jana/libjana/jana-store.c0000644000175000017500000001030211327631152015503 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-store * @short_description: A component store interface * @see_also: #JanaComponent, #JanaStoreView * * #JanaStore is the interface for a component storage. A component store * has functions to add, modify and remove components, as well as query the * storage itself and retrieve specific components. */ #include "jana-store.h" static void jana_store_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /** * JanaStore::opened: * @store: the store that received the signal * * The ::opened signal is emitted after jana_store_open() * is called and the store is ready to be queried. **/ g_signal_new ("opened", G_OBJECT_CLASS_TYPE (g_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaStoreInterface, opened), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); initialized = TRUE; } } GType jana_store_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaStoreInterface), jana_store_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaStore", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } /** * jana_store_open: * @self: A #JanaStore * * Opens the store. Prior to opening a store, any #JanaStoreView on the store * will not receive any components and retrieval of components will fail. * This is an asynchronous call. When the store is open and ready, the ::opened * signal will be fired. Implementations of this function should return as * immediately as possible and do any lengthy processing in idle time, or in * a thread. */ void jana_store_open (JanaStore *self) { JANA_STORE_GET_INTERFACE (self)->open (self); } /** * jana_store_get_component: * @self: A #JanaStore * @uid: The UID of a #JanaComponent * * Retrieves a particular #JanaComponent using its unique identifier. * * Returns: The #JanaComponent requested, or %NULL if it does not exist in this * store. */ JanaComponent * jana_store_get_component (JanaStore *self, const gchar *uid) { return JANA_STORE_GET_INTERFACE (self)->get_component (self, uid); } /** * jana_store_get_view: * @self: A #JanaStore * * Retrieves a #JanaStoreView on this #JanaStore. * * Returns: A new #JanaStoreView. */ JanaStoreView * jana_store_get_view (JanaStore *self) { return JANA_STORE_GET_INTERFACE (self)->get_view (self); } /** * jana_store_add_component: * @self: A #JanaStore * @comp: The #JanaComponent * * Adds a component to the store. */ void jana_store_add_component (JanaStore *self, JanaComponent *comp) { return JANA_STORE_GET_INTERFACE (self)->add_component (self, comp); } /** * jana_store_modify_component: * @self: A #JanaStore * @comp: The #JanaComponent * * Updates the stored component with any changes made. Does nothing if the * component does not exist in the store. */ void jana_store_modify_component (JanaStore *self, JanaComponent *comp) { return JANA_STORE_GET_INTERFACE (self)->modify_component (self, comp); } /** * jana_store_remove_component: * @self: A #JanaStore * @comp: The #JanaComponent * * Removes a component from the store. Does nothing if the component does not * exist in the store. */ void jana_store_remove_component (JanaStore *self, JanaComponent *comp) { return JANA_STORE_GET_INTERFACE (self)->remove_component (self, comp); } jana/libjana/libjana.pc.in0000644000175000017500000000041111327631152015625 0ustar paulliupaulliuprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libjana Description: An interface library for time-related personal information Requires: gobject-2.0 Version: @VERSION@ Libs: -L${libdir} -ljana Cflags: -I${includedir}/jana jana/libjana/jana-utils.c0000644000175000017500000011552611327631152015525 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-utils * @short_description: A set of utility functions * * jana-utils contains a collection of utility functions related to, and * using the interfaces specified in libjana. */ #include #include #include #include #include #include "jana-utils.h" static const guint8 days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static gboolean locale_set = FALSE; /** * jana_utils_time_is_leap_year: * @year: A year * * Determines if @year is a leap year. * * Returns: %TRUE if @year is a leap year, %FALSE otherwise. */ gboolean jana_utils_time_is_leap_year (guint16 year) { /* See Wikipedia 'leap years': * if year modulo 400 is 0 then leap * else if year modulo 100 is 0 then no_leap * else if year modulo 4 is 0 then leap * else no_leap */ if ((!(year % 400)) || ((year % 100) && (!(year % 4)))) return TRUE; else return FALSE; } /** * jana_utils_time_days_in_month: * @year: A year * @month: A month * * Determines the amount of days in the given month and year. * * Returns: The amount of days in the given month and year. */ guint8 jana_utils_time_days_in_month (guint16 year, guint8 month) { if ((month == 2) && (jana_utils_time_is_leap_year (year))) return days_in_month[month-1] + 1; else return days_in_month[month-1]; } /** * jana_utils_time_day_of_week: * @time: A #JanaTime * * Determines the day of the week that @time occurs on. * * Returns: The day of the week that @time occurs on. */ GDateWeekday jana_utils_time_day_of_week (JanaTime *time) { GDateWeekday day; GDate *date; /* TODO: Write function to do this directly on a JanaTime */ date = jana_utils_time_to_gdate (time); day = g_date_get_weekday (date); g_date_free (date); return day; } /** * jana_utils_time_day_of_year: * @time: A #JanaTime * * Determines what day of the year @time is, where 1st January is the first * day of the year. * * Returns: The day of the year that @time is. */ guint jana_utils_time_day_of_year (JanaTime *time) { guint month, day; day = 0; for (month = 1; month < jana_time_get_month (time); month++) day += jana_utils_time_days_in_month ( jana_time_get_year (time), month); day += jana_time_get_day (time); return day; } /** * jana_utils_time_week_of_year: * @time: A #JanaTime * @week_starts_monday: %TRUE if the week begins on Monday, %FALSE if it * begins on Sunday * * Retrieves what week of the year @time occurs within. * * Returns: The week of the year @time occurs within. */ guint jana_utils_time_week_of_year (JanaTime *time, gboolean week_starts_monday) { guint week; GDate *date; /* TODO: Write function to do this directly on a JanaTime */ date = jana_utils_time_to_gdate (time); if (week_starts_monday) week = g_date_get_monday_week_of_year (date); else week = g_date_get_sunday_week_of_year (date); g_date_free (date); return week; } /** * jana_utils_time_set_start_of_week: * @start: A #JanaTime * * Moves @start backwards to the start of the week (Monday), if it isn't * already. * * Returns: The day of the week @start was on, before modification. */ GDateWeekday jana_utils_time_set_start_of_week (JanaTime *start) { GDateWeekday day = jana_utils_time_day_of_week (start); if (day) jana_time_set_day (start, jana_time_get_day (start) - (day - 1)); return day; } /** * jana_utils_time_set_end_of_week: * @end: A #JanaTime * * Moves @end forwards to the end of the week (Sunday), if it isn't already. * * Returns: The day of the week @end was on, before modification. */ GDateWeekday jana_utils_time_set_end_of_week (JanaTime *end) { GDateWeekday day = jana_utils_time_day_of_week (end); if (day) jana_time_set_day (end, jana_time_get_day (end) + (7 - day)); return day; } /** * jana_utils_time_to_gdate: * @time: A #JanaTime * * Converts a #JanaTime to a #GDate. * * Returns: A newly allocated #GDate, with fields set from @time. */ GDate * jana_utils_time_to_gdate (JanaTime *time) { GDate *date = g_date_new (); g_date_set_dmy (date, jana_time_get_day (time), jana_time_get_month (time), jana_time_get_year (time)); return date; } /** * jana_utils_time_to_tm: * @time: #JanaTime implementation * * Converts @time to a broken-down time structure, usable by libc time * functions. tm_gmtoff and tm_zone components of this structure are not * filled in, however, they can be completed using jana_time_get_offset() and * jana_time_get_tzname(). * * Returns: A broken-down time structure */ struct tm jana_utils_time_to_tm (JanaTime *time) { struct tm broken; memset (&broken, 0, sizeof (struct tm)); broken.tm_sec = jana_time_get_seconds (time); broken.tm_min = jana_time_get_minutes (time); broken.tm_hour = jana_time_get_hours (time); broken.tm_mday = jana_time_get_day (time); broken.tm_mon = jana_time_get_month (time) - 1; broken.tm_year = jana_time_get_year (time) - 1900; /* Normalise time (fills in details such as day of week, etc.) */ mktime (&broken); /* The time was already adjusted for DST, un-adjust */ /* FIXME: Is DST always one hour? Cursory investigation suggests yes */ if (broken.tm_isdst > 0) broken.tm_hour -= 1; return broken; } /** * jana_utils_strftime: * @time: #JanaTime implementation * @format: Time formatting string * * Create a formatted string of @time, using strftime() and @format. * * Returns: A newly allocated string, representing @time using @format, or * %NULL on failure. */ gchar * jana_utils_strftime (JanaTime *time, const gchar *format) { gchar *string; gint size; struct tm brokentime = jana_utils_time_to_tm (time); if ((size = strftime (NULL, G_MAXINT, format, &brokentime))) { string = g_malloc (size + 1); strftime (string, size + 1, format, &brokentime); return string; } else return NULL; } /** * jana_utils_time_compare: * @time1: A #JanaTime * @time2: A #JanaTime to compare with * @date_only: Whether to only consider date fields * * Compares @time1 to @time2, taking into account the offset field. * * Returns: -1 if @time1 occurs before @time2, 0 if @time1 is equal to @time2, * and 1 if @time1 is after @time2. */ gint jana_utils_time_compare (JanaTime *time1, JanaTime *time2, gboolean date_only) { JanaTime *time2_corrected; gint time1_part; guint8 seconds, minutes, hours, day, month; guint16 year; gboolean corrected = FALSE; /* Get time2 relative to time1 */ if (jana_time_get_offset (time1) == jana_time_get_offset (time2)) time2_corrected = time2; else { time2_corrected = jana_time_duplicate (time2); jana_time_set_offset (time2_corrected, jana_time_get_offset (time1)); corrected = TRUE; } year = jana_time_get_year (time2_corrected); month = jana_time_get_month (time2_corrected); day = jana_time_get_day (time2_corrected); if (!jana_time_get_isdate (time2_corrected)) { hours = jana_time_get_hours (time2_corrected); minutes = jana_time_get_minutes (time2_corrected); seconds = jana_time_get_seconds (time2_corrected); } else { hours = 0; minutes = 0; seconds = 0; } if (corrected) g_object_unref (time2_corrected); /* Check years */ time1_part = jana_time_get_year (time1); if (time1_part < year) return -1; else if (time1_part > year) return 1; /* Check months */ time1_part = jana_time_get_month (time1); if (time1_part < month) return -1; else if (time1_part > month) return 1; /* Check days */ time1_part = jana_time_get_day (time1); if (time1_part < day) return -1; else if (time1_part > day) return 1; if (date_only) return 0; if (jana_time_get_isdate (time1)) { if (hours || minutes || seconds) return -1; else return 0; } /* Check hours */ time1_part = jana_time_get_hours (time1); if (time1_part < hours) return -1; else if (time1_part > hours) return 1; /* Check minutes */ time1_part = jana_time_get_minutes (time1); if (time1_part < minutes) return -1; else if (time1_part > minutes) return 1; /* Check seconds */ time1_part = jana_time_get_seconds (time1); if (time1_part < seconds) return -1; else if (time1_part > seconds) return 1; return 0; } /** * jana_utils_time_copy: * @source: A #JanaTime to copy from * @dest: A #JanaTime to copy to * * Copies the contents of @source to @dest. This can be useful when you want * to duplicate a time without creating a new #JanaTime, or when you need * to convert a time between different implementations of #JanaTime. Fields * are set in such an order as to not cause normalisation to alter the time. * * Returns: @dest. */ JanaTime * jana_utils_time_copy (JanaTime *source, JanaTime *dest) { gchar *tzname; tzname = jana_time_get_tzname (source); jana_time_set_tzname (dest, tzname); g_free (tzname); jana_time_set_offset (dest, jana_time_get_offset (source)); jana_time_set_year (dest, jana_time_get_year (source)); jana_time_set_month (dest, jana_time_get_month (source)); jana_time_set_day (dest, jana_time_get_day (source)); jana_time_set_hours (dest, jana_time_get_hours (source)); jana_time_set_minutes (dest, jana_time_get_minutes (source)); jana_time_set_seconds (dest, jana_time_get_seconds (source)); jana_time_set_isdate (dest, jana_time_get_isdate (source)); return dest; } static gint days_between (gint year1, gint year2) { gint reverse = 0, year, days; if (year1 > year2) { reverse = year1; year1 = year2; year2 = reverse; } for (days = 0, year = year1; year < year2; year++) { if (jana_utils_time_is_leap_year (year)) days += 366; else days += 365; } return reverse ? -days : days; } /** * jana_utils_time_diff: * @t1: A #JanaTime * @t2: A #JanaTime * @year: Return location for difference in years, or %NULL * @month: Return location for difference in months, or %NULL * @day: Return location for difference in days, or %NULL * @hours: Return location for difference in hours, or %NULL * @minutes: Return location for difference in minutes, or %NULL * @seconds: Return location for difference in seconds, or %NULL * * Gets the difference between two times. Times are compared so that if @t2 is * later than @t1, the difference is positive. If a parameter is ommitted, the * result will be accumulated in the next nearest parameter. For example, * if there were a years difference between @t1 and @t2, but the @year * parameter was ommitted, the @month parameter will accumulate 12 months. * This function takes into account the relative time offsets of @t1 and @t2, * so no prior conversion is required. */ void jana_utils_time_diff (JanaTime *t1, JanaTime *t2, gint *year, gint *month, gint *day, gint *hours, gint *minutes, glong *seconds) { gboolean corrected = FALSE; if (year) *year = 0; if (month) *month = 0; if (day) *day = 0; if (hours) *hours = 0; if (minutes) *minutes = 0; if (seconds) *seconds = 0; if (jana_time_get_offset (t1) != jana_time_get_offset (t2)) { t2 = jana_time_duplicate (t2); jana_time_set_offset (t2, jana_time_get_offset (t1)); corrected = TRUE; } /* FIXME: Consider leap seconds? */ if (year) *year = jana_time_get_year (t2) - jana_time_get_year (t1); else if (month) *month = (jana_time_get_year (t2) - jana_time_get_year (t1)) * 12; else { gint days = days_between ( jana_time_get_year (t1), jana_time_get_year (t2)); if (day) *day = days; else if (hours) *hours = days * 24; else if (minutes) *minutes = days * 24 * 60; else if (seconds) *seconds = days * 24 * 60 * 60; } if (month) { *month += jana_time_get_month (t2) - jana_time_get_month (t1); } else { /* Count days in the month difference */ gint year, month, days; year = jana_time_get_year (t1); for (days = 0, month = jana_time_get_month (t1); month < jana_time_get_month (t2); month = (month % 12) + 1) { days += jana_utils_time_days_in_month (year, month); if (month == 12) year++; } if (day) *day += days; else if (hours) *hours += days * 24; else if (minutes) *minutes += days * 24 * 60; else if (seconds) *seconds += days * 24 * 60 * 60; } if (day) *day += jana_time_get_day (t2) - jana_time_get_day (t1); else if (hours) *hours += (jana_time_get_day (t2) - jana_time_get_day (t1)) * 24; else if (minutes) *minutes += (jana_time_get_day (t2) - jana_time_get_day (t1)) * 24 * 60; else if (seconds) *seconds += (jana_time_get_day (t2) - jana_time_get_day (t1)) * 24 * 60 * 60; if (hours) *hours += jana_time_get_hours (t2) - jana_time_get_hours (t1); else if (minutes) *minutes += (jana_time_get_hours (t2) - jana_time_get_hours (t1)) * 60; else if (seconds) *seconds += (jana_time_get_hours (t2) - jana_time_get_hours (t1)) * 60 * 60; if (minutes) *minutes += jana_time_get_minutes (t2) - jana_time_get_minutes (t1); else if (seconds) *seconds += (jana_time_get_minutes (t2) - jana_time_get_minutes (t1)) * 60; if (seconds) *seconds += jana_time_get_seconds (t2) - jana_time_get_seconds (t1); /* FIXME: Normalise? */ if (corrected) g_object_unref (t2); } /** * jana_utils_time_adjust: * @time: A #JanaTime * @year: Years to add to @time * @month: Months to add to @time * @day: Days to add to @time * @hours: Hours to add to @time * @minutes: Minutes to add to @time * @seconds: Seconds to add to @time * * A convenience function to adjust a time by a specified amount on each field. * The time will be adjusted in the order seconds, minutes, hours, days, months * and years. It is important to take into account how a time may be normalised * when adjusting. This function can be used in conjunction with * jana_utils_time_diff() to adjust one time to be equal to another, while * taking time offsets into account. */ void jana_utils_time_adjust (JanaTime *time, gint year, gint month, gint day, gint hours, gint minutes, gint seconds) { if (seconds) jana_time_set_seconds ( time, jana_time_get_seconds (time) + seconds); if (minutes) jana_time_set_minutes ( time, jana_time_get_minutes (time) + minutes); if (hours) jana_time_set_hours ( time, jana_time_get_hours (time) + hours); if (day) jana_time_set_day ( time, jana_time_get_day (time) + day); if (month) jana_time_set_month ( time, jana_time_get_month (time) + month); if (year) jana_time_set_year ( time, jana_time_get_year (time) + year); } /** * jana_utils_time_now: * @time: A #JanaTime to overwrite * * Retrieves the current time, with the timezone and offset set. * * Returns: @time. */ JanaTime * jana_utils_time_now (JanaTime *jtime) { time_t now_t = time (NULL); struct tm *now = localtime (&now_t); gchar *tzname = jana_utils_get_local_tzname (); jana_time_set_tzname (jtime, tzname); jana_time_set_offset (jtime, now->tm_gmtoff); g_free (tzname); jana_time_set_seconds (jtime, now->tm_sec); jana_time_set_minutes (jtime, now->tm_min); jana_time_set_hours (jtime, now->tm_hour); jana_time_set_day (jtime, now->tm_mday); jana_time_set_month (jtime, now->tm_mon + 1); jana_time_set_year (jtime, now->tm_year + 1900); return jtime; } /** * jana_utils_duration_contains: * @duration: A #JanaDuration * @time: A #JanaTime * * Determines whether @time occurs within @duration. * * Returns: %TRUE if @time occurs within @duration, %FALSE otherwise. */ gboolean jana_utils_duration_contains (JanaDuration *duration, JanaTime *time) { if ((jana_utils_time_compare (time, duration->start, FALSE) >= 0) && (jana_utils_time_compare (time, duration->end, FALSE) < 0)) return TRUE; else return FALSE; } static void copy_component_fields (JanaComponent *source, JanaComponent *dest) { gchar **string_list; string_list = jana_component_get_categories (source); jana_component_set_categories (dest, (const gchar **)string_list); g_strfreev (string_list); /* FIXME: Also copy custom component properties? */ } /** * jana_utils_event_copy: * @source: A #JanaEvent to copy from * @dest: A #JanaEvent to copy to * * Copies the contents of @source into @dest. This function copies all fields * of @source over those of @dest, taking into account whether alarms, * recurrences and custom properties are supported. * * Returns: @dest. */ JanaEvent * jana_utils_event_copy (JanaEvent *source, JanaEvent *dest) { gchar *string; JanaTime *time; string = jana_event_get_summary (source); jana_event_set_summary (dest, string); g_free (string); string = jana_event_get_description (source); jana_event_set_description (dest, string); g_free (string); string = jana_event_get_location (source); jana_event_set_location (dest, string); g_free (string); time = jana_event_get_start (source); jana_event_set_start (dest, time); g_object_unref (time); time = jana_event_get_end (source); jana_event_set_end (dest, time); g_object_unref (time); copy_component_fields ((JanaComponent *)source, (JanaComponent *)dest); if (jana_event_supports_alarm (dest) && jana_event_supports_alarm (source)) { if (jana_event_has_alarm (source)) { time = jana_event_get_alarm_time (source); jana_event_set_alarm (dest, time); g_object_unref (time); } else jana_event_set_alarm (dest, NULL); } if (jana_event_supports_recurrence (dest) && jana_event_supports_recurrence (source)) { if (jana_event_has_recurrence (source)) { JanaRecurrence *recur = jana_event_get_recurrence (source); jana_event_set_recurrence (dest, recur); jana_recurrence_free (recur); } else jana_event_set_recurrence (dest, NULL); } if (jana_event_supports_exceptions (dest) && jana_event_supports_exceptions (source)) { if (jana_event_has_exceptions (source)) { GList *exceptions = jana_event_get_exceptions (source); jana_event_set_exceptions (dest, exceptions); jana_exceptions_free (exceptions); } else jana_event_set_exceptions (dest, NULL); } return dest; } /** * jana_utils_note_copy: * @source: A #JanaNote to copy from * @dest: A #JanaNote to copy to * * Copies the contents of @source into @dest. This function copies all fields * of @source over those of @dest. * * Returns: @dest. */ JanaNote * jana_utils_note_copy (JanaNote *source, JanaNote *dest) { gchar *string; JanaTime *time; string = jana_note_get_author (source); jana_note_set_author (dest, string); g_free (string); string = jana_note_get_recipient (source); jana_note_set_recipient (dest, string); g_free (string); string = jana_note_get_body (source); jana_note_set_body (dest, string); g_free (string); time = jana_note_get_creation_time (source); jana_note_set_creation_time (dest, time); g_object_unref (time); copy_component_fields ((JanaComponent *)source, (JanaComponent *)dest); return dest; } /** * jana_utils_task_copy: * @source: A #JanaTask to copy from * @dest: A #JanaTask to copy to * * Copies the contents of @source into @dest. This function copies all fields * of @source over those of @dest. * * Returns: @dest. */ JanaTask * jana_utils_task_copy (JanaTask *source, JanaTask *dest) { gchar *string; JanaTime *time; gint priority; gboolean completed; string = jana_task_get_summary (source); jana_task_set_summary (dest, string); g_free (string); string = jana_task_get_description (source); jana_task_set_description (dest, string); g_free (string); completed = jana_task_get_completed (source); jana_task_set_completed (dest, completed); priority = jana_task_get_priority (source); jana_task_set_priority (dest, priority); time = jana_task_get_due_date (source); jana_task_set_due_date (dest, time); g_object_unref (time); copy_component_fields ((JanaComponent *)source, (JanaComponent *)dest); return dest; } static GList * jana_utils_event_get_instances_cb (JanaTime *start, JanaTime *end, JanaTime *range_start, JanaTime *range_end, glong offset) { JanaTime *instance_start, *instance_end; GList *instances = NULL; /* TODO: Exception support */ /* Split instances into days */ instance_start = jana_time_duplicate (start); jana_time_set_offset (instance_start, offset); instance_end = jana_time_duplicate (instance_start); jana_time_set_isdate (instance_end, TRUE); jana_time_set_day (instance_end, jana_time_get_day (instance_end) + 1); end = jana_time_duplicate (end); jana_time_set_offset (end, offset); while (jana_utils_time_compare (instance_start, end, FALSE) < 0) { JanaDuration *instance; if (jana_utils_time_compare (instance_end, end, FALSE) > 0) { g_object_unref (instance_end); instance_end = jana_time_duplicate (end); } if (((!range_end) || (jana_utils_time_compare ( instance_start, range_end, FALSE) < 0)) && ((!range_start) || (jana_utils_time_compare ( instance_end, range_start, FALSE) >= 0))) { instance = jana_duration_new ( instance_start, instance_end); instances = g_list_append (instances, instance); } else if (range_end && (jana_utils_time_compare ( instance_start, range_end, FALSE) >= 0)) break; jana_time_set_day (instance_start, jana_time_get_day ( instance_start) + 1); jana_time_set_day (instance_end, jana_time_get_day ( instance_end) + 1); jana_time_set_isdate (instance_start, TRUE); } g_object_unref (instance_start); g_object_unref (instance_end); g_object_unref (end); return instances; } /** * jana_utils_event_get_instances: * @event: A #JanaEvent * @range_start: The start boundary for instances, or %NULL for no boundary * @range_end: The end boundary for instances, or %NULL for no boundary * @offset: The offset, in seconds, to offset the event by * * Splits an event across each day it occurs, taking into account @offset, * and returns a list of #JanaDuration's for each day it occurs. The first and * last instances have their start and end adjusted correctly. If the event * doesn't occur over more than one day, the list will contain just one * duration whose start and end match the start and end of the event, adjusted * by @offset. If @range_end is %NULL and @event has an indefinite * recurrence, the recurrence will be ignored. This is to avoid * infinite loops; it is discouraged to call this function without bounds. * * Returns: A list of #JanaDuration's for each day @event occurs. This list * should be freed with jana_utils_instance_list_free(). */ GList * jana_utils_event_get_instances (JanaEvent *event, JanaTime *range_start, JanaTime *range_end, glong offset) { JanaTime *start, *end; GList *instances = NULL; if (jana_event_has_recurrence (event)) { gint range_year; JanaRecurrence *recur = jana_event_get_recurrence (event); start = jana_event_get_start (event); /* All recurrences re-occur yearly, so we can skip to the * same year as the range_start at least. * FIXME: Verify this is ok in the situation of events * starting on leap years... */ range_year = jana_time_get_year (range_start); if (jana_time_get_year (start) < range_year) { jana_time_set_year (start, range_year); } end = jana_event_get_end (event); /* Skip recurrences if an ending bound isn't set, or if the * interval is invalid */ if (((!range_end) && (!recur->end)) || (recur->interval == 0)) { instances = jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset); } else switch (recur->type) { case JANA_RECURRENCE_DAILY : while (((!recur->end) || (jana_utils_time_compare ( start, recur->end, TRUE) <= 0)) && ((!range_end) || (jana_utils_time_compare ( start, range_end, FALSE) < 0))) { instances = g_list_concat (instances, jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset)); /* Increment days by the interval size */ jana_time_set_day (start, jana_time_get_day (start) + recur->interval); jana_time_set_day (end, jana_time_get_day (end) + recur->interval); } break; case JANA_RECURRENCE_WEEKLY : while (((!recur->end) || (jana_utils_time_compare ( start, recur->end, TRUE) <= 0)) && ((!range_end) || (jana_utils_time_compare ( start, range_end, FALSE) < 0))) { gint i, day_adjust; GDateWeekday day; instances = g_list_concat (instances, jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset)); day = jana_utils_time_day_of_week (start); /* Skip weeks depending on interval */ if (recur->interval > 1) { gboolean skip = TRUE; /* Check if there are more occurences * left this week first */ for (i = day; i < 7; i++) { if (recur->week_days[i]) { skip = FALSE; break; } } /* If not, skip the appropriate amount * of weeks */ if (skip) { jana_time_set_day (start, jana_time_get_day ( start) + (7 * (recur->interval - 1))); jana_time_set_day (end, jana_time_get_day ( end) + (7 * (recur->interval - 1))); } } /* Figure out when the next occurrence is */ for (i = day % 7,day_adjust = 1; day_adjust < 7; i = (i + 1) % 7, day_adjust ++) { if (recur->week_days[i]) break; } jana_utils_time_adjust (start, 0, 0, day_adjust, 0, 0, 0); jana_utils_time_adjust (end, 0, 0, day_adjust, 0, 0, 0); } break; case JANA_RECURRENCE_MONTHLY : { gint nth_day = ((jana_time_get_day (start) - 1) / 7)+1; if ((jana_time_get_day (start) + 7) > jana_utils_time_days_in_month (jana_time_get_year ( start), jana_time_get_month (start))) { nth_day = -1; } while (((!recur->end) || (jana_utils_time_compare ( start, recur->end, TRUE) <= 0)) && ((!range_end) || (jana_utils_time_compare ( start, range_end, FALSE) < 0))) { instances = g_list_concat (instances, jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset)); /* Skip months depending on interval */ if (recur->interval > 1) { jana_time_set_month (start, jana_time_get_month (start) + (recur->interval - 1)); jana_time_set_month (end, jana_time_get_month (end) + (recur->interval - 1)); } if (recur->by_date) { /* Simple case,just add another month */ jana_time_set_month (start, jana_time_get_month (start)+1); jana_time_set_month (end, jana_time_get_month (end) + 1); } else { /* Less simple, get to the nth day of * the next month. */ gint month = jana_time_get_month ( start); gint weeks = 3; /* Start by adding 3 weeks */ jana_time_set_day (start, jana_time_get_day (start) + 21); /* Add weeks until we're into the next * month. */ while (jana_time_get_month (start) == month) { jana_time_set_day (start, jana_time_get_day ( start) + 7); weeks ++; } /* Apologies for the indenting that * follows :( */ /* Add weeks until we're onto the right * day. */ if (nth_day > 0) { /* 'nth day of month' style */ while ((((jana_time_get_day ( start) - 1) / 7)+1) != nth_day) { jana_time_set_day ( start, jana_time_get_day ( start) + 7); weeks ++; } } else { /* Last day of month style, * skip to the last day of the * month. */ while ((jana_time_get_day ( start) + 7) < jana_utils_time_days_in_month ( jana_time_get_year ( start), jana_time_get_month (start))) { jana_time_set_day ( start, jana_time_get_day ( start) + 7); weeks ++; } } /* Adjust end */ jana_time_set_day (end, jana_time_get_day (end) + (weeks * 7)); } } break; } case JANA_RECURRENCE_YEARLY : while (((!recur->end) || (jana_utils_time_compare ( start, recur->end, TRUE) <= 0)) && ((!range_end) || (jana_utils_time_compare ( start, range_end, FALSE) < 0))) { instances = g_list_concat (instances, jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset)); /* Increment years by the interval size */ jana_time_set_year (start, jana_time_get_year (start) + recur->interval); jana_time_set_year (end, jana_time_get_year (end) + recur->interval); } break; } jana_recurrence_free (recur); g_object_unref (start); g_object_unref (end); return instances; } else { start = jana_event_get_start (event); end = jana_event_get_end (event); instances = jana_utils_event_get_instances_cb ( start, end, range_start, range_end, offset); g_object_unref (start); g_object_unref (end); return instances; } } /** * jana_utils_component_insert_category: * @component: A #JanaComponent * @category: The category to insert * @position: The position to insert at * * Inserts a category in the category list of the given component, at the * given position. If @position is %-1, the category will be placed at the end * of the list. */ void jana_utils_component_insert_category (JanaComponent *component, const gchar *category, gint position) { gint i, j, size, length; gchar **categories; const gchar **new_categories; categories = jana_component_get_categories (component); length = categories ? g_strv_length (categories) : 0; size = sizeof (gchar *) * (length + 2); new_categories = g_slice_alloc0 (size); for (i = 0, j = 0; i < length; i++, j++) { if (i == position) { new_categories[j] = category; j++; } new_categories[j] = categories[i]; } if (i == j) new_categories[i] = category; jana_component_set_categories (component, new_categories); g_slice_free1 (size, new_categories); g_strfreev (categories); } /** * jana_utils_component_remove_category: * @component: A #JanaComponent * @category: The category to remove * * Removes the first occurrence of the given category from the component's * category list. * * Returns: %TRUE if a category was removed, %FALSE otherwise. */ gboolean jana_utils_component_remove_category (JanaComponent *component, const gchar *category) { gint i, j, size, length; gchar **categories; const gchar **new_categories; gboolean removed = FALSE; categories = jana_component_get_categories (component); if (!categories) return FALSE; length = g_strv_length (categories); size = sizeof (gchar *) * length; new_categories = g_slice_alloc0 (size); for (i = 0, j = 0; i < g_strv_length (categories); i++, j++) { if (strcmp (categories[i], category) == 0) j--; else new_categories[j] = categories[i]; } if (i != j) { removed = TRUE; jana_component_set_categories (component, new_categories); } g_slice_free1 (size, new_categories); g_strfreev (categories); return removed; } /** * jana_utils_component_has_category: * @component: A #JanaComponent * @category: The category to search for * * Checks if the specified component has a particular category set. * * Returns: %TRUE if that category exists, %FALSE otherwise. */ gboolean jana_utils_component_has_category (JanaComponent *component, const gchar *category) { gint i; gchar **categories; if (!category) return FALSE; categories = jana_component_get_categories (component); if (!categories) return FALSE; for (i = 0; i < g_strv_length (categories); i++) { if (strcmp (categories[i], category) == 0) { g_strfreev (categories); return TRUE; } } g_strfreev (categories); return FALSE; } /** * jana_utils_instance_list_free: * @instances: An instance list returned by jana_utils_event_get_instances() * * Frees an event instance list. See jana_utils_event_get_instances(). */ void jana_utils_instance_list_free (GList *instances) { while (instances) { jana_duration_free ((JanaDuration *)instances->data); instances = g_list_delete_link (instances, instances); } } /** * jana_utils_get_local_tzname: * * Retrieves the local timezone name using system functions. * * Returns: A newly allocated string with the local tzname. */ gchar * jana_utils_get_local_tzname () { static gboolean tzset_called = FALSE; if (!tzset_called) { tzset (); } return g_strdup_printf ("%s%s%s", tzname[0], (tzname[1]&&(tzname[1][0]!='\0')) ? "/" : "", (tzname[1]&&(tzname[1][0]!='\0')) ? tzname[1] : ""); } static const gchar *number_suffix (gint number) { if ((number == 11) || (number == 13)) return "th"; else switch (number % 10) { case 1 : return "st"; case 2 : return "nd"; case 3 : return "rd"; default : return "th"; } } /** * jana_utils_recurrence_to_string: * @recur: A #JanaRecurrence * @start: The start of the recurrence * * Creates a localised string that represents @recur in a human-readable * format. If @recur is %NULL, a string representing no recurrence * will be returned. If @start is %NULL, monthly recurrences will not be * fully described. * * Returns: A newly allocated string with the human-readable recurrence info */ gchar * jana_utils_recurrence_to_string (JanaRecurrence *recur, JanaTime *start) { /* This is gonna be really hard (impossible?) to localise... */ GString *string; gchar *returnval; if (!recur) return g_strdup ("None"); if (!locale_set) { setlocale (LC_TIME, ""); locale_set = TRUE; } string = g_string_new ("Every "); switch (recur->interval) { case 2 : g_string_append (string, "other "); break; case 3 : g_string_append (string, "third "); break; case 4 : g_string_append (string, "fourth "); break; case 5 : g_string_append (string, "fifth "); break; case 6 : g_string_append (string, "sixth "); break; case 7 : g_string_append (string, "seventh "); break; case 8 : g_string_append (string, "eigth "); break; case 9 : g_string_append (string, "ninth "); break; default : if (recur->interval > 9) { g_string_append_printf (string, "%d%s ", recur->interval, number_suffix (recur->interval)); } break; } switch (recur->type) { case JANA_RECURRENCE_DAILY : g_string_append (string, "day"); break; case JANA_RECURRENCE_WEEKLY : g_string_append (string, "week"); break; case JANA_RECURRENCE_MONTHLY : g_string_append (string, "month"); break; case JANA_RECURRENCE_YEARLY : g_string_append (string, "year"); break; } if (recur->type == JANA_RECURRENCE_WEEKLY) { gint day, days, count; gboolean first = TRUE; /* Count the recurring days so we can use 'and' before the last */ for (day = 0, days = 0; day < 7; day++) if (recur->week_days[day]) days++; if (days) g_string_append (string, ", on"); for (day = 0, count = 0; day < 7; day++) { if (recur->week_days[day]) { count ++; if (!first) { if (count == days) g_string_append ( string, " and"); else g_string_append (string, ","); } g_string_append_printf (string, " %s", nl_langinfo (DAY_1 + ((day + 1) % 7))); first = FALSE; } } } else if ((recur->type == JANA_RECURRENCE_MONTHLY) && (start)) { if (recur->by_date) { gint day = jana_time_get_day (start); g_string_append_printf (string, ", on the %d%s", day, number_suffix (day)); } else { gint nth_day = ((jana_time_get_day (start) - 1) / 7)+1; GDateWeekday day = jana_utils_time_day_of_week (start); g_string_append_printf (string, ", on the %d%s %s", nth_day, number_suffix (nth_day), nl_langinfo (DAY_1 + (day % 7))); } } if (recur->end) { g_string_append_printf (string, ", until %d/%d/%04d", jana_time_get_day (recur->end), jana_time_get_month (recur->end), jana_time_get_year (recur->end)); } returnval = string->str; g_string_free (string, FALSE); return returnval; } /** * jana_utils_recurrence_diff: * @r1: A #JanaRecurrence * @r2: The #JanaRecurrence to compare to * * Determines whether two recurrence rules are different. * * Returns: %TRUE if @r1 is different to @r2, %FALSE otherwise. */ gboolean jana_utils_recurrence_diff (JanaRecurrence *r1, JanaRecurrence *r2) { if ((!r1) && (!r2)) return FALSE; if ((!r1) || (!r2)) return TRUE; if ((r1->type == r2->type) && (r1->interval == r2->interval) && (r1->week_days[0] == r2->week_days[0]) && (r1->week_days[1] == r2->week_days[1]) && (r1->week_days[2] == r2->week_days[2]) && (r1->week_days[3] == r2->week_days[3]) && (r1->week_days[4] == r2->week_days[4]) && (r1->week_days[5] == r2->week_days[5]) && (r1->week_days[6] == r2->week_days[6]) && (r1->by_date == r2->by_date) && ((r1->end && r2->end && (jana_utils_time_compare (r1->end, r2->end, FALSE) == 0)) || ((!r1->end) && (!r2->end)))) return FALSE; else return TRUE; } /** * jana_utils_ab_day: * @day: The day number, where 0 is Monday, 1 is Tuesday, etc. * * Retrieves the first UTF-8 character of the abbreviated, locale-correct day * name, in a null-terminated string. The returned string must not be freed * and will be overwritten by subsequent calls to this function. * * Returns: A NULL-terminated string containing the * first character of the abbreviated day name. */ const gchar * jana_utils_ab_day (guint day) { static gchar character[5]; const gchar *abday, *firstchar; if (!locale_set) { setlocale (LC_TIME, ""); locale_set = TRUE; } abday = nl_langinfo (DAY_1 + ((day + 1)%7)); firstchar = g_utf8_next_char (abday); memcpy (character, abday, firstchar - abday); character[firstchar-abday] = '\0'; return character; } /** * jana_utils_time_daylight_hours: * @latitude: A latitude, in decimal degrees * @day_of_year: The day of the year * * Calculates the amount of hours of daylight one should expect at a particular * latitude and time of year. * * Returns: Hours of daylight */ gdouble jana_utils_time_daylight_hours (gdouble latitude, guint day_of_year) { static gboolean first_call = TRUE; static gdouble p[365]; /* See: * http://mathforum.org/library/drmath/view/56478.html * for an explanation of this formula. */ /* Note that there's a race condition here and this block could be * entered more than once, but it shouldn't matter. */ if (first_call) { gint i; for (i = 0; i < 365; i++) { p[i] = asin (0.39795 * cos (0.2163108 + 2 * atan ( 0.9671396 * tan (0.0086 * ((gdouble)i-186))))); } first_call = FALSE; } return 24 - 24 / M_PI * acos ((sin (0.8333 * M_PI/180) + sin ( latitude * M_PI/180) * sin (p[day_of_year])) / (cos (latitude * M_PI/180) * cos(p[day_of_year]))); } jana/libjana/jana-utils.h0000644000175000017500000000637211327631152015530 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_UTILS_H #define JANA_UTILS_H #include #include #include #include #include #include gboolean jana_utils_time_is_leap_year (guint16 year); guint8 jana_utils_time_days_in_month (guint16 year, guint8 month); GDateWeekday jana_utils_time_day_of_week (JanaTime *time); guint jana_utils_time_day_of_year (JanaTime *time); GDateWeekday jana_utils_time_set_start_of_week (JanaTime *start); GDateWeekday jana_utils_time_set_end_of_week (JanaTime *end); guint jana_utils_time_week_of_year (JanaTime *time, gboolean week_starts_monday); GDate * jana_utils_time_to_gdate (JanaTime *time); gchar * jana_utils_strftime (JanaTime *time, const gchar *format); gint jana_utils_time_compare (JanaTime *time1, JanaTime *time2, gboolean date_only); JanaTime * jana_utils_time_copy (JanaTime *source, JanaTime *dest); void jana_utils_time_diff (JanaTime *t1, JanaTime *t2, gint *year, gint *month, gint *day, gint *hours, gint *minutes, glong *seconds); void jana_utils_time_adjust (JanaTime *time, gint year, gint month, gint day, gint hours, gint minutes, gint seconds); JanaTime * jana_utils_time_now (JanaTime *time); gboolean jana_utils_duration_contains (JanaDuration *duration, JanaTime *time); JanaEvent * jana_utils_event_copy (JanaEvent *source, JanaEvent *dest); JanaNote * jana_utils_note_copy (JanaNote *source, JanaNote *dest); JanaTask * jana_utils_task_copy (JanaTask *source, JanaTask *dest); GList * jana_utils_event_get_instances (JanaEvent *event, JanaTime *range_start, JanaTime *range_end, glong offset); void jana_utils_component_insert_category (JanaComponent *component, const gchar *category, gint position); gboolean jana_utils_component_remove_category (JanaComponent *component, const gchar *category); gboolean jana_utils_component_has_category (JanaComponent *component, const gchar *category); void jana_utils_instance_list_free (GList *instances); gchar * jana_utils_get_local_tzname (); struct tm jana_utils_time_to_tm (JanaTime *time); gchar * jana_utils_recurrence_to_string (JanaRecurrence *recur, JanaTime *start); gboolean jana_utils_recurrence_diff (JanaRecurrence *r1, JanaRecurrence *r2); const gchar * jana_utils_ab_day (guint day); gdouble jana_utils_time_daylight_hours (gdouble latitude, guint day_of_year); #endif /* JANA_UTILS_H */ jana/libjana/jana-store-view.c0000644000175000017500000001626411327631152016470 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-store-view * @short_description: A store query interface * @see_also: #JanaStore * * #JanaStoreView is the interface for a query, or 'view' on a #JanaStore. A * store view has functions to query a particular time range of components. */ #include "jana-store-view.h" enum { ADDED, MODIFIED, REMOVED, LAST_SIGNAL }; static void jana_store_view_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /** * JanaStoreView::added: * @store_view: the store view that received the signal * @components: A list of #JanaComponents * * The ::added signal is emitted when new components become * visible in the scope of the store view. **/ g_signal_new ("added", G_OBJECT_CLASS_TYPE (g_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaStoreViewInterface, added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * JanaStoreView::modified: * @store_view: the store view that received the signal * @components: A list of #JanaComponents * * The ::modified signal is emitted when components that were * previously in view have been modified in some way. **/ g_signal_new ("modified", G_OBJECT_CLASS_TYPE (g_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaStoreViewInterface, modified), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * JanaStoreView::removed: * @store_view: the store view that received the signal * @uids: A list of uids * * The ::removed signal is emitted when components that were * previously in view have been removed from the underling * #JanaStore. **/ g_signal_new ("removed", G_OBJECT_CLASS_TYPE (g_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaStoreViewInterface, removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * JanaStoreView::progress: * @store_view: the store view that received the signal * @percent: Percentage completion of the current running query * * The ::progress signal is emitted periodically as the * query progresses. When the query is complete, @percent will * be 100. **/ g_signal_new ("progress", G_OBJECT_CLASS_TYPE (g_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (JanaStoreViewInterface, progress), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); initialized = TRUE; } } GType jana_store_view_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaStoreViewInterface), jana_store_view_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaStoreView", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } /** * jana_store_view_get_range: * @self: A #JanaStoreView * @start: Return location for the start of the view range, or %NULL * @end: Return location for the end of the view range, or %NULL * * Retrieves the range over which this #JanaStoreView is set to span. A %NULL * start or end indicate an unbounded range. */ void jana_store_view_get_range (JanaStoreView *self, JanaTime **start, JanaTime **end) { JANA_STORE_VIEW_GET_INTERFACE (self)->get_range (self, start, end); } /** * jana_store_view_set_range: * @self: A #JanaStoreView * @start: The start of the range, or %NULL * @end: The end of the range, or %NULL * * Sets the range for the #JanaStoreView to span. A %NULL parameter indicates * that that end of the range should be unbounded (i.e. extended infinitely * into the past or future). For event stores, this query will match against * events that have occurences within this range; for note stores, this query * will match against notes that were created or modified within this range. */ void jana_store_view_set_range (JanaStoreView *self, JanaTime *start, JanaTime *end) { JANA_STORE_VIEW_GET_INTERFACE (self)->set_range (self, start, end); } /** * jana_store_view_add_match: * @self: A #JanaStoreView * @field: The field to match against * @data: The matching string to use * * Adds a matching query to the store view. This allows to search for components * whose fields contain a particular string. The matching is done disregarding * the case of letters in the string. @field must contain a field that matches * the component type being store by the underlying #JanaStore, otherwise * unexpected results may occur. * * Returns: A #JanaStoreViewMatch, representing the matching query. */ JanaStoreViewMatch * jana_store_view_add_match (JanaStoreView *self, JanaStoreViewField field, const gchar *data) { return JANA_STORE_VIEW_GET_INTERFACE (self)-> add_match (self, field, data); } /** * jana_store_view_get_matches: * @self: A #JanaStoreView * * Retrieves all matching queries that have been added to the store view. See * jana_store_view_add_match(). * * Returns: A newly allocated #GList, containing all the #JanaStoreViewMatch * structures added to the store view. This list must be freed with * g_list_free(). */ GList * jana_store_view_get_matches (JanaStoreView *self) { return JANA_STORE_VIEW_GET_INTERFACE (self)->get_matches (self); } /** * jana_store_view_remove_match: * @self: A #JanaStoreView * @match: A #JanaStoreViewMatch * * Removes a matching query from a store view. @match must have been returned * by jana_store_view_add_match(). */ void jana_store_view_remove_match (JanaStoreView *self, JanaStoreViewMatch *match) { JANA_STORE_VIEW_GET_INTERFACE (self)->remove_match (self, match); } /** * jana_store_view_clear_matches: * @self: A #JanaStoreView * * Removes all matching queries from a store view. */ void jana_store_view_clear_matches (JanaStoreView *self) { JANA_STORE_VIEW_GET_INTERFACE (self)->clear_matches (self); } /** * jana_store_view_start: * @self: A #JanaStoreView * * Starts the view. No signals will be emitted prior to calling this function. */ void jana_store_view_start (JanaStoreView *self) { JANA_STORE_VIEW_GET_INTERFACE (self)->start (self); } /** * jana_store_view_get_store: * @self: A #JanaStoreView * * Retrieves the #JanaStore that this view operates on. * * Returns: The #JanaStore that this view operates on. */ JanaStore * jana_store_view_get_store (JanaStoreView *self) { return JANA_STORE_VIEW_GET_INTERFACE (self)->get_store (self); } jana/libjana/jana-event.c0000644000175000017500000003055511327631152015504 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-event * @short_description: An event component interface * @see_also: #JanaComponent * * #JanaEvent is the interface for components that store information on * calendar events. It has functions for basic event description, as well as * recurrences, exceptions and alarms. */ #include #include "jana-event.h" static void jana_event_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } } GType jana_event_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaEventInterface), jana_event_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaEvent", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } GType jana_recurrence_get_type (void) { static GType our_type = 0; if (!our_type) our_type = g_boxed_type_register_static ("JanaRecurrence", (GBoxedCopyFunc) jana_recurrence_copy, (GBoxedFreeFunc) jana_recurrence_free); return our_type; } /** * jana_recurrence_new: * * Creates a new #JanaRecurrence. This will be an infinite, daily recurrence, * with an interval of 1. All other fields will be left %NULL or %FALSE. * * Returns: A newly allocated #JanaRecurrence, to be freed with * jana_recurrence_free(). */ JanaRecurrence * jana_recurrence_new () { JanaRecurrence *recur = g_slice_new0 (JanaRecurrence); /* JANA_RECURRENCE_DAILY is already zero, but set in case it changes */ recur->type = JANA_RECURRENCE_DAILY; recur->interval = 1; return recur; } /** * jana_recurrence_copy: * @recurrence: A #JanaRecurrence * * Creates a copy of a #JanaRecurrence. * * Returns: A newly allocated copy of @recurrence, to be freed with * jana_recurrence_free(). */ JanaRecurrence * jana_recurrence_copy (JanaRecurrence *recurrence) { JanaRecurrence *recurrence_copy; if (!recurrence) return NULL; recurrence_copy = jana_recurrence_new (); g_memmove (recurrence_copy, recurrence, sizeof (JanaRecurrence)); recurrence_copy->end = recurrence->end ? jana_time_duplicate (recurrence->end) : NULL; return recurrence_copy; } /** * jana_recurrence_free: * @recurrence: A #JanaRecurrence * * Frees the memory associated with @recurrence. If @recurrence is %NULL, * does nothing. */ void jana_recurrence_free (JanaRecurrence *recurrence) { if (!recurrence) return; if (recurrence->end) g_object_unref (recurrence->end); g_slice_free (JanaRecurrence, recurrence); } /** * jana_exceptions_free: * @exceptions: A list of exceptions, as returned by * jana_event_get_exceptions () * * Frees a list of exceptions. See jana_event_get_exceptions(). */ void jana_exceptions_free (GList *exceptions) { GList *e; for (e = exceptions; e; e = e->next) g_object_unref (G_OBJECT (e->data)); g_list_free (exceptions); } /** * jana_event_get_summary: * @self: A #JanaEvent * * Retrieves the summary associated with the event. * * Returns: A newly allocated string, containing the summary. * See jana_event_set_summary(). */ gchar * jana_event_get_summary (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_summary (self); } /** * jana_event_get_description: * @self: A #JanaEvent * * Retrieves the description associated with the event. * * Returns: A newly allocated string, containing the description. See * jana_event_set_description(). */ gchar * jana_event_get_description (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_description (self); } /** * jana_event_get_location: * @self: A #JanaEvent * * Retrieves the location associated with the event. Note that this is just * a field designated for a user-specified location, and as such, is not related * to time-zones and has no particular format. See jana_event_set_location(). * * Returns: A newly allocated string, containing the location. */ gchar * jana_event_get_location (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_location (self); } /** * jana_event_get_start: * @self: A #JanaEvent * * Retrieves the time at which the event starts. See jana_event_set_start(). * * Returns: A referenced #JanaTime for the start of the event. */ JanaTime * jana_event_get_start (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_start (self); } /** * jana_event_get_end: * @self: A #JanaEvent * * Retrieves the time at which the event ends. See jana_event_set_end(). * * Returns: A referenced #JanaTime for the end of the event. */ JanaTime * jana_event_get_end (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_end (self); } /** * jana_event_supports_alarm: * @self: A #JanaEvent * * Determines whether the event supports setting an alarm. * * Returns: %TRUE if the event supports setting an alarm, %FALSE otherwise. */ gboolean jana_event_supports_alarm (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->supports_alarm (self); } /** * jana_event_has_alarm: * @self: A #JanaEvent * * Determines whether the event has an alarm set on it. * * Returns: %TRUE if the event has an alarm set, %FALSE otherwise. */ gboolean jana_event_has_alarm (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->has_alarm (self); } /** * jana_event_get_alarm_time: * @self: A #JanaEvent * * Retrieves the alarm time set on the event. See jana_event_set_alarm_time(). * * Returns: A referenced #JanaTime for the alarm set on the event, or %NULL if * there is no alarm set. */ JanaTime * jana_event_get_alarm_time (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_alarm_time (self); } /** * jana_event_supports_recurrence: * @self: A #JanaEvent * * Determines whether the event supports setting a recurrence. * * Returns: %TRUE if the event supports setting a recurrence, %FALSE otherwise. */ gboolean jana_event_supports_recurrence (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->supports_recurrence (self); } /** * jana_event_has_recurrence: * @self: A #JanaEvent * * Determines whether the event has a set recurrence. * * Returns: %TRUE if the event has a set recurrence, %FALSE otherwise. */ gboolean jana_event_has_recurrence (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->has_recurrence (self); } /** * jana_event_get_recurrence: * @self: A #JanaEvent * * Retrieves the recurrence description set on the event. * * Returns: A newly allocated #JanaRecurrence, or %NULL if there is no * set recurrence. See jana_event_get_recurrence(). */ JanaRecurrence * jana_event_get_recurrence (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_recurrence (self); } /** * jana_event_supports_exceptions: * @self: A #JanaEvent * * Determines whether the event supports setting an exceptions list. * * Returns: %TRUE if the event supports setting exceptions, %FALSE otherwise. */ gboolean jana_event_supports_exceptions (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->supports_exceptions (self); } /** * jana_event_has_exceptions: * @self: A #JanaEvent * * Determines whether the event has an exceptions list. * * Returns: %TRUE if the event has an exceptions list, %FALSE otherwise. */ gboolean jana_event_has_exceptions (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->has_exceptions (self); } /** * jana_event_get_exceptions: * @self: A #JanaEvent * * Retrieves the event's exceptions list. See jana_event_set_exceptions(). * * Returns: A list of dates, as #JanaTime, on which the event does not occur, * or %NULL if there is no set exceptions list. This list should be freed with * jana_exceptions_free(). */ GList * jana_event_get_exceptions (JanaEvent *self) { return JANA_EVENT_GET_INTERFACE (self)->get_exceptions (self); } /** * jana_event_set_summary: * @self: A #JanaEvent * @summary: A summary string * * Sets the event's summary. Ideally, a summary should be a short, one-line * description of the event. */ void jana_event_set_summary (JanaEvent *self, const gchar *summary) { JANA_EVENT_GET_INTERFACE (self)->set_summary (self, summary); } /** * jana_event_set_description: * @self: A #JanaEvent * @description: A description string * * Sets the event's description. A description can elaborate on the event's * summary and include event details that do not fit, or are not appropriate * in other fields. */ void jana_event_set_description (JanaEvent *self, const gchar *description) { JANA_EVENT_GET_INTERFACE (self)->set_description (self, description); } /** * jana_event_set_location: * @self: A #JanaEvent * @location: A location string * * Sets the event's location. Ideally, a location should be a short, one-line * summary of the event's location. A full address would be more suited to the * description field (see jana_event_set_description()). */ void jana_event_set_location (JanaEvent *self, const gchar *location) { JANA_EVENT_GET_INTERFACE (self)->set_location (self, location); } /** * jana_event_set_start: * @self: A #JanaEvent * @start: A #JanaTime * * Sets the event's starting time. */ void jana_event_set_start (JanaEvent *self, JanaTime *start) { JANA_EVENT_GET_INTERFACE (self)->set_start (self, start); } /** * jana_event_set_end: * @self: A #JanaEvent * @end: A #JanaTime * * Sets the event's ending time. This should not occur on or before the * starting time. Setting an ending time before a starting time may cause * unpredictable results, depending on the implementation of #JanaEvent. */ void jana_event_set_end (JanaEvent *self, JanaTime *end) { JANA_EVENT_GET_INTERFACE (self)->set_end (self, end); } /** * jana_event_set_alarm: * @self: A #JanaEvent * @time: A #JanaTime, or %NULL * * Sets or clears the event's alarm time. This function does nothing if the * event does not support alarms. See jana_event_supports_alarm(). */ void jana_event_set_alarm (JanaEvent *self, JanaTime *time) { JANA_EVENT_GET_INTERFACE (self)->set_alarm (self, time); } /** * jana_event_set_recurrence: * @self: A #JanaEvent * @recurrence: A #JanaRecurrence, or %NULL * * Sets or clears the event's recurrence rule. This function does nothing if * the event does not support recurrence. See jana_event_supports_recurrence(). */ void jana_event_set_recurrence (JanaEvent *self, const JanaRecurrence *recurrence) { JANA_EVENT_GET_INTERFACE (self)->set_recurrence (self, recurrence); } /** * jana_event_set_exceptions: * @self: A #JanaEvent * @exceptions: A list of #JanaTime objects. * * Sets the event's exceptions list. For each #JanaTime in @exceptions, the * event is considered not to occur, even if its start/end or recurrence rule * would dictate otherwise. This function does nothing if the event does not * support exceptions. See jana_event_supports_exceptions(). */ void jana_event_set_exceptions (JanaEvent *self, GList *exceptions) { JANA_EVENT_GET_INTERFACE (self)->set_exceptions (self, exceptions); } /** * jana_event_get_categories: * @self: A #JanaEvent * * See jana_component_get_categories(). * * Deprecated: Use jana_component_get_categories() instead. * * Returns: A newly allocated, %NULL-terminated array of strings, or %NULL. */ gchar ** jana_event_get_categories (JanaEvent *self) { return jana_component_get_categories (JANA_COMPONENT (self)); } /** * jana_event_set_categories: * @self: A #JanaEvent * @categories: A %NULL-terminated array of strings, or %NULL * * See jana_component_set_categories(). * * Deprecated: Use jana_component_set_categories() instead. */ void jana_event_set_categories (JanaEvent *self, const gchar **categories) { jana_component_set_categories (JANA_COMPONENT (self), categories); } jana/libjana/jana-event.h0000644000175000017500000001476111327631152015512 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_EVENT_H #define JANA_EVENT_H #include #include #include #define JANA_TYPE_EVENT (jana_event_get_type ()) #define JANA_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_EVENT, JanaEvent)) #define JANA_IS_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_EVENT)) #define JANA_EVENT_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_EVENT, JanaEventInterface)) #define JANA_TYPE_RECURRENCE (jana_recurrence_get_type ()) /** * JanaEvent: * * The #JanaEvent struct contains only private data. */ typedef struct _JanaEvent JanaEvent; /* Dummy object */ typedef struct _JanaEventInterface JanaEventInterface; /** * JanaRecurrenceType: * @JANA_RECURRENCE_DAILY: A daily recurrence * @JANA_RECURRENCE_WEEKLY: A weekly recurrence * @JANA_RECURRENCE_MONTHLY: A monthly recurrence * @JANA_RECURRENCE_YEARLY: A yearly recurrence * * Enum values for different types of recurrence. * **/ typedef enum { JANA_RECURRENCE_DAILY, JANA_RECURRENCE_WEEKLY, JANA_RECURRENCE_MONTHLY, JANA_RECURRENCE_YEARLY, } JanaRecurrenceType; /** * JanaRecurrence: * @type: The type of recurrence. * @interval: The interval of the recurrence, where 1 is 'every', 2 is 'every * other', 3 is 'every third', etc. * @week_days: For weekly recurrence, this indicates which days the recurrence * happens on. The zeroth element in the array corresponds to a Monday and each * day follow sequentially. If @week_days is empty, the starting date of the * recurrence is assumed to be the day to occur on. If @week_days does not * include the starting day but includes other days, the recurrence will * occur on the starting day, then every week on the days specified in * @week_days after the starting day. * @by_date: For monthly recurrence, this indicates whether the * recurrence is by day or by date (i.e. First Monday of the month, or 1st of * the month). If @by_date is %FALSE, the day of the starting date will be * used to determine which day to occur on. If the starting date is the last * day in that month, the recurrence rule is treated as 'last x-day in month', * as not all months have the same amount of week-days. * @end: The ending time for the recurrence, or %NULL for indefinite recurrences * * This struct specifies a particular recurrence. **/ typedef struct { JanaRecurrenceType type; gint interval; gboolean week_days[7]; gboolean by_date; JanaTime * end; } JanaRecurrence; struct _JanaEventInterface { GTypeInterface parent; /* Standard parts of all events */ gchar * (*get_summary) (JanaEvent *self); gchar * (*get_description) (JanaEvent *self); gchar * (*get_location) (JanaEvent *self); JanaTime * (*get_start) (JanaEvent *self); JanaTime * (*get_end) (JanaEvent *self); /* Alarm-related */ gboolean (*supports_alarm) (JanaEvent *self); gboolean (*has_alarm) (JanaEvent *self); JanaTime * (*get_alarm_time) (JanaEvent *self); /* Recurrence-related */ gboolean (*supports_recurrence) (JanaEvent *self); gboolean (*has_recurrence) (JanaEvent *self); JanaRecurrence * (*get_recurrence) (JanaEvent *self); /* Exceptions related */ gboolean (*supports_exceptions) (JanaEvent *self); gboolean (*has_exceptions) (JanaEvent *self); /* A list of JanaTime dates on which the event doesn't occur */ GList * (*get_exceptions) (JanaEvent *self); /* Setter functions */ void (*set_summary) (JanaEvent *self, const gchar *summary); void (*set_description) (JanaEvent *self, const gchar *description); void (*set_location) (JanaEvent *self, const gchar *location); void (*set_start) (JanaEvent *self, JanaTime *start); void (*set_end) (JanaEvent *self, JanaTime *end); void (*set_alarm) (JanaEvent *self, JanaTime *time); void (*set_recurrence) (JanaEvent *self, const JanaRecurrence *recurrence); void (*set_exceptions) (JanaEvent *self, GList *exceptions); }; GType jana_event_get_type (void); GType jana_recurrence_get_type (void); JanaRecurrence * jana_recurrence_new (); JanaRecurrence * jana_recurrence_copy (JanaRecurrence *recurrence); void jana_recurrence_free (JanaRecurrence *recurrence); void jana_exceptions_free (GList *exceptions); gchar * jana_event_get_summary (JanaEvent *self); gchar * jana_event_get_description (JanaEvent *self); gchar * jana_event_get_location (JanaEvent *self); JanaTime * jana_event_get_start (JanaEvent *self); JanaTime * jana_event_get_end (JanaEvent *self); gchar ** jana_event_get_categories (JanaEvent *self); gboolean jana_event_supports_alarm (JanaEvent *self); gboolean jana_event_has_alarm (JanaEvent *self); JanaTime * jana_event_get_alarm_time (JanaEvent *self); gboolean jana_event_supports_recurrence (JanaEvent *self); gboolean jana_event_has_recurrence (JanaEvent *self); JanaRecurrence * jana_event_get_recurrence (JanaEvent *self); gboolean jana_event_supports_exceptions (JanaEvent *self); gboolean jana_event_has_exceptions (JanaEvent *self); GList * jana_event_get_exceptions (JanaEvent *self); void jana_event_set_summary (JanaEvent *self, const gchar *summary); void jana_event_set_description (JanaEvent *self, const gchar *description); void jana_event_set_location (JanaEvent *self, const gchar *location); void jana_event_set_start (JanaEvent *self, JanaTime *start); void jana_event_set_end (JanaEvent *self, JanaTime *end); void jana_event_set_categories (JanaEvent *self, const gchar **categories); void jana_event_set_alarm (JanaEvent *self, JanaTime *time); void jana_event_set_recurrence (JanaEvent *self, const JanaRecurrence *recurrence); void jana_event_set_exceptions (JanaEvent *self, GList *exceptions); #endif /* JANA_EVENT_H */ jana/libjana/jana-time.c0000644000175000017500000002776311327631152015330 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-time * @short_description: A time representation interface * * #JanaTime is the interface for representing a time. It has functions to set * all the components of a basic calendar time, including date and timezone. */ #include "jana-time.h" #include "jana-utils.h" static void jana_time_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } } GType jana_time_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaTimeInterface), jana_time_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaTime", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } /** * jana_time_get_seconds: * @self: A #JanaTime * * Get the seconds component of the time. See jana_time_set_seconds(). * * Returns: The seconds component of the time. */ guint8 jana_time_get_seconds (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_seconds (self); } /** * jana_time_get_minutes: * @self: A #JanaTime * * Get the minutes component of the time. See jana_time_set_minutes(). * * Returns: The minutes component of the time. */ guint8 jana_time_get_minutes (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_minutes (self); } /** * jana_time_get_hours: * @self: A #JanaTime * * Get the hours component of the time. See jana_time_set_hours(). * * Returns: The hours component of the time. */ guint8 jana_time_get_hours (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_hours (self); } /** * jana_time_get_day: * @self: A #JanaTime * * Get the day component of the time. See jana_time_set_day(). * * Returns: The day component of the time. */ guint8 jana_time_get_day (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_day (self); } /** * jana_time_get_month: * @self: A #JanaTime * * Get the month component of the time. See jana_time_set_month(). * * Returns: The month component of the time. */ guint8 jana_time_get_month (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_month (self); } /** * jana_time_get_year: * @self: A #JanaTime * * Get the year component of the time. See jana_time_set_year(). * * Returns: The year component of the time. */ guint16 jana_time_get_year (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_year (self); } /** * jana_time_get_isdate: * @self: A #JanaTime * * Determines whether the time has been set as a date-only time. See * jana_time_set_isdate(). * * Returns: %TRUE if the time should be considered as a date, %FALSE otherwise. */ gboolean jana_time_get_isdate (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_isdate (self); } /** * jana_time_get_daylight: * @self: A #JanaTime * * Determines whether the time is in daylight savings or not. See * jana_time_set_daylight(). * * Returns: %TRUE if the time is in daylight savings, %FALSE otherwise. */ gboolean jana_time_get_daylight (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_daylight (self); } /** * jana_time_get_tzname: * @self: A #JanaTime * * Retrieves the timezone of the time. See jana_time_set_tzname(). * * Returns: The timezone name, e.g. "GMT/BST", "EST", etc. */ gchar * jana_time_get_tzname (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_tzname (self); } /** * jana_time_get_offset: * @self: A #JanaTime * * Gets the UTC (Universal Time Co-ordinated) offset of the time, in seconds. * See jana_time_set_offset(). * * Returns: The offset, in seconds, over UTC. */ glong jana_time_get_offset (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->get_offset (self); } /** * jana_time_set_seconds: * @self: A #JanaTime * @seconds: The seconds component to set * * Sets the seconds component of the time. If the seconds parameter is invalid, * the time will be normalised. For example, a seconds parameter of -1 would * cause the minutes to be decreased by 1 and the seconds to be set to 59. If * normalisation causes the time to cross the daylight savings boundary of the * set timezone, the time will be adjusted accordingly. */ void jana_time_set_seconds (JanaTime *self, gint seconds) { JANA_TIME_GET_INTERFACE (self)->set_seconds (self, seconds); } /** * jana_time_set_minutes: * @self: A #JanaTime * @minutes: The minutes component to set * * Sets the minutes component of the time. If the minutes parameter is invalid, * the time will be normalised. For example, a minutes parameter of -1 would * cause the hours to be decreased by 1 and the minutes to be set to 59. If * normalisation causes the time to cross the daylight savings boundary of the * set timezone, the time will be adjusted accordingly. */ void jana_time_set_minutes (JanaTime *self, gint minutes) { JANA_TIME_GET_INTERFACE (self)->set_minutes (self, minutes); } /** * jana_time_set_hours: * @self: A #JanaTime * @hours: The hours component to set * * Sets the hours component of the time. If the hours parameter is invalid, * the time will be normalised. For example, an hours parameter of -1 would * cause the date to be decreased by 1 day and the hours to be set to 23. If * normalisation causes the time to cross the daylight savings boundary of the * set timezone, the time will be adjusted accordingly. */ void jana_time_set_hours (JanaTime *self, gint hours) { JANA_TIME_GET_INTERFACE (self)->set_hours (self, hours); } /** * jana_time_set_day: * @self: A #JanaTime * @day: The day component to set * * Sets the day component of the time. If the day parameter is invalid, * the time will be normalised. For example, a day parameter of 0 would * cause the date to be set to the last day of the previous month. If * normalisation causes the time to cross the daylight savings boundary of the * set timezone, the time will be adjusted accordingly. */ void jana_time_set_day (JanaTime *self, gint day) { JANA_TIME_GET_INTERFACE (self)->set_day (self, day); } /** * jana_time_set_month: * @self: A #JanaTime * @month: The month component to set * * Sets the month component of the time. If the day parameter is invalid, * the time will be normalised. For example, a month parameter of 0 would * cause the date to be set to the last month of the previous year. If * normalisation causes the time to cross the daylight savings boundary of the * set timezone, the time will be adjusted accordingly. */ void jana_time_set_month (JanaTime *self, gint month) { JANA_TIME_GET_INTERFACE (self)->set_month (self, month); } /** * jana_time_set_year: * @self: A #JanaTime * @year: The year component to set * * Sets the year component of the time. The time may be normalised in the * situation that the year is adjusted from a leap year to a non-leap year and * the month and day was set to the 29th of February. In this situation, the * month and day would be adjusted to the 1st of March. */ void jana_time_set_year (JanaTime *self, gint year) { JANA_TIME_GET_INTERFACE (self)->set_year (self, year); } /** * jana_time_set_isdate: * @self: A #JanaTime * @isdate: Whether the time should be considered only as a date * * Sets whether the time should be considered only as a date. The seconds, * minutes and hours components of the time are not guaranteed to be * preserved when @isdate is %TRUE. */ void jana_time_set_isdate (JanaTime *self, gboolean isdate) { JANA_TIME_GET_INTERFACE (self)->set_isdate (self, isdate); } /** * jana_time_set_tzname: * @self: A #JanaTime * @tzname: The timezone to set * * Sets the timezone of the time. The time offset will also be adjusted to an * offset that corresponds to the newly set timezone. If there is an offset * for the newly set timezone that is the same as the previously set offset, * the offset will remain unchanged. In addition, the time will be adjusted * by the difference between the old offset and the new offset. */ void jana_time_set_tzname (JanaTime *self, const gchar *tzname) { JANA_TIME_GET_INTERFACE (self)->set_tzname (self, tzname); } /** * jana_time_set_offset: * @self: A #JanaTime * @offset: The time offset to set * * Sets the offset of the time. The timezone will also be adjusted to a * zone that corresponds to the newly set offset. If there is a zone * for the newly set offset that is the same as the previously set zone, * the zone will remain unchanged. In addition, the time will be adjusted * by the difference between the old offset and the new offset. */ void jana_time_set_offset (JanaTime *self, glong offset) { JANA_TIME_GET_INTERFACE (self)->set_offset (self, offset); } /** * jana_time_duplicate: * @self: A #JanaTime * * Creates a copy of @self. * * Returns: A new copy of @self. */ JanaTime * jana_time_duplicate (JanaTime *self) { return JANA_TIME_GET_INTERFACE (self)->duplicate (self); } GType jana_duration_get_type (void) { static GType our_type = 0; if (!our_type) our_type = g_boxed_type_register_static ("JanaDuration", (GBoxedCopyFunc) jana_duration_copy, (GBoxedFreeFunc) jana_duration_free); return our_type; } /** * jana_duration_new: * @start: The start of the duration, or %NULL * @end: The end of the duration, or %NULL * * Creates a new #JanaDuration. * * Returns: A newly allocated #JanaDuration, to be freed with * jana_duration_free(). */ JanaDuration * jana_duration_new (JanaTime *start, JanaTime *end) { JanaDuration *duration = g_slice_new0 (JanaDuration); if (start) duration->start = jana_time_duplicate (start); if (end) duration->end = jana_time_duplicate (end); return duration; } /** * jana_duration_copy: * @duration: A #JanaDuration * * Create a copy of a #JanaDuration. * * Returns: A copy of @duration. */ JanaDuration * jana_duration_copy (JanaDuration *duration) { if (!duration) return NULL; return jana_duration_new (duration->start, duration->end); } /** * jana_duration_set_start: * @self: A #JanaDuration * @start: The start time, or %NULL * * Sets the start of the duration. */ void jana_duration_set_start (JanaDuration *self, JanaTime *start) { if (self->start) g_object_unref (self->start); self->start = start ? jana_time_duplicate (start) : NULL; } /** * jana_duration_set_end: * @self: A #JanaDuration * @end: The end time, or %NULL * * Sets the end of the duration. */ void jana_duration_set_end (JanaDuration *self, JanaTime *end) { if (self->end) g_object_unref (self->end); self->end = end ? jana_time_duplicate (end) : NULL; } /** * jana_duration_valid: * @self: A #JanaDuration * * Determines whether the duration is valid. For the duration to be valid, * the start and end must be set, and the end must occur on or after the start. * * Returns: %TRUE if the duration is valid, %FALSE otherwise. */ gboolean jana_duration_valid (JanaDuration *self) { if (self && self->start && self->end && jana_utils_time_compare (self->start, self->end, FALSE) <= 0) return TRUE; else return FALSE; } /** * jana_duration_free: * @self: A #JanaDuration * * Frees the memory associated with a #JanaDuration. */ void jana_duration_free (JanaDuration *self) { if (!self) return; g_object_unref (self->start); g_object_unref (self->end); g_slice_free (JanaDuration, self); } jana/libjana/jana-task.c0000644000175000017500000000541311327631152015320 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-task * @short_description: A task/todo component interface * @see_also: #JanaComponent * * #JanaTask is the interface for components that store task information. */ #include "jana-task.h" static void jana_task_base_init (gpointer g_class) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } } GType jana_task_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (JanaTaskInterface), jana_task_base_init, /* base_init */ NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "JanaTask", &info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } gchar * jana_task_get_summary (JanaTask *self) { return JANA_TASK_GET_INTERFACE (self)->get_summary (self); } gchar * jana_task_get_description (JanaTask *self) { return JANA_TASK_GET_INTERFACE (self)->get_description (self); } gboolean jana_task_get_completed (JanaTask *self) { return JANA_TASK_GET_INTERFACE (self)->get_completed (self); } JanaTime * jana_task_get_due_date (JanaTask *self) { return JANA_TASK_GET_INTERFACE (self)->get_due_date (self); } gint jana_task_get_priority (JanaTask *self) { return JANA_TASK_GET_INTERFACE (self)->get_priority (self); } void jana_task_set_summary (JanaTask *self, const gchar *summary) { JANA_TASK_GET_INTERFACE (self)->set_summary (self, summary); } void jana_task_set_description (JanaTask *self, const gchar *description) { JANA_TASK_GET_INTERFACE (self)->set_description (self, description); } void jana_task_set_completed (JanaTask *self, gboolean completed) { JANA_TASK_GET_INTERFACE (self)->set_completed (self, completed); } void jana_task_set_due_date (JanaTask *self, JanaTime *time) { JANA_TASK_GET_INTERFACE (self)->set_due_date (self, time); } void jana_task_set_priority (JanaTask *self, gint priority) { JANA_TASK_GET_INTERFACE (self)->set_priority (self, priority); } jana/libjana/jana-component.h0000644000175000017500000000716011327631152016366 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_COMPONENT_H #define JANA_COMPONENT_H #include #define JANA_TYPE_COMPONENT (jana_component_get_type ()) #define JANA_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_COMPONENT, JanaComponent)) #define JANA_IS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_COMPONENT)) #define JANA_COMPONENT_GET_INTERFACE(inst)\ (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_COMPONENT,\ JanaComponentInterface)) /** * JanaComponent: * * The #JanaComponent struct contains only private data. */ typedef struct _JanaComponent JanaComponent; /* Dummy object */ typedef struct _JanaComponentInterface JanaComponentInterface; /** * JanaComponentType: * @JANA_COMPONENT_NULL: No specific type * @JANA_COMPONENT_EVENT: Event type. Component can be cast to a #JanaEvent * @JANA_COMPONENT_NOTE: Note type. Component can be cast to a #JanaNote * @JANA_COMPONENT_TASK: Task type. Component can be cast to a #JanaTask * * Enum values for different types of component. * **/ typedef enum { JANA_COMPONENT_NULL, JANA_COMPONENT_EVENT, JANA_COMPONENT_NOTE, JANA_COMPONENT_TASK, } JanaComponentType; struct _JanaComponentInterface { GTypeInterface parent; JanaComponentType (*get_component_type) (JanaComponent *self); gboolean (*is_fully_represented) (JanaComponent *self); gchar * (*get_uid) (JanaComponent *self); const gchar * (*peek_uid) (JanaComponent *self); gchar ** (*get_categories) (JanaComponent *self); void (*set_categories) (JanaComponent *self, const gchar **categories); gboolean (*supports_custom_props) (JanaComponent *self); GList * (*get_custom_props_list) (JanaComponent *self); gchar * (*get_custom_prop) (JanaComponent *self, const gchar *name); gboolean (*set_custom_prop) (JanaComponent *self, const gchar *name, const gchar *value); }; GType jana_component_get_type (void); JanaComponentType jana_component_get_component_type (JanaComponent *self); gboolean jana_component_is_fully_represented (JanaComponent *self); gchar * jana_component_get_uid (JanaComponent *self); const gchar * jana_component_peek_uid (JanaComponent *self); gchar ** jana_component_get_categories (JanaComponent *self); void jana_component_set_categories (JanaComponent *self, const gchar **categories); gboolean jana_component_supports_custom_props (JanaComponent *self); GList * jana_component_get_custom_props_list (JanaComponent *self); gchar * jana_component_get_custom_prop (JanaComponent *self, const gchar *name); gboolean jana_component_set_custom_prop (JanaComponent *self, const gchar *name, const gchar *value); /* Props list is a list of key-name pairs as gchar **'s */ void jana_component_props_list_free (GList *props); #endif /* JANA_COMPONENT_H */ jana/libjana/jana-task.h0000644000175000017500000000525111327631152015325 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_TASK_H #define JANA_TASK_H #include #include #define JANA_TYPE_TASK (jana_task_get_type ()) #define JANA_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_TASK, JanaTask)) #define JANA_IS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_TASK)) #define JANA_TASK_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_TASK, JanaTaskInterface)) /** * JanaTask: * * The #JanaTask struct contains only private data. */ typedef struct _JanaTask JanaTask; /* Dummy object */ typedef struct _JanaTaskInterface JanaTaskInterface; struct _JanaTaskInterface { GTypeInterface parent; gchar * (*get_summary) (JanaTask *self); gchar * (*get_description) (JanaTask *self); gboolean (*get_completed) (JanaTask *self); JanaTime * (*get_due_date) (JanaTask *self); gint (*get_priority) (JanaTask *self); void (*set_summary) (JanaTask *self, const gchar *summary); void (*set_description) (JanaTask *self, const gchar *description); void (*set_completed) (JanaTask *self, gboolean completed); void (*set_due_date) (JanaTask *self, JanaTime *time); void (*set_priority) (JanaTask *self, gint priority); }; GType jana_task_get_type (void); gchar * jana_task_get_summary (JanaTask *self); gchar * jana_task_get_description (JanaTask *self); gboolean jana_task_get_completed (JanaTask *self); JanaTime * jana_task_get_due_date (JanaTask *self); gint jana_task_get_priority (JanaTask *self); void jana_task_set_summary (JanaTask *self, const gchar *summary); void jana_task_set_description (JanaTask *self, const gchar *description); void jana_task_set_completed (JanaTask *self, gboolean completed); void jana_task_set_due_date (JanaTask *self, JanaTime *time); void jana_task_set_priority (JanaTask *self, gint priority); #endif /* JANA_TASK_H */ jana/libjana/jana-store.h0000644000175000017500000000473711327631152015527 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_STORE_H #define JANA_STORE_H #include #define JANA_TYPE_STORE (jana_store_get_type ()) #define JANA_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ JANA_TYPE_STORE,\ JanaStore)) #define JANA_IS_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ JANA_TYPE_STORE)) #define JANA_STORE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst),\ JANA_TYPE_STORE,\ JanaStoreInterface)) /** * JanaStore: * * The #JanaStore struct contains only private data. */ typedef struct _JanaStore JanaStore; /* Dummy object */ typedef struct _JanaStoreInterface JanaStoreInterface; #include #include struct _JanaStoreInterface { GTypeInterface parent; void (*open) (JanaStore *self); JanaComponent * (*get_component) (JanaStore *self, const gchar *uid); JanaStoreView * (*get_view) (JanaStore *self); void (*add_component) (JanaStore *self, JanaComponent *comp); void (*modify_component) (JanaStore *self, JanaComponent *comp); void (*remove_component) (JanaStore *self, JanaComponent *comp); /* Signals */ void (*opened) (JanaStore *self); /*gchar * (*auth) (JanaStore *self, */ }; GType jana_store_get_type (void); void jana_store_open (JanaStore *self); JanaComponent * jana_store_get_component (JanaStore *self, const gchar *uid); JanaStoreView * jana_store_get_view (JanaStore *self); void jana_store_add_component (JanaStore *self, JanaComponent *comp); void jana_store_modify_component (JanaStore *self, JanaComponent *comp); void jana_store_remove_component (JanaStore *self, JanaComponent *comp); #endif /* JANA_STORE_H */ jana/libjana/jana.h0000644000175000017500000000233011327631152014360 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana * @short_description: An interface library for time-related personal * information */ #ifndef JANA_H #define JANA_H #include #include #include #include #include #include #include #include #endif jana/libjana/doc/0000755000175000017500000000000011327631152014045 5ustar paulliupaulliujana/libjana/doc/Makefile.am0000644000175000017500000000002211327631152016073 0ustar paulliupaulliuSUBDIRS=reference jana/libjana/doc/reference/0000755000175000017500000000000011327631152016003 5ustar paulliupaulliujana/libjana/doc/reference/Makefile.am0000644000175000017500000000544011327631152020042 0ustar paulliupaulliu## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libjana # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=../../ # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS=--type-init-func="g_type_init();g_type_class_ref(G_TYPE_OBJECT)" # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/libjana/*.h CFILE_GLOB=$(top_srcdir)/libjana/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES= # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) INCLUDES=-I$(top_srcdir)/src -I$(top_builddir) $(GOBJECT_CFLAGS) GTKDOC_LIBS=$(top_srcdir)/libjana/libjana.la $(GOBJECT_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = version.xml.in jana/libjana/doc/reference/libjana.types0000644000175000017500000000030211327631152020464 0ustar paulliupaulliujana_store_get_type jana_time_get_type jana_duration_get_type jana_task_get_type jana_component_get_type jana_store_view_get_type jana_note_get_type jana_event_get_type jana_recurrence_get_type jana/libjana/doc/reference/tmpl/0000755000175000017500000000000011327631152016757 5ustar paulliupaulliujana/libjana/doc/reference/tmpl/dummy.sgml0000644000175000017500000000000011327631152020764 0ustar paulliupaulliujana/libjana/doc/reference/libjana-docs.sgml0000644000175000017500000000130611327631152021215 0ustar paulliupaulliu libjana Reference Manual libjana jana/libjana/doc/reference/version.xml.in0000644000175000017500000000001211327631152020610 0ustar paulliupaulliu@VERSION@ jana/libjana/doc/reference/libjana-overrides.txt0000644000175000017500000000014611327631152022145 0ustar paulliupaulliu jana_utils_time_to_tm struct tm JanaTime *time jana/libjana/doc/reference/libjana-sections.txt0000644000175000017500000000703311327631152021774 0ustar paulliupaulliu
jana-store JanaStore JanaStore jana_store_open jana_store_get_component jana_store_get_view jana_store_add_component jana_store_modify_component jana_store_remove_component
jana-time JanaTime JanaDuration JanaTime jana_time_get_seconds jana_time_get_minutes jana_time_get_hours jana_time_get_day jana_time_get_month jana_time_get_year jana_time_get_isdate jana_time_get_daylight jana_time_get_tzname jana_time_get_offset jana_time_set_seconds jana_time_set_minutes jana_time_set_hours jana_time_set_day jana_time_set_month jana_time_set_year jana_time_set_isdate jana_time_set_tzname jana_time_set_offset jana_time_duplicate jana_duration_new jana_duration_copy jana_duration_set_start jana_duration_set_end jana_duration_valid jana_duration_free
jana-task JanaTask JanaTask
jana-component JanaComponent JanaComponent JanaComponentType jana_component_get_component_type jana_component_is_fully_represented jana_component_get_uid jana_component_get_categories jana_component_set_categories jana_component_supports_custom_props jana_component_get_custom_props_list jana_component_get_custom_prop jana_component_set_custom_prop jana_component_props_list_free
jana-store-view JanaStoreView JanaStoreView JanaStoreViewField jana_store_view_get_range jana_store_view_set_range jana_store_view_add_match jana_store_view_get_matches jana_store_view_remove_match jana_store_view_clear_matches jana_store_view_start jana_store_view_get_store
jana-note JanaNote JanaNote jana_note_get_author jana_note_get_recipient jana_note_get_body jana_note_get_creation_time jana_note_get_modified_time jana_note_set_author jana_note_set_recipient jana_note_set_body jana_note_set_creation_time
jana-event JanaEvent JanaEvent JanaRecurrence JanaRecurrenceType jana_recurrence_new jana_recurrence_copy jana_recurrence_free jana_exceptions_free jana_event_get_summary jana_event_get_description jana_event_get_location jana_event_get_start jana_event_get_end jana_event_get_categories jana_event_supports_alarm jana_event_has_alarm jana_event_get_alarm_time jana_event_supports_recurrence jana_event_has_recurrence jana_event_get_recurrence jana_event_supports_exceptions jana_event_has_exceptions jana_event_get_exceptions jana_event_set_summary jana_event_set_description jana_event_set_location jana_event_set_start jana_event_set_end jana_event_set_categories jana_event_set_alarm jana_event_set_recurrence jana_event_set_exceptions
jana-utils jana_utils_time_is_leap_year jana_utils_time_days_in_month jana_utils_time_day_of_week jana_utils_time_day_of_year jana_utils_time_set_start_of_week jana_utils_time_set_end_of_week jana_utils_time_week_of_year jana_utils_time_to_gdate jana_utils_time_to_tm jana_utils_strftime jana_utils_time_compare jana_utils_time_copy jana_utils_time_diff jana_utils_time_adjust jana_utils_time_now jana_utils_duration_contains jana_utils_event_copy jana_utils_note_copy jana_utils_event_get_instances jana_utils_component_insert_category jana_utils_component_remove_category jana_utils_component_has_category jana_utils_instance_list_free jana_utils_get_local_tzname jana_utils_recurrence_to_string jana_utils_recurrence_diff jana_utils_ab_day jana_utils_time_daylight_hours
jana
jana/COPYING0000644000175000017500000006366111327631152012747 0ustar paulliupaulliu GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. ^L Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. ^L GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. ^L Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. ^L 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. ^L 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. ^L 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. ^L 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ^L How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jana/autogen.sh0000755000175000017500000000010211327631152013672 0ustar paulliupaulliu#!/bin/sh REQUIRED_AUTOMAKE_VERSION=1.7 exec gnome-autogen.sh $@ jana/Makefile.am0000644000175000017500000000021411327631152013731 0ustar paulliupaulliuSUBDIRS=libjana libjana-ecal libjana-gtk @build_tests@ @build_examples@ po DIST_SUBDIRS=libjana libjana-ecal libjana-gtk tests examples po jana/configure.ac0000644000175000017500000000454711327631152014200 0ustar paulliupaulliuAC_PREREQ(2.53) AC_INIT(jana, 0.0, http://www.openedhand.com/) AM_INIT_AUTOMAKE() AC_CONFIG_SRCDIR(libjana/jana-component.c) AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE AC_ISC_POSIX AC_PROG_CC AC_STDC_HEADERS AC_PROG_LIBTOOL IT_PROG_INTLTOOL([0.35.0]) dnl i18n support GETTEXT_PACKAGE=Jana AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package]) AC_SUBST(GETTEXT_PACKAGE) AM_GLIB_GNU_GETTEXT AC_CHECK_LIB(m, pow) PKG_CHECK_MODULES(GOBJECT, gobject-2.0 >= 2.12.0) PKG_CHECK_MODULES(GTHREAD, gthread-2.0) PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6.0) PKG_CHECK_MODULES(ECAL, libecal-1.2 >= 1.4.0) PKG_CHECK_MODULES(GCONF, gconf-2.0) old_cflags=$CFLAGS CFLAGS=$ECAL_CFLAGS AC_CHECK_TYPE(ECalComponentId, [], [], [#include ]) if test $ac_cv_type_ECalComponentId = yes; then AC_DEFINE(HAVE_ECALCOMPONENTID, 1, [Defined if ECalComponentId exists]) fi CFLAGS=$old_cflags old_libs=$LIBS LIBS=$ECAL_LIBS AC_CHECK_FUNC(e_cal_new_system_memos, AC_DEFINE(HAVE_ECAL_NEW_SYSTEM_MEMOS, 1, [Defined if e_cal_new_system_memos exists])) LIBS=$old_libs AC_ARG_ENABLE([tests], AC_HELP_STRING([--enable-tests], [Enable building of test applications]), [build_tests=tests]) AC_ARG_ENABLE([examples], AC_HELP_STRING([--enable-examples], [Enable building of example applications]), [build_examples=examples]) AC_ARG_ENABLE([glade], AC_HELP_STRING([--enable-glade], [Enable glade-3 development support]), [enable_glade=yes]) if test "$enable_glade" = yes; then PKG_PROG_PKG_CONFIG() AC_DEFINE(HAVE_GLADE, 1, [Defined when building with glade-3 support]) PKG_CHECK_MODULES(GLADE, gladeui-1.0 >= 3.4.5) catalogdir=`${PKG_CONFIG} --variable=catalogdir gladeui-1.0` fi AM_CONDITIONAL(WITH_GLADE, test "$enable_glade" = yes) AC_SUBST([build_tests]) AC_SUBST([build_examples]) AC_SUBST([catalogdir]) GTK_DOC_CHECK([1.4]) AC_OUTPUT([ Makefile libjana/Makefile libjana/libjana.pc libjana/doc/Makefile libjana/doc/reference/Makefile libjana/doc/reference/version.xml libjana-ecal/Makefile libjana-ecal/libjana-ecal.pc libjana-ecal/doc/Makefile libjana-ecal/doc/reference/Makefile libjana-ecal/doc/reference/version.xml libjana-gtk/Makefile libjana-gtk/libjana-gtk.pc libjana-gtk/data/Makefile libjana-gtk/doc/Makefile libjana-gtk/doc/reference/Makefile libjana-gtk/doc/reference/version.xml tests/Makefile examples/Makefile examples/data/Makefile po/Makefile.in ]) jana/po/0000755000175000017500000000000011327631152012316 5ustar paulliupaulliujana/po/POTFILES.in0000644000175000017500000000000011327631152014061 0ustar paulliupaulliujana/NEWS0000644000175000017500000000000011327631152012365 0ustar paulliupaulliujana/MAINTAINERS0000644000175000017500000000016511327631152013377 0ustar paulliupaulliuChris Lord E-mail: chris@linux.intel.com Userid: chrisl Rob Bradford E-mail: rbradford@gnome.org Userid: rbradford jana/libjana-ecal/0000755000175000017500000000000011327631152014202 5ustar paulliupaulliujana/libjana-ecal/jana-ecal-task.h0000644000175000017500000000405011327631152017125 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_TASK_H #define JANA_ECAL_TASK_H #include #include #include #include #define JANA_ECAL_TYPE_TASK (jana_ecal_task_get_type ()) #define JANA_ECAL_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_TASK, JanaEcalTask)) #define JANA_ECAL_TASK_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), \ JANA_ECAL_TYPE_TASK, \ JanaEcalTaskClass)) #define JANA_ECAL_IS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_TASK)) #define JANA_ECAL_IS_TASK_CLASS(vtable)(G_TYPE_CHECK_CLASS_TYPE ((vtable), \ JANA_ECAL_TYPE_TASK)) #define JANA_ECAL_TASK_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ JANA_ECAL_TYPE_TASK, \ JanaEcalTaskClass)) typedef struct _JanaEcalTask JanaEcalTask; typedef struct _JanaEcalTaskClass JanaEcalTaskClass; /** * JanaEcalTask: * * The #JanaEcalTask struct contains only private data. */ struct _JanaEcalTask { GObject parent; }; struct _JanaEcalTaskClass { GObjectClass parent; }; GType jana_ecal_task_get_type (void); JanaTask *jana_ecal_task_new (); JanaTask *jana_ecal_task_new_from_ecalcomp (ECalComponent *task); #endif /* JANA_ECAL_TASK_H */ jana/libjana-ecal/jana-ecal-task.c0000644000175000017500000001641311327631152017126 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-task * @short_description: An implementation of #JanaTask using libecal * * #JanaEcalTask is an implementation of #JanaTask that provides a * wrapper over #ECalComponent and its journal-related functions, using libecal. */ #define HANDLE_LIBICAL_MEMORY 1 #include "jana-ecal-task.h" #include "jana-ecal-component.h" #include "jana-ecal-time.h" #include "jana-ecal-utils.h" #include static void task_interface_init (gpointer g_iface, gpointer iface_data); static void component_interface_init (gpointer g_iface, gpointer iface_data); static JanaComponentType component_get_component_type (JanaComponent *self); static gboolean component_is_fully_represented (JanaComponent *self); static gchar * task_get_summary (JanaTask *self); static gchar * task_get_description (JanaTask *self); static gboolean task_get_completed (JanaTask *self); static JanaTime * task_get_due_date (JanaTask *self); static gint task_get_priority (JanaTask *self); static void task_set_summary (JanaTask *self, const gchar *summary); static void task_set_description (JanaTask *self, const gchar *description); static void task_set_completed (JanaTask *self, gboolean completed); static void task_set_due_date (JanaTask *self, JanaTime *time); static void task_set_priority (JanaTask *self, gint priority); G_DEFINE_TYPE_WITH_CODE (JanaEcalTask, jana_ecal_task, JANA_ECAL_TYPE_COMPONENT, G_IMPLEMENT_INTERFACE (JANA_TYPE_COMPONENT, component_interface_init) G_IMPLEMENT_INTERFACE (JANA_TYPE_TASK, task_interface_init)); static void component_interface_init (gpointer g_iface, gpointer iface_data) { JanaComponentInterface *iface = (JanaComponentInterface *)g_iface; iface->get_component_type = component_get_component_type; iface->is_fully_represented = component_is_fully_represented; } static void task_interface_init (gpointer g_iface, gpointer iface_data) { JanaTaskInterface *iface = (JanaTaskInterface *)g_iface; iface->get_summary = task_get_summary; iface->get_description = task_get_description; iface->get_completed = task_get_completed; iface->get_due_date = task_get_due_date; iface->get_priority = task_get_priority; iface->set_summary = task_set_summary; iface->set_description = task_set_description; iface->set_completed = task_set_completed; iface->set_due_date = task_set_due_date; iface->set_priority = task_set_priority; } static void jana_ecal_task_class_init (JanaEcalTaskClass *klass) { /* Not overriding any object methods or adding private data */ } static void jana_ecal_task_init (JanaEcalTask *self) { /* No initialisation required */ } /** * jana_ecal_task_new: * * Creates a new #JanaEcalTask. * * Returns: A new #JanaEcalTask, cast as a #JanaTask. */ JanaTask * jana_ecal_task_new () { ECalComponent *comp = e_cal_component_new (); JanaTask *task; e_cal_component_set_icalcomponent (comp, icalcomponent_new (ICAL_VTODO_COMPONENT)); task = JANA_TASK (g_object_new (JANA_ECAL_TYPE_TASK, "ecalcomp", comp, NULL)); return task; } /** * jana_ecal_task_new_from_ecalcomp: * @event: An #ECalComponent * * Creates a new #JanaEcalTask based on the given #ECalComponent. The type of * the given #ECalComponent must be %E_CAL_COMPONENT_JOURNAL. See * e_cal_component_get_vtype(). * * Returns: A new #JanaEcalTask that wraps the given #ECalComponent, cast as * a #JanaTask. */ JanaTask * jana_ecal_task_new_from_ecalcomp (ECalComponent *event) { return JANA_TASK (g_object_new (JANA_ECAL_TYPE_TASK, "ecalcomp", event, NULL)); } static JanaComponentType component_get_component_type (JanaComponent *self) { return JANA_COMPONENT_TASK; } static gboolean component_is_fully_represented (JanaComponent *self) { GSList *desc_list; ECalComponent *comp; gboolean result = TRUE; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_description_list (comp, &desc_list); if (g_slist_length (desc_list) > 1) result = FALSE; e_cal_component_free_text_list (desc_list); g_object_unref (comp); return result; } static gchar * task_get_summary (JanaTask *self) { return jana_ecal_component_get_summary (JANA_ECAL_COMPONENT (self)); } static gchar * task_get_description (JanaTask *self) { return jana_ecal_component_get_description (JANA_ECAL_COMPONENT (self)); } static gboolean task_get_completed (JanaTask *self) { ECalComponent *comp; icalproperty_status status; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_status (comp, &status); g_object_unref (comp); return (status == ICAL_STATUS_COMPLETED); } static JanaTime * task_get_due_date (JanaTask *self) { ECalComponent *comp; ECalComponentDateTime etime; JanaTime *time = NULL; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_due (comp, &etime); if (etime.value) { time = jana_ecal_time_new_from_ecaltime (&etime); e_cal_component_free_datetime (&etime); } g_object_unref (comp); return time; } static gint task_get_priority (JanaTask *self) { ECalComponent *comp; gint *priority = NULL; gint res; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_priority (comp, &priority); res = priority ? *priority: 0; if (priority) e_cal_component_free_priority (priority); g_object_unref (comp); return res; } static void task_set_summary (JanaTask *self, const gchar *summary) { jana_ecal_component_set_summary (JANA_ECAL_COMPONENT (self), summary); } static void task_set_description (JanaTask *self, const gchar *description) { jana_ecal_component_set_description ( JANA_ECAL_COMPONENT (self), description); } static void task_set_completed (JanaTask *self,gboolean completed) { ECalComponent *comp; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_set_status (comp, completed ? ICAL_STATUS_COMPLETED : ICAL_STATUS_NONE); g_object_unref (comp); } static void task_set_due_date (JanaTask *self, JanaTime *time) { ECalComponent *comp; icaltimetype *itime; ECalComponentDateTime dt; g_object_get (time, "icaltime", &itime, NULL); dt.value = itime; if (icaltime_is_utc (*itime)) dt.tzid = "UTC"; else dt.tzid = (const char *)icaltimezone_get_tzid ( (icaltimezone *)itime->zone); g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_set_due (comp, &dt); g_object_unref (comp); } static void task_set_priority (JanaTask *self, gint priority) { ECalComponent *comp; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_set_priority (comp, &priority); g_object_unref (comp); } jana/libjana-ecal/jana-ecal-event.h0000644000175000017500000000411411327631152017305 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_EVENT_H #define JANA_ECAL_EVENT_H #include #include #include #include #define JANA_ECAL_TYPE_EVENT (jana_ecal_event_get_type ()) #define JANA_ECAL_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_EVENT, JanaEcalEvent)) #define JANA_ECAL_EVENT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), \ JANA_ECAL_TYPE_EVENT, \ JanaEcalEventClass)) #define JANA_ECAL_IS_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_EVENT)) #define JANA_ECAL_IS_EVENT_CLASS(vtable)(G_TYPE_CHECK_CLASS_TYPE ((vtable), \ JANA_ECAL_TYPE_EVENT)) #define JANA_ECAL_EVENT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ JANA_ECAL_TYPE_EVENT, \ JanaEcalEventClass)) typedef struct _JanaEcalEvent JanaEcalEvent; typedef struct _JanaEcalEventClass JanaEcalEventClass; /** * JanaEcalEvent: * * The #JanaEcalEvent struct contains only private data. */ struct _JanaEcalEvent { GObject parent; }; struct _JanaEcalEventClass { GObjectClass parent; }; GType jana_ecal_event_get_type (void); JanaEvent *jana_ecal_event_new (); JanaEvent *jana_ecal_event_new_from_ecalcomp (ECalComponent *event); #endif /* JANA_ECAL_EVENT_H */ jana/libjana-ecal/jana-ecal-component.c0000644000175000017500000004306611327631152020172 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-component * @short_description: An implementation of #JanaComponent using libecal * * #JanaEcalComponent is an implementation of #JanaComponent that provides a * wrapper over #ECalComponent, using libecal. */ #define HANDLE_LIBICAL_MEMORY 1 #include "jana-ecal-component.h" #include "jana-ecal-time.h" #include #include static void component_interface_init (gpointer g_iface, gpointer iface_data); static JanaComponentType component_get_component_type (JanaComponent *self); static gboolean component_is_fully_represented (JanaComponent *self); static gchar * component_get_uid (JanaComponent *self); static const gchar * component_peek_uid (JanaComponent *self); static gchar ** component_get_categories(JanaComponent *self); static void component_set_categories(JanaComponent *self, const gchar **categories); static gboolean component_supports_custom_props (JanaComponent *self); static GList * component_get_custom_props_list (JanaComponent *self); static gchar * component_get_custom_prop (JanaComponent *self, const gchar *name); static gboolean component_set_custom_prop (JanaComponent *self, const gchar *name, const gchar *value); G_DEFINE_TYPE_WITH_CODE (JanaEcalComponent, jana_ecal_component, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (JANA_TYPE_COMPONENT, component_interface_init)); #define COMPONENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ JANA_ECAL_TYPE_COMPONENT, JanaEcalComponentPrivate)) typedef struct _JanaEcalComponentPrivate JanaEcalComponentPrivate; struct _JanaEcalComponentPrivate { ECalComponent *comp; }; enum { PROP_ECALCOMP = 1, }; static void jana_ecal_component_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (object); switch (property_id) { case PROP_ECALCOMP : g_value_set_object (value, priv->comp); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_component_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (object); switch (property_id) { case PROP_ECALCOMP : priv->comp = E_CAL_COMPONENT (g_value_dup_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_component_dispose (GObject *object) { JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (object); if (priv->comp) { g_object_unref (priv->comp); priv->comp = NULL; } if (G_OBJECT_CLASS (jana_ecal_component_parent_class)->dispose) G_OBJECT_CLASS (jana_ecal_component_parent_class)->dispose (object); } static void jana_ecal_component_finalize (GObject *object) { G_OBJECT_CLASS (jana_ecal_component_parent_class)->finalize (object); } static void component_interface_init (gpointer g_iface, gpointer iface_data) { JanaComponentInterface *iface = (JanaComponentInterface *)g_iface; iface->get_component_type = component_get_component_type; iface->is_fully_represented = component_is_fully_represented; iface->get_uid = component_get_uid; iface->peek_uid = component_peek_uid; iface->get_categories = component_get_categories; iface->set_categories = component_set_categories; iface->supports_custom_props = component_supports_custom_props; iface->get_custom_props_list = component_get_custom_props_list; iface->get_custom_prop = component_get_custom_prop; iface->set_custom_prop = component_set_custom_prop; } static void jana_ecal_component_class_init (JanaEcalComponentClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaEcalComponentPrivate)); object_class->get_property = jana_ecal_component_get_property; object_class->set_property = jana_ecal_component_set_property; object_class->dispose = jana_ecal_component_dispose; object_class->finalize = jana_ecal_component_finalize; g_object_class_install_property ( object_class, PROP_ECALCOMP, g_param_spec_object ( "ecalcomp", "ECalComponent *", "The ECalComponent represented by this JanaComponent " "object.", E_TYPE_CAL_COMPONENT, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void jana_ecal_component_init (JanaEcalComponent *self) { } /** * jana_ecal_component_new_from_ecalcomp: * @component: An #ECalComponent * * Creates a new #JanaEcalComponent from an #ECalComponent. * * Returns: A new #JanaEcalComponent that wraps the given #ECalComponent, * cast as a #JanaComponent. */ JanaComponent * jana_ecal_component_new_from_ecalcomp (ECalComponent *component) { return JANA_COMPONENT (g_object_new (JANA_ECAL_TYPE_COMPONENT, "ecalcomp", component, NULL)); } /** * jana_ecal_component_get_summary: * @self: A #JanaEcalComponent * * Retrieves the summary from the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. * * Returns: A newly allocated string with the summary from the underlying * #ECalComponent, or %NULL. */ gchar * jana_ecal_component_get_summary (JanaEcalComponent *self) { ECalComponentText summary; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_get_summary (priv->comp, &summary); if (summary.value) return g_strdup (summary.value); /*else if (summary.altrep) return g_strdup (summary.altrep);*/ else return NULL; } /** * jana_ecal_component_get_description: * @self: A #JanaEcalComponent * * Retrieves the first description from the underlying #ECalComponent. This * function is intended for using only when extending #JanaEcalComponent. * * Returns: A newly allocated string with the first description from the * underlying #ECalComponent, or %NULL. */ gchar * jana_ecal_component_get_description (JanaEcalComponent *self) { GSList *desc_list; ECalComponentText *desc; gchar *desc_copy = NULL; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); /* Note, that only journal components are allowed to have more than one * description. It's ok to just take the first here. */ e_cal_component_get_description_list (priv->comp, &desc_list); if (desc_list) { desc = desc_list->data; if (desc->value) desc_copy = g_strdup (desc->value); } e_cal_component_free_text_list (desc_list); return desc_copy; } /** * jana_ecal_component_get_location: * @self: A #JanaEcalComponent * * Retrieves the location from the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. * * Returns: A newly allocated string with the location from the * underlying #ECalComponent, or %NULL. */ gchar * jana_ecal_component_get_location (JanaEcalComponent *self) { const char *location; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_get_location (priv->comp, &location); return location ? g_strdup (location) : NULL; } /** * jana_ecal_component_set_summary: * @self: A #JanaEcalComponent * @summary: A UTF-8 string * * Sets the summary on the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. */ void jana_ecal_component_set_summary (JanaEcalComponent *self, const gchar *summary) { ECalComponentText summary_text; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); summary_text.value = summary; summary_text.altrep = NULL; e_cal_component_set_summary (priv->comp, &summary_text); } /** * jana_ecal_component_set_description: * @self: A #JanaEcalComponent * @description: A UTF-8 string * * Sets the description on the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. */ void jana_ecal_component_set_description (JanaEcalComponent *self, const gchar *description) { ECalComponentText desc_text; GSList *text_list; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); desc_text.value = description; desc_text.altrep = NULL; text_list = g_slist_append (NULL, &desc_text); e_cal_component_set_description_list (priv->comp, text_list); g_slist_free (text_list); } /** * jana_ecal_component_set_location: * @self: A #JanaEcalComponent * @location: A UTF-8 string * * Sets the location on the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. */ void jana_ecal_component_set_location (JanaEcalComponent *self, const gchar *location) { JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_set_location (priv->comp, location); } /** * jana_ecal_component_get_start: * @self: A #JanaEcalComponent * * Retrieves the dtstart of the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. * * Returns: A #JanaTime representing the dtstart of the underlying * #ECalComponent, or %NULL. */ JanaTime * jana_ecal_component_get_start (JanaEcalComponent *self) { ECalComponentDateTime dt; JanaTime *time; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); dt.value = NULL; e_cal_component_get_dtstart (priv->comp, &dt); if (dt.value) { time = jana_ecal_time_new_from_ecaltime (&dt); e_cal_component_free_datetime (&dt); } else { const gchar *location; /* A NULL time means 'from the beginning of time', so create * a very early time as substitute. */ time = jana_ecal_time_new (); e_cal_component_get_location (priv->comp, &location); if (location) jana_ecal_time_set_location ( JANA_ECAL_TIME (time), location); jana_time_set_year (time, -G_MAXINT); jana_time_set_month (time, 1); jana_time_set_day (time, 1); jana_time_set_isdate (time, TRUE); } return time; } /** * jana_ecal_component_get_end: * @self: A #JanaEcalComponent * * Retrieves the dtend of the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. * * Returns: A #JanaTime representing the dtend of the underlying * #ECalComponent, or %NULL. */ JanaTime * jana_ecal_component_get_end (JanaEcalComponent *self) { ECalComponentDateTime dt; JanaTime *time; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); dt.value = NULL; e_cal_component_get_dtend (priv->comp, &dt); time = jana_ecal_time_new_from_ecaltime (&dt); if (dt.value) e_cal_component_free_datetime (&dt); return time; } /** * jana_ecal_component_set_start: * @self: A #JanaEcalComponent * @start: A #JanaTime * * Sets the dtstart on the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. */ void jana_ecal_component_set_start (JanaEcalComponent *self, JanaTime *start) { JanaEcalTime *time; icaltimetype *icaltime; ECalComponentDateTime dt; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); if (JANA_ECAL_IS_TIME (start)) { time = g_object_ref (JANA_ECAL_TIME (start)); } else { time = JANA_ECAL_TIME (jana_utils_time_copy ( start, jana_ecal_time_new ())); } g_object_get (time, "icaltime", &icaltime, NULL); /* vaue, tzid */ dt.value = icaltime; if (icaltime_is_utc (*icaltime)) dt.tzid = "UTC"; else dt.tzid = (const char *)icaltimezone_get_tzid ( (icaltimezone *)icaltime->zone); e_cal_component_set_dtstart (priv->comp, &dt); g_object_unref (time); } /** * jana_ecal_component_set_end: * @self: A #JanaEcalComponent * @end: A #JanaTime * * Sets the dtend on the underlying #ECalComponent. This function * is intended for using only when extending #JanaEcalComponent. */ void jana_ecal_component_set_end (JanaEcalComponent *self, JanaTime *end) { JanaEcalTime *time; icaltimetype *icaltime; ECalComponentDateTime dt; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); if (JANA_ECAL_IS_TIME (end)) { time = g_object_ref (JANA_ECAL_TIME (end)); } else { time = JANA_ECAL_TIME (jana_utils_time_copy ( end, jana_ecal_time_new ())); } g_object_get (time, "icaltime", &icaltime, NULL); /* vaue, tzid */ dt.value = icaltime; if (icaltime_is_utc (*icaltime)) dt.tzid = "UTC"; else dt.tzid = (const char *)icaltimezone_get_tzid ( (icaltimezone *)icaltime->zone); e_cal_component_set_dtend (priv->comp, &dt); g_object_unref (time); } static JanaComponentType component_get_component_type (JanaComponent *self) { /* Sub-classes should override this method */ return JANA_COMPONENT_NULL; } static gboolean component_is_fully_represented (JanaComponent *self) { /* Sub-classes should override this method */ return FALSE; } static gchar * component_get_uid (JanaComponent *self) { const char *uid = NULL; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_get_uid (priv->comp, &uid); return uid ? g_strdup (uid) : NULL; } static const gchar * component_peek_uid (JanaComponent *self) { const char *uid = NULL; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_get_uid (priv->comp, &uid); return uid; } static gchar ** component_get_categories (JanaComponent *self) { const char *categories; gchar **category_list; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); e_cal_component_get_categories (priv->comp, &categories); if (categories) { category_list = g_strsplit (categories, ",", 0); return category_list; } else return NULL; } static void component_set_categories (JanaComponent *self, const gchar **categories) { gchar *categories_joined; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); categories_joined = g_strjoinv (",", (gchar **)categories); /* Note: Setting an empty categories list on an event without a * category set will cause libical to crash. */ if ((!categories_joined) || (categories_joined[0] == '\0')) { const gchar *categories; e_cal_component_get_categories (priv->comp, &categories); if (categories) e_cal_component_set_categories (priv->comp, NULL); } else { e_cal_component_set_categories (priv->comp, categories_joined); } g_free (categories_joined); } static gboolean component_supports_custom_props (JanaComponent *self) { return TRUE; } static GList * component_get_custom_props_list (JanaComponent *self) { icalproperty *prop; icalcomponent *comp; GList *props = NULL; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); comp = e_cal_component_get_icalcomponent (priv->comp); for (prop = icalcomponent_get_first_property (comp, ICAL_X_PROPERTY); prop; prop = icalcomponent_get_next_property ( comp, ICAL_X_PROPERTY)) { gchar **prop_pair = g_new (gchar *, 2); gchar *name = g_strdup (icalproperty_get_x_name (prop)); #ifdef LIBICAL_MEMFIXES gchar *value = icalproperty_get_value_as_string (prop); #else gchar *value = g_strdup (icalproperty_get_value_as_string ( prop)); #endif prop_pair[0] = name; prop_pair[1] = value; props = g_list_prepend (props, prop_pair); } return props; } static gchar * component_get_custom_prop (JanaComponent *self, const gchar *name) { icalproperty *prop; icalcomponent *comp; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); comp = e_cal_component_get_icalcomponent (priv->comp); /* See if the property exists first */ for (prop = icalcomponent_get_first_property (comp, ICAL_X_PROPERTY); prop; prop = icalcomponent_get_next_property ( comp, ICAL_X_PROPERTY)) { if (strcmp (icalproperty_get_x_name (prop), name) == 0) { #ifdef LIBICAL_MEMFIXES return icalproperty_get_value_as_string (prop); #else return g_strdup (icalproperty_get_value_as_string ( prop)); #endif } } return NULL; } static gboolean component_set_custom_prop (JanaComponent *self, const gchar *name, const gchar *value) { icalproperty *prop; icalcomponent *comp; gboolean exists = FALSE; JanaEcalComponentPrivate *priv = COMPONENT_PRIVATE (self); if (strncmp ("X-", name, 2) != 0) return FALSE; comp = e_cal_component_get_icalcomponent (priv->comp); /* See if the property exists first */ for (prop = icalcomponent_get_first_property (comp, ICAL_X_PROPERTY); prop; prop = icalcomponent_get_next_property ( comp, ICAL_X_PROPERTY)) { if (strcmp (icalproperty_get_x_name (prop), name) == 0) { exists = TRUE; break; } } if (!exists) { /* Create a new property */ prop = icalproperty_new (ICAL_X_PROPERTY); icalproperty_set_x_name (prop, name); } icalproperty_set_value (prop, icalvalue_new_from_string ( ICAL_X_VALUE, value)); if (!exists) { icalcomponent_add_property (comp, prop); /* FIXME: Check that the property added without errors - no * idea how to do this :( */ /*if (icalproperty_isa (prop) != ICAL_X_PROPERTY) { icalcomponent_remove_property (comp, prop); icalproperty_free (prop); return FALSE; }*/ } return TRUE; } jana/libjana-ecal/jana-ecal-store-view.h0000644000175000017500000000431511327631152020273 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_STORE_VIEW_H #define JANA_ECAL_STORE_VIEW_H #include #include #include #include #define JANA_ECAL_TYPE_STORE_VIEW (jana_ecal_store_view_get_type ()) #define JANA_ECAL_STORE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_STORE_VIEW, \ JanaEcalStoreView)) #define JANA_ECAL_STORE_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST \ ((vtable), \ JANA_ECAL_TYPE_STORE_VIEW, \ JanaEcalStoreViewClass)) #define JANA_ECAL_IS_STORE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_STORE_VIEW)) #define JANA_ECAL_IS_STORE_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE \ ((vtable), \ JANA_ECAL_TYPE_STORE_VIEW)) #define JANA_ECAL_STORE_VIEW_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS \ ((inst), \ JANA_ECAL_TYPE_STORE_VIEW, \ JanaEcalStoreViewClass)) typedef struct _JanaEcalStoreView JanaEcalStoreView; typedef struct _JanaEcalStoreViewClass JanaEcalStoreViewClass; /** * JanaEcalStoreView: * * The #JanaEcalStoreView struct contains only private data. */ struct _JanaEcalStoreView { GObject parent; }; struct _JanaEcalStoreViewClass { GObjectClass parent; }; GType jana_ecal_store_view_get_type (void); JanaStoreView *jana_ecal_store_view_new (JanaEcalStore *store); #endif /* JANA_ECAL_STORE_VIEW_H */ jana/libjana-ecal/libjana-ecal.pc.in0000644000175000017500000000043111327631152017433 0ustar paulliupaulliuprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libjana-ecal Description: An evolution-data-server based implementation of libjana Requires: libjana libecal-1.2 Version: @VERSION@ Libs: -L${libdir} -ljana-ecal Cflags: -I${includedir}/jana jana/libjana-ecal/jana-ecal-time.c0000644000175000017500000003726311327631152017130 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-time * @short_description: An implementation of #JanaTime using libecal * * #JanaEcalTime is an implementation of #JanaTime that provides a * wrapper over #icaltimetype, using libecal. */ #define HANDLE_LIBICAL_MEMORY 1 #include "jana-ecal-time.h" #include #include static void time_interface_init (gpointer g_iface, gpointer iface_data); static guint8 time_get_seconds (JanaTime *self); static guint8 time_get_minutes (JanaTime *self); static guint8 time_get_hours (JanaTime *self); static guint8 time_get_day (JanaTime *self); static guint8 time_get_month (JanaTime *self); static guint16 time_get_year (JanaTime *self); static gboolean time_get_isdate (JanaTime *self); static gboolean time_get_daylight(JanaTime *self); static gchar * time_get_tzname (JanaTime *self); static glong time_get_offset (JanaTime *self); static void time_set_seconds (JanaTime *self, gint seconds); static void time_set_minutes (JanaTime *self, gint minutes); static void time_set_hours (JanaTime *self, gint hours); static void time_set_day (JanaTime *self, gint day); static void time_set_month (JanaTime *self, gint month); static void time_set_year (JanaTime *self, gint year); static void time_set_isdate (JanaTime *self, gboolean isdate); static void time_set_tzname (JanaTime *self, const gchar *tzname); static void time_set_offset (JanaTime *self, glong offset); static JanaTime * time_duplicate(JanaTime *self); G_DEFINE_TYPE_WITH_CODE (JanaEcalTime, jana_ecal_time, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (JANA_TYPE_TIME, time_interface_init)); #define TIME_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), JANA_ECAL_TYPE_TIME, JanaEcalTimePrivate)) typedef struct _JanaEcalTimePrivate JanaEcalTimePrivate; struct _JanaEcalTimePrivate { icaltimetype *time; gboolean year_set; gboolean month_set; gboolean day_set; }; enum { PROP_ICALTIME = 1, }; static void jana_ecal_time_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaEcalTimePrivate *priv = TIME_PRIVATE (object); switch (property_id) { case PROP_ICALTIME : g_value_set_pointer (value, priv->time); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_time_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { icaltimetype *time; JanaEcalTimePrivate *priv = TIME_PRIVATE (object); switch (property_id) { case PROP_ICALTIME : if ((time = g_value_get_pointer (value))) { priv->time = g_slice_new (icaltimetype); g_memmove (priv->time, time, sizeof (icaltimetype)); if ((!icaltime_is_null_time (*priv->time)) && icaltime_is_valid_time (*priv->time)) { priv->year_set = TRUE; priv->month_set = TRUE; priv->day_set = TRUE; } } else { priv->time = g_slice_new0 (icaltimetype); *priv->time = icaltime_null_time (); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_time_dispose (GObject *object) { if (G_OBJECT_CLASS (jana_ecal_time_parent_class)->dispose) G_OBJECT_CLASS (jana_ecal_time_parent_class)->dispose (object); } static void jana_ecal_time_finalize (GObject *object) { JanaEcalTimePrivate *priv = TIME_PRIVATE (object); if (priv->time) { g_slice_free (icaltimetype, priv->time); priv->time = NULL; } G_OBJECT_CLASS (jana_ecal_time_parent_class)->finalize (object); } static void time_interface_init (gpointer g_iface, gpointer iface_data) { JanaTimeInterface *iface = (JanaTimeInterface *)g_iface; iface->get_seconds = time_get_seconds; iface->get_minutes = time_get_minutes; iface->get_hours = time_get_hours; iface->get_day = time_get_day; iface->get_month = time_get_month; iface->get_year = time_get_year; iface->get_isdate = time_get_isdate; iface->get_daylight = time_get_daylight; iface->get_tzname = time_get_tzname; iface->get_offset = time_get_offset; iface->set_seconds = time_set_seconds; iface->set_minutes = time_set_minutes; iface->set_hours = time_set_hours; iface->set_day = time_set_day; iface->set_month = time_set_month; iface->set_year = time_set_year; iface->set_isdate = time_set_isdate; iface->set_tzname = time_set_tzname; iface->set_offset = time_set_offset; iface->duplicate = time_duplicate; } static void jana_ecal_time_class_init (JanaEcalTimeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaEcalTimePrivate)); object_class->get_property = jana_ecal_time_get_property; object_class->set_property = jana_ecal_time_set_property; object_class->dispose = jana_ecal_time_dispose; object_class->finalize = jana_ecal_time_finalize; g_object_class_install_property ( object_class, PROP_ICALTIME, g_param_spec_pointer ( "icaltime", "struct icaltimetype *", "The icaltimetype represented by this JanaTime " "object.", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void jana_ecal_time_init (JanaEcalTime *self) { /*JanaEcalTimePrivate *priv = TIME_PRIVATE (self);*/ } /** * jana_ecal_time_new: * * Creates a new #JanaEcalTime. * * Returns: A new #JanaEcalTime, cast as a #JanaTime. */ JanaTime * jana_ecal_time_new () { return JANA_TIME (g_object_new (JANA_ECAL_TYPE_TIME, NULL)); } /** * jana_ecal_time_new_from_icaltime: * @time: An #icaltimetype * * Creates a new #JanaEcalTime using the given #icaltimetype. * * Returns: A new #JanaEcalTime, cast as a #JanaTime. */ JanaTime * jana_ecal_time_new_from_icaltime (const icaltimetype *time) { return JANA_TIME (g_object_new (JANA_ECAL_TYPE_TIME, "icaltime", time, NULL)); } /** * jana_ecal_time_new_from_ecaltime: * @time: An #ECalComponentDateTime * * Creates a new #JanaEcalTime using the given #ECalComponentDateTime * * Returns: A new #JanaEcalTime, cast as a #JanaTime */ JanaTime * jana_ecal_time_new_from_ecaltime (ECalComponentDateTime *dt) { if (dt->value) { if (dt->tzid) { icaltime_set_timezone (dt->value, icaltimezone_get_builtin_timezone_from_tzid ( dt->tzid)); } return jana_ecal_time_new_from_icaltime (dt->value); } else return NULL; } static guint8 time_get_seconds (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint8)priv->time->second; } static guint8 time_get_minutes (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint8)priv->time->minute; } static guint8 time_get_hours (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint8)priv->time->hour; } static guint8 time_get_day (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint8)priv->time->day; } static guint8 time_get_month (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint8)priv->time->month; } static guint16 time_get_year (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (guint16)priv->time->year; } static gboolean time_get_isdate (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return priv->time->is_date; } static gboolean time_get_daylight (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return priv->time->is_daylight; } static gchar * time_get_tzname (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); char *zone = icaltimezone_get_tznames ( (icaltimezone *)priv->time->zone); return zone ? g_strdup (zone) : g_strdup ("UTC"); } static void time_normalise (JanaTime *self, int offset) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if (priv->year_set && priv->month_set && priv->day_set) { /* Normalise the time and verify daylight settings */ *priv->time = icaltime_normalize (*priv->time); offset -= icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, &priv->time->is_daylight); if (offset) icaltime_adjust (priv->time, 0, 0, 0, -offset); } } static glong time_get_offset (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return (glong)icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); } static void time_set_seconds (JanaTime *self, gint seconds) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if (priv->time->is_date) return; offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->second = (int)seconds; time_normalise (self, offset); } static void time_set_minutes (JanaTime *self, gint minutes) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if (priv->time->is_date) return; offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->minute = (int)minutes; time_normalise (self, offset); } static void time_set_hours (JanaTime *self, gint hours) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if (priv->time->is_date) return; offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->hour = (int)hours; time_normalise (self, offset); } static void time_set_day (JanaTime *self, gint day) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->day = (int)day; time_normalise (self, offset); priv->day_set = TRUE; } static void time_set_month (JanaTime *self, gint month) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->month = (int)month; time_normalise (self, offset); priv->month_set = TRUE; } static void time_set_year (JanaTime *self, gint year) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->year = (int)year; time_normalise (self, offset); priv->year_set = TRUE; } static void time_set_isdate (JanaTime *self, gboolean isdate) { int offset; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); priv->time->is_date = isdate ? 1 : 0; if (isdate) { /* Set non-date fields to zero - required for queries */ priv->time->hour = 0; priv->time->minute = 0; priv->time->second = 0; } time_normalise (self, offset); } static void time_set_tzname (JanaTime *self, const gchar *tzname) { gint i, offset; icalarray *builtin; gboolean preserve = TRUE; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); const char *current_zone; if (!tzname || (strcmp ("UTC", tzname) == 0)) { icaltimezone_convert_time (priv->time, (icaltimezone *)priv->time->zone, icaltimezone_get_utc_timezone ()); priv->time->zone = icaltimezone_get_utc_timezone (); return; } current_zone = icaltimezone_get_tznames ((icaltimezone *) priv->time->zone); if (current_zone && (strcmp (tzname, current_zone) == 0)) return; offset = icaltimezone_get_utc_offset ( (icaltimezone *)priv->time->zone, priv->time, NULL); builtin = icaltimezone_get_builtin_timezones (); tzname_zone_loop: for (i = 0; i < builtin->num_elements; i++) { icaltimezone *zone = (icaltimezone *)icalarray_element_at ( builtin, i); int zone_offset; gchar *zone_tz; zone_tz = icaltimezone_get_tznames (zone); zone_offset = icaltimezone_get_utc_offset ( zone, priv->time, NULL); if (zone_tz && (strcasecmp (tzname, zone_tz) == 0)) { if ((!preserve) || (zone_offset == offset)) { icaltimezone_convert_time (priv->time, (icaltimezone *)priv->time->zone, zone); priv->time->zone = zone; return; } } } if (preserve) { preserve = FALSE; goto tzname_zone_loop; } g_warning ("%s: tzname '%s' not set", G_STRFUNC, tzname); } static void time_set_offset (JanaTime *self, glong offset) { gint i; gchar *tzname; icalarray *builtin; gboolean preserve = TRUE; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if (time_get_offset (self) == offset) return; tzname = icaltimezone_get_tznames ((icaltimezone *)priv->time->zone); if (!tzname) tzname = "UTC"; builtin = icaltimezone_get_builtin_timezones (); offset_zone_loop: for (i = 0; i < builtin->num_elements; i++) { icaltimezone *zone = (icaltimezone *)icalarray_element_at ( builtin, i); int zone_offset; gchar *zone_tz; zone_tz = icaltimezone_get_tznames (zone); zone_offset = icaltimezone_get_utc_offset ( zone, priv->time, NULL); if (zone_tz && (zone_offset == offset)) { if ((!preserve) || (strcasecmp (tzname, zone_tz) == 0)) { icaltimezone_convert_time (priv->time, (icaltimezone *)priv->time->zone, zone); priv->time->zone = zone; return; } } } if (preserve) { preserve = FALSE; goto offset_zone_loop; } g_warning ("%s: Offset '%ld' not set", G_STRFUNC, offset); } static JanaTime * time_duplicate (JanaTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return jana_ecal_time_new_from_icaltime (priv->time); } /** * jana_ecal_time_set_location: * @self: A #JanaEcalTime * @location: An iCal/vCalendar timezone string * * Sets the location of the time, using a timezone string such as * "Europe/London", as opposed to the libc timezone name as used in * jana_time_set_tzname(). The time will still be adjusted for the new * timezone. A %NULL location parameter will be treated as "UTC". */ void jana_ecal_time_set_location (JanaEcalTime *self, const gchar *location) { icaltimezone *zone; JanaEcalTimePrivate *priv = TIME_PRIVATE (self); if ((!location) || (strcmp (location, "UTC") == 0)) zone = icaltimezone_get_utc_timezone (); else zone = icaltimezone_get_builtin_timezone (location); if (zone) { icaltimezone *from_zone = priv->time->zone ? (icaltimezone *)priv->time->zone : icaltimezone_get_utc_timezone (); icaltimezone_convert_time (priv->time, from_zone, zone); priv->time->zone = zone; } } /** * jana_ecal_time_get_location: * @self: A #JanaEcalTime * * Retrieves the full timezone name of the given time. See * jana_ecal_time_set_location(). * * Returns: A string containing the full timezone name. This is owned by * libecal and must not be freed. */ const gchar * jana_ecal_time_get_location (JanaEcalTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); const gchar *location = (const gchar *)icaltimezone_get_location ( (icaltimezone *)priv->time->zone); return location ? location : "UTC"; } /** * jana_ecal_time_to_time_t * @self: A #JanaEcalTime * * Converts a #JanaEcalTime to time_t type. * * Returns: A time_t representation of the time. */ time_t jana_ecal_time_to_time_t (JanaEcalTime *self) { JanaEcalTimePrivate *priv = TIME_PRIVATE (self); return icaltime_as_timet (*priv->time); } jana/libjana-ecal/jana-ecal-component.h0000644000175000017500000000574011327631152020174 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_COMPONENT_H #define JANA_ECAL_COMPONENT_H #include #include #include #include #define JANA_ECAL_TYPE_COMPONENT (jana_ecal_component_get_type ()) #define JANA_ECAL_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_COMPONENT, \ JanaEcalComponent)) #define JANA_ECAL_COMPONENT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST \ ((vtable), \ JANA_ECAL_TYPE_COMPONENT, \ JanaEcalComponentClass)) #define JANA_ECAL_IS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_COMPONENT)) #define JANA_ECAL_IS_COMPONENT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE \ ((vtable), \ JANA_ECAL_TYPE_COMPONENT)) #define JANA_ECAL_COMPONENT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS \ ((inst), \ JANA_ECAL_TYPE_COMPONENT, \ JanaEcalComponentClass)) typedef struct _JanaEcalComponent JanaEcalComponent; typedef struct _JanaEcalComponentClass JanaEcalComponentClass; /** * JanaEcalComponent: * * The #JanaEcalComponent struct contains only private data. */ struct _JanaEcalComponent { GObject parent; }; struct _JanaEcalComponentClass { GObjectClass parent; }; GType jana_ecal_component_get_type (void); JanaComponent *jana_ecal_component_new_from_ecalcomp (ECalComponent *component); gchar * jana_ecal_component_get_summary (JanaEcalComponent *self); gchar * jana_ecal_component_get_description (JanaEcalComponent *self); gchar * jana_ecal_component_get_location (JanaEcalComponent *self); JanaTime * jana_ecal_component_get_start (JanaEcalComponent *self); JanaTime * jana_ecal_component_get_end (JanaEcalComponent *self); void jana_ecal_component_set_summary (JanaEcalComponent *self, const gchar *summary); void jana_ecal_component_set_description (JanaEcalComponent *self, const gchar *description); void jana_ecal_component_set_location (JanaEcalComponent *self, const gchar *location); void jana_ecal_component_set_start (JanaEcalComponent *self, JanaTime *start); void jana_ecal_component_set_end (JanaEcalComponent *self, JanaTime *end); #endif /* JANA_ECAL_COMPONENT_H */ jana/libjana-ecal/Makefile.am0000644000175000017500000000162411327631152016241 0ustar paulliupaulliuSUBDIRS = . doc localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" $(GOBJECT_CFLAGS) $(ECAL_CFLAGS) $(GCONF_CFLAGS) -Wall AM_LDFLAGS = $(GOBJECT_LIBS) $(ECAL_LIBS) $(GCONF_LIBS) source_h = jana-ecal.h \ jana-ecal-component.h \ jana-ecal-event.h \ jana-ecal-note.h \ jana-ecal-store.h \ jana-ecal-store-view.h \ jana-ecal-time.h \ jana-ecal-utils.h \ jana-ecal-task.h source_c = jana-ecal-component.c \ jana-ecal-event.c \ jana-ecal-note.c \ jana-ecal-store.c \ jana-ecal-store-view.c \ jana-ecal-time.c \ jana-ecal-utils.c \ jana-ecal-task.c lib_LTLIBRARIES = libjana-ecal.la libjana_ecal_la_LIBADD = $(top_srcdir)/libjana/libjana.la libjana_ecal_la_SOURCES = $(source_c) $(source_h) library_includedir=$(includedir)/jana/libjana-ecal library_include_HEADERS = $(source_h) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libjana-ecal.pc jana/libjana-ecal/jana-ecal-store.h0000644000175000017500000000431611327631152017324 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_STORE_H #define JANA_ECAL_STORE_H #include #include #include #include #include #define JANA_ECAL_TYPE_STORE (jana_ecal_store_get_type ()) #define JANA_ECAL_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_STORE, JanaEcalStore)) #define JANA_ECAL_STORE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), \ JANA_ECAL_TYPE_STORE, \ JanaEcalStoreClass)) #define JANA_ECAL_IS_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_STORE)) #define JANA_ECAL_IS_STORE_CLASS(vtable)(G_TYPE_CHECK_CLASS_TYPE ((vtable), \ JANA_ECAL_TYPE_STORE)) #define JANA_ECAL_STORE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ JANA_ECAL_TYPE_STORE, \ JanaEcalStoreClass)) typedef struct _JanaEcalStore JanaEcalStore; typedef struct _JanaEcalStoreClass JanaEcalStoreClass; /** * JanaEcalStore: * * The #JanaEcalStore struct contains only private data. */ struct _JanaEcalStore { GObject parent; }; struct _JanaEcalStoreClass { GObjectClass parent; }; GType jana_ecal_store_get_type (void); JanaStore *jana_ecal_store_new (JanaComponentType type); JanaStore *jana_ecal_store_new_from_uri (const gchar *uri, JanaComponentType type); const gchar *jana_ecal_store_get_uri (JanaEcalStore *store); #endif /* JANA_ECAL_STORE_H */ jana/libjana-ecal/jana-ecal.h0000644000175000017500000000274311327631152016174 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal * @short_description: An evolution-data-server based implementation of libjana */ #ifndef JANA_ECAL_H #define JANA_ECAL_H #ifndef HANDLE_LIBICAL_MEMORY #define HANDLE_LIBICAL_MEMORY 1 #define JANA_HANDLE_LIBICAL_MEMORY 1 #endif #include #include #include #include #include #include #include #include #ifdef JANA_HANDLE_LIBICAL_MEMORY #undef HANDLE_LIBICAL_MEMORY #endif #endif jana/libjana-ecal/jana-ecal-note.h0000644000175000017500000000405111327631152017131 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_NOTE_H #define JANA_ECAL_NOTE_H #include #include #include #include #define JANA_ECAL_TYPE_NOTE (jana_ecal_note_get_type ()) #define JANA_ECAL_NOTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_NOTE, JanaEcalNote)) #define JANA_ECAL_NOTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), \ JANA_ECAL_TYPE_NOTE, \ JanaEcalNoteClass)) #define JANA_ECAL_IS_NOTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_NOTE)) #define JANA_ECAL_IS_NOTE_CLASS(vtable)(G_TYPE_CHECK_CLASS_TYPE ((vtable), \ JANA_ECAL_TYPE_NOTE)) #define JANA_ECAL_NOTE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ JANA_ECAL_TYPE_NOTE, \ JanaEcalNoteClass)) typedef struct _JanaEcalNote JanaEcalNote; typedef struct _JanaEcalNoteClass JanaEcalNoteClass; /** * JanaEcalNote: * * The #JanaEcalNote struct contains only private data. */ struct _JanaEcalNote { GObject parent; }; struct _JanaEcalNoteClass { GObjectClass parent; }; GType jana_ecal_note_get_type (void); JanaNote *jana_ecal_note_new (); JanaNote *jana_ecal_note_new_from_ecalcomp (ECalComponent *note); #endif /* JANA_ECAL_NOTE_H */ jana/libjana-ecal/jana-ecal-note.c0000644000175000017500000001762211327631152017134 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-note * @short_description: An implementation of #JanaNote using libecal * * #JanaEcalNote is an implementation of #JanaNote that provides a * wrapper over #ECalComponent and its journal-related functions, using libecal. */ #define HANDLE_LIBICAL_MEMORY 1 #include "jana-ecal-note.h" #include "jana-ecal-component.h" #include "jana-ecal-time.h" #include "jana-ecal-utils.h" #include static void note_interface_init (gpointer g_iface, gpointer iface_data); static void component_interface_init (gpointer g_iface, gpointer iface_data); static JanaComponentType component_get_component_type (JanaComponent *self); static gboolean component_is_fully_represented (JanaComponent *self); static gchar * note_get_author (JanaNote *self); static gchar * note_get_recipient (JanaNote *self); static gchar * note_get_body (JanaNote *self); static JanaTime * note_get_creation_time (JanaNote *self); static JanaTime * note_get_modified_time (JanaNote *self); static void note_set_author (JanaNote *self, const gchar *author); static void note_set_recipient (JanaNote *self, const gchar *recipient); static void note_set_body (JanaNote *self, const gchar *body); static void note_set_creation_time (JanaNote *note, JanaTime *time); G_DEFINE_TYPE_WITH_CODE (JanaEcalNote, jana_ecal_note, JANA_ECAL_TYPE_COMPONENT, G_IMPLEMENT_INTERFACE (JANA_TYPE_COMPONENT, component_interface_init) G_IMPLEMENT_INTERFACE (JANA_TYPE_NOTE, note_interface_init)); static void component_interface_init (gpointer g_iface, gpointer iface_data) { JanaComponentInterface *iface = (JanaComponentInterface *)g_iface; iface->get_component_type = component_get_component_type; iface->is_fully_represented = component_is_fully_represented; } static void note_interface_init (gpointer g_iface, gpointer iface_data) { JanaNoteInterface *iface = (JanaNoteInterface *)g_iface; iface->get_author = note_get_author; iface->get_recipient = note_get_recipient; iface->get_body = note_get_body; iface->get_creation_time = note_get_creation_time; iface->get_modified_time = note_get_modified_time; iface->set_author = note_set_author; iface->set_recipient = note_set_recipient; iface->set_body = note_set_body; iface->set_creation_time = note_set_creation_time; } static void jana_ecal_note_class_init (JanaEcalNoteClass *klass) { /* Not overriding any object methods or adding private data */ } static void jana_ecal_note_init (JanaEcalNote *self) { /* No initialisation required */ } /** * jana_ecal_note_new: * * Creates a new #JanaEcalNote. * * Returns: A new #JanaEcalNote, cast as a #JanaNote. */ JanaNote * jana_ecal_note_new () { ECalComponent *comp = e_cal_component_new (); JanaTime *now; JanaNote *note; e_cal_component_set_icalcomponent (comp, icalcomponent_new (ICAL_VJOURNAL_COMPONENT)); note = JANA_NOTE (g_object_new (JANA_ECAL_TYPE_NOTE, "ecalcomp", comp, NULL)); /* Set creation time */ now = jana_ecal_utils_time_now_local (); note_set_creation_time (note, now); g_object_unref (now); return note; } /** * jana_ecal_note_new_from_ecalcomp: * @event: An #ECalComponent * * Creates a new #JanaEcalNote based on the given #ECalComponent. The type of * the given #ECalComponent must be %E_CAL_COMPONENT_JOURNAL. See * e_cal_component_get_vtype(). * * Returns: A new #JanaEcalNote that wraps the given #ECalComponent, cast as * a #JanaNote. */ JanaNote * jana_ecal_note_new_from_ecalcomp (ECalComponent *event) { return JANA_NOTE (g_object_new (JANA_ECAL_TYPE_NOTE, "ecalcomp", event, NULL)); } static JanaComponentType component_get_component_type (JanaComponent *self) { return JANA_COMPONENT_NOTE; } static gboolean component_is_fully_represented (JanaComponent *self) { GSList *desc_list; ECalComponent *comp; gboolean result = TRUE; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_description_list (comp, &desc_list); if (g_slist_length (desc_list) > 1) result = FALSE; e_cal_component_free_text_list (desc_list); g_object_unref (comp); return result; } static void set_modification_time (JanaNote *self) { JanaTime *now; ECalComponent *comp; icaltimetype *icaltime; g_object_get (self, "ecalcomp", &comp, NULL); /* Set modification time */ now = jana_ecal_utils_time_now_local (); g_object_get (now, "icaltime", &icaltime, NULL); e_cal_component_set_last_modified (comp, icaltime); jana_ecal_component_set_end (JANA_ECAL_COMPONENT (self), now); g_object_unref (now); g_object_unref (comp); } static gchar * note_get_author (JanaNote *self) { return jana_ecal_component_get_summary (JANA_ECAL_COMPONENT (self)); } static gchar * note_get_recipient (JanaNote *self) { return jana_ecal_component_get_location (JANA_ECAL_COMPONENT (self)); } static gchar * note_get_body (JanaNote *self) { return jana_ecal_component_get_description (JANA_ECAL_COMPONENT (self)); } static JanaTime * note_get_creation_time (JanaNote *self) { JanaTime *creation = jana_ecal_component_get_start ( JANA_ECAL_COMPONENT (self)); /* Event was probably created by another app and doesn't have dtstart * set. * FIXME: This will cause problems with store views... */ if (!creation) { icaltimetype *itime; ECalComponent *comp; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_created (comp, &itime); creation = jana_ecal_time_new_from_icaltime (itime); if (itime) e_cal_component_free_icaltimetype (itime); g_object_unref (comp); } return creation; } static JanaTime * note_get_modified_time (JanaNote *self) { JanaTime *modified = jana_ecal_component_get_end ( JANA_ECAL_COMPONENT (self)); /* Event was probably created by another app and doesn't have dtend * set. * FIXME: This will cause problems with store views... */ if (!modified) { icaltimetype *itime; ECalComponent *comp; g_object_get (self, "ecalcomp", &comp, NULL); e_cal_component_get_last_modified (comp, &itime); modified = jana_ecal_time_new_from_icaltime (itime); if (itime) e_cal_component_free_icaltimetype (itime); g_object_unref (comp); } return modified; } static void note_set_author (JanaNote *self, const gchar *author) { jana_ecal_component_set_summary (JANA_ECAL_COMPONENT (self), author); set_modification_time (self); } static void note_set_recipient (JanaNote *self, const gchar *recipient) { jana_ecal_component_set_location ( JANA_ECAL_COMPONENT (self), recipient); set_modification_time (self); } static void note_set_body (JanaNote *self, const gchar *body) { jana_ecal_component_set_description (JANA_ECAL_COMPONENT (self), body); set_modification_time (self); } static void note_set_creation_time (JanaNote *note, JanaTime *time) { icaltimetype *icaltime; ECalComponent *comp; if (JANA_ECAL_IS_TIME (time)) { time = g_object_ref (time); } else { time = jana_utils_time_copy ( time, jana_ecal_time_new ()); } g_object_get (note, "ecalcomp", &comp, NULL); g_object_get (time, "icaltime", &icaltime, NULL); e_cal_component_set_created (comp, icaltime); jana_ecal_component_set_start (JANA_ECAL_COMPONENT (note), time); g_object_unref (time); g_object_unref (comp); } jana/libjana-ecal/jana-ecal-utils.h0000644000175000017500000000365011327631152017330 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_UTILS_H #define JANA_ECAL_UTILS_H #include #include #include /** * JANA_ECAL_LOCATION_KEY: * * The GConf key path used to store the ecal timezone location. This will be * checked by jana_ecal_utils_guess_location() before any other method. For * convenience, this path is the same path Evolution uses to store its * ecal timezone location. */ #define JANA_ECAL_LOCATION_KEY "/apps/evolution/calendar/display/timezone" /** * JANA_ECAL_LOCATION_KEY_DIR: * @see_also: #JANA_ECAL_LOCATION_KEY * * The parent directory of the GConf key used to store the ecal timezone * location. If #JANA_ECAL_LOCATION_KEY exists, this GConf directory can be * monitored to detect when it has changed. See also #JANA_ECAL_LOCATION_KEY. */ #define JANA_ECAL_LOCATION_KEY_DIR "/apps/evolution/calendar/display" JanaTime * jana_ecal_utils_time_now (const gchar *location); JanaTime * jana_ecal_utils_time_now_local (); JanaTime * jana_ecal_utils_time_today (const gchar *location); gchar * jana_ecal_utils_guess_location (); gchar ** jana_ecal_utils_get_locations (); #endif jana/libjana-ecal/jana-ecal-utils.c0000644000175000017500000001571011327631152017323 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-utils * @short_description: A set of utility functions for libjana-ecal * * jana-ecal-utils contains a set of libjana-ecal related utility functions. */ #define HANDLE_LIBICAL_MEMORY 1 #include #include #include #include #include #include #include "jana-ecal-utils.h" /** * jana_ecal_utils_time_now: * @location: A full timezone name * * Creates a new #JanaEcalTime with the current time of the given location. * * Returns: A new #JanaEcalTime, cast as a #JanaTime. */ JanaTime * jana_ecal_utils_time_now (const gchar *location) { icaltimetype ical_time; const icaltimezone *zone; zone = (const icaltimezone *)icaltimezone_get_builtin_timezone ( location); ical_time = icaltime_current_time_with_zone (zone); icaltime_set_timezone (&ical_time, zone); return jana_ecal_time_new_from_icaltime (&ical_time); } /** * jana_ecal_utils_time_now_local: * * Creates a new #JanaEcalTime with the current time of the guessed location. * See jana_ecal_utils_guess_location(). * * Returns: A new #JanaEcalTime, cast as a #JanaTime. */ JanaTime * jana_ecal_utils_time_now_local () { gchar *location = jana_ecal_utils_guess_location (); JanaTime *time = jana_ecal_utils_time_now (location); g_free (location); return time; } /** * jana_ecal_utils_time_today: * @location: A full timezone name * * Creates a new #JanaEcalTime with the current date of the given location. * * Returns: A new #JanaEcalTime, cast as a #JanaTime. */ JanaTime * jana_ecal_utils_time_today (const gchar *location) { JanaTime *time; icaltimetype ical_time; const icaltimezone *zone; zone = (const icaltimezone *)icaltimezone_get_builtin_timezone ( location); ical_time = icaltime_current_time_with_zone (zone); icaltime_set_timezone (&ical_time, zone); time = jana_ecal_time_new_from_icaltime (&ical_time); jana_time_set_isdate (time, TRUE); return time; } /** * jana_ecal_utils_guess_location: * * Tries to guess the location by checking for common system settings and * files, and finally falling back on the first location that matches the * current system timezone. See also #JANA_ECAL_LOCATION_KEY. * * Returns: A newly allocated string with the guessed location. */ gchar * jana_ecal_utils_guess_location () { gint i; FILE *file; gchar *tzname; gchar string[128]; icaltimetype today; icalarray *builtin; time_t now_t = time (NULL); struct tm *now = localtime (&now_t); /* Check the Evolution timezone key first */ tzname = gconf_client_get_string (gconf_client_get_default (), JANA_ECAL_LOCATION_KEY, NULL); if (tzname && icaltimezone_get_builtin_timezone (tzname)) return tzname; g_free (tzname); /* Debian systems have /etc/timezone */ if ((file = fopen ("/etc/timezone", "r"))) { if ((fgets (string, 128, file)) && (string[0] != '\0')) { gint c; for (c = 0; (string[c] != '\0') && (string[c] != '\n'); c++); string[c] = '\0'; if (icaltimezone_get_builtin_timezone (string)) { fclose (file); return g_strdup (string); } } fclose (file); } #if GLIB_CHECK_VERSION(2,14,0) /* OpenSuSE (and RH?) systems have /etc/sysconfig/clock */ if ((file = fopen ("/etc/sysconfig/clock", "r"))) { GRegex *regex; GError *error = NULL; regex = g_regex_new ("ZONE *= *\".*\"", G_REGEX_OPTIMIZE, 0, &error); if (!regex) { g_warning ("Failed to create regex: %s", error->message); g_error_free (error); } else while (fgets (string, 128, file)) { GMatchInfo *match_info; if (g_regex_match (regex, string, 0, &match_info)) { gchar *zone; gchar *match = g_match_info_fetch ( match_info, 0); g_match_info_free (match_info); g_regex_unref (regex); regex = NULL; if (match[strlen (match) - 2] == '\n') match[strlen (match)-2] = '\0'; else match[strlen (match)-1] = '\0'; zone = g_strdup (strchr (match, '\"') + 1); g_free (match); if (icaltimezone_get_builtin_timezone (zone)) { fclose (file); return zone; } else { g_free (zone); break; } } g_match_info_free (match_info); } if (regex) g_regex_unref (regex); fclose (file); } #endif /* Check to see if the /etc/localtime symlink exists */ if (g_file_test ("/etc/localtime", G_FILE_TEST_IS_SYMLINK)) { gchar *link; if ((link = g_file_read_link ("/etc/localtime", NULL))) { tzname = g_strrstr (link, "zoneinfo/"); if (tzname && icaltimezone_get_builtin_timezone (tzname + 9)) { tzname = g_strdup (tzname + 9); g_free (link); return tzname; } g_free (link); } } /* Fallback to first location that matches libc timezone and the * offset for the current time. */ today = icaltime_today (); tzname = jana_utils_get_local_tzname (); if (strcmp (tzname, "UTC") == 0) return tzname; builtin = icaltimezone_get_builtin_timezones (); for (i = 0; i < builtin->num_elements; i++) { icaltimezone *zone = (icaltimezone *)icalarray_element_at ( builtin, i); gchar *zone_tz; int offset; offset = icaltimezone_get_utc_offset (zone, &today, NULL); zone_tz = icaltimezone_get_tznames (zone); if (zone_tz && (strcasecmp (tzname, zone_tz) == 0) && (offset == now->tm_gmtoff)) { g_free (tzname); return g_strdup (icaltimezone_get_display_name (zone)); } } g_free (tzname); /* No matching timezone found, fall back to UTC */ return g_strdup ("UTC"); } /** * jana_ecal_utils_get_locations: * * Retrieves the built-in list of timezone locations from libecal. * * Returns: A newly allocated string array, to be freed with g_strfreev(). */ gchar ** jana_ecal_utils_get_locations () { gint i, z; icalarray *builtin; gchar **locations; builtin = icaltimezone_get_builtin_timezones (); locations = g_new0 (gchar *, builtin->num_elements + 1); for (i = 0, z = 0; i < builtin->num_elements; i++) { icaltimezone *zone = (icaltimezone *)icalarray_element_at ( builtin, i); /* Don't return zones that don't have a tzname */ if (icaltimezone_get_tznames (zone)) { locations[z] = g_strdup ( icaltimezone_get_display_name (zone)); z++; } } return locations; } jana/libjana-ecal/jana-ecal-store.c0000644000175000017500000003124311327631152017316 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-store * @short_description: An implementation of #JanaStore using libecal * * #JanaEcalStore is an implementation of #JanaStore that provides a * wrapper over #ECal, using libecal. */ #ifdef HAVE_CONFIG_H #include #endif #define HANDLE_LIBICAL_MEMORY 1 #include #include "jana-ecal-component.h" #include "jana-ecal-event.h" #include "jana-ecal-note.h" #include "jana-ecal-task.h" #include "jana-ecal-store-view.h" #include "jana-ecal-store.h" static void store_interface_init (gpointer g_iface, gpointer iface_data); static void store_open (JanaStore *self); static JanaComponent * store_get_component (JanaStore *self, const gchar *uid); static JanaStoreView * store_get_view (JanaStore *self); static void store_add_component (JanaStore *self, JanaComponent *comp); static void store_modify_component (JanaStore *self, JanaComponent *comp); static void store_remove_component (JanaStore *self, JanaComponent *comp); static void store_cal_opened_cb (ECal *ecal, gint arg1, JanaStore *self); G_DEFINE_TYPE_WITH_CODE (JanaEcalStore, jana_ecal_store, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (JANA_TYPE_STORE, store_interface_init)); #define STORE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ JANA_ECAL_TYPE_STORE, JanaEcalStorePrivate)) typedef struct _JanaEcalStorePrivate JanaEcalStorePrivate; struct _JanaEcalStorePrivate { ECal *ecal; JanaComponentType type; }; enum { PROP_ECAL = 1, PROP_TYPE, }; static void jana_ecal_store_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaEcalStorePrivate *priv = STORE_PRIVATE (object); switch (property_id) { case PROP_ECAL : g_value_set_object (value, priv->ecal); break; case PROP_TYPE : g_value_set_int (value, priv->type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_store_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaEcalStorePrivate *priv = STORE_PRIVATE (object); switch (property_id) { case PROP_ECAL : priv->ecal = E_CAL (g_value_dup_object (value)); g_signal_connect (G_OBJECT (priv->ecal), "cal-opened", G_CALLBACK (store_cal_opened_cb), object); break; case PROP_TYPE : priv->type = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_store_dispose (GObject *object) { JanaEcalStorePrivate *priv = STORE_PRIVATE (object); if (priv->ecal) { g_object_unref (priv->ecal); priv->ecal = NULL; } if (G_OBJECT_CLASS (jana_ecal_store_parent_class)->dispose) G_OBJECT_CLASS (jana_ecal_store_parent_class)->dispose (object); } static void jana_ecal_store_finalize (GObject *object) { G_OBJECT_CLASS (jana_ecal_store_parent_class)->finalize (object); } static void store_interface_init (gpointer g_iface, gpointer iface_data) { JanaStoreInterface *iface = (JanaStoreInterface *)g_iface; iface->open = store_open; iface->get_component = store_get_component; iface->get_view = store_get_view; iface->add_component = store_add_component; iface->modify_component = store_modify_component; iface->remove_component = store_remove_component; } static void jana_ecal_store_class_init (JanaEcalStoreClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaEcalStorePrivate)); object_class->get_property = jana_ecal_store_get_property; object_class->set_property = jana_ecal_store_set_property; object_class->dispose = jana_ecal_store_dispose; object_class->finalize = jana_ecal_store_finalize; g_object_class_install_property ( object_class, PROP_ECAL, g_param_spec_object ( "ecal", "ECal *", "The ECal represented by this JanaStore object.", E_TYPE_CAL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_TYPE, g_param_spec_int ( "type", "JanaComponentType", "The component type stored in this JanaStore object.", JANA_COMPONENT_NULL, JANA_COMPONENT_TASK, JANA_COMPONENT_NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void jana_ecal_store_init (JanaEcalStore *self) { /*JanaEcalStorePrivate *priv = STORE_PRIVATE (self);*/ } #ifndef HAVE_ECAL_NEW_SYSTEM_MEMOS /* Taken from eds libecal */ static ECal * e_cal_new_system_memos (void) { ECal *ecal; char *uri; char *filename; filename = g_build_filename (g_get_home_dir (), ".evolution/memos/local/system", NULL); uri = g_filename_to_uri (filename, NULL, NULL); g_free (filename); ecal = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); g_free (uri); return ecal; } #endif /** * jana_ecal_store_new: * @type: The type of store to create/open * * Opens or creates the default evolution-data-server system storage for the * specified type of component. * * Returns: A #JanaEcalStore that wraps the evolution-data-server system * storage of the specified component type, cast as a #JanaStore. */ JanaStore * jana_ecal_store_new (JanaComponentType type) { ECal *ecal; switch (type) { case JANA_COMPONENT_EVENT : ecal = e_cal_new_system_calendar (); break; case JANA_COMPONENT_NOTE : ecal = e_cal_new_system_memos (); break; case JANA_COMPONENT_TASK : ecal = e_cal_new_system_tasks (); break; default : g_warning ("%s called with invalid type", G_STRFUNC); return NULL; } return JANA_STORE (g_object_new (JANA_ECAL_TYPE_STORE, "ecal", ecal, "type", type, NULL)); } static gboolean store_cal_opened_signal_cb (JanaStore *self) { g_signal_emit_by_name (self, "opened"); return FALSE; } static void store_cal_opened_cb (ECal *ecal, gint arg1, JanaStore *self) { /* This happens in a thread, so use g_idle_add to get back to the * main thread. */ g_idle_add ((GSourceFunc)store_cal_opened_signal_cb, self); } /** * jana_ecal_store_new_from_uri: * @uri: The uri to the store * @type: The type of store to create/open * * Opens or creates an evolution-data-server storage at the given uri for the * specified type of component. * * Returns: A #JanaEcalStore that wraps an evolution-data-server storage of * the specified component type at the given uri, cast as a #JanaStore. */ JanaStore * jana_ecal_store_new_from_uri (const gchar *uri, JanaComponentType type) { ECal *ecal; ECalSourceType etype; switch (type) { case JANA_COMPONENT_EVENT : etype = E_CAL_SOURCE_TYPE_EVENT; break; case JANA_COMPONENT_NOTE : etype = E_CAL_SOURCE_TYPE_JOURNAL; break; case JANA_COMPONENT_TASK : etype = E_CAL_SOURCE_TYPE_TODO; break; default : g_warning ("%s called with invalid type", G_STRFUNC); return NULL; } if ((ecal = e_cal_new_from_uri (uri, etype))) { return JANA_STORE (g_object_new (JANA_ECAL_TYPE_STORE, "ecal", ecal, "type", type, NULL)); } else { g_warning ("Could not create ECal in %s", G_STRFUNC); return NULL; } } /** * jana_ecal_store_get_uri * @store: The store to get the uri of. * * Returns: The uri of the calendar that this store represents. */ const gchar * jana_ecal_store_get_uri (JanaEcalStore *store) { JanaEcalStorePrivate *priv = STORE_PRIVATE (store); g_return_val_if_fail (JANA_ECAL_IS_STORE (store), NULL); return e_cal_get_uri (priv->ecal); } static void store_open (JanaStore *self) { JanaEcalStorePrivate *priv = STORE_PRIVATE (self); e_cal_open_async (priv->ecal, FALSE); } /* TODO: Test this function */ static JanaComponent * store_get_component (JanaStore *self, const gchar *uid) { GList *comps; JanaComponent *component; GError *error = NULL; JanaEcalStorePrivate *priv = STORE_PRIVATE (self); if (!e_cal_get_objects_for_uid (priv->ecal, uid, &comps, &error)) { g_warning ("Unable to retrieve event: %s", error->message); g_error_free (error); return NULL; } if (!comps) return NULL; switch (e_cal_component_get_vtype (E_CAL_COMPONENT (comps->data))) { case E_CAL_COMPONENT_EVENT : component = JANA_COMPONENT (jana_ecal_event_new_from_ecalcomp ( E_CAL_COMPONENT (comps->data))); break; case E_CAL_COMPONENT_TODO : case E_CAL_COMPONENT_JOURNAL : component = JANA_COMPONENT (jana_ecal_note_new_from_ecalcomp ( E_CAL_COMPONENT (comps->data))); break; default: component = jana_ecal_component_new_from_ecalcomp ( E_CAL_COMPONENT (comps->data)); break; } while (comps) { g_object_unref (comps->data); comps = g_list_delete_link (comps, comps); } return component; } static JanaStoreView * store_get_view (JanaStore *self) { return jana_ecal_store_view_new (JANA_ECAL_STORE (self)); } static JanaEcalComponent * get_jana_ecal_comp (JanaStore *self, JanaComponent *comp) { /*JanaEcalStorePrivate *priv = STORE_PRIVATE (self);*/ switch (jana_component_get_component_type (comp)) { case JANA_COMPONENT_EVENT : { JanaEcalEvent *event; if (!JANA_ECAL_IS_EVENT (comp)) { event = JANA_ECAL_EVENT ( jana_utils_event_copy (JANA_EVENT (comp), jana_ecal_event_new ())); } else { event = g_object_ref (JANA_ECAL_EVENT ( g_object_ref (comp))); } return JANA_ECAL_COMPONENT (event); break; } case JANA_COMPONENT_NOTE : { JanaEcalNote *note; if (!JANA_ECAL_IS_NOTE (comp)) { note = JANA_ECAL_NOTE ( jana_utils_note_copy (JANA_NOTE (comp), jana_ecal_note_new ())); } else { note = g_object_ref (JANA_ECAL_NOTE ( g_object_ref (comp))); } return JANA_ECAL_COMPONENT (note); break; } case JANA_COMPONENT_TASK : { JanaEcalTask *task; if (!JANA_ECAL_IS_TASK (comp)) { task = JANA_ECAL_TASK ( jana_utils_task_copy (JANA_TASK (comp), jana_ecal_task_new ())); } else { task = g_object_ref (JANA_ECAL_TASK ( g_object_ref (comp))); } return JANA_ECAL_COMPONENT (task); break; } default : g_warning ("%s called with invalid component type", G_STRFUNC); return NULL; } } static void store_add_component (JanaStore *self, JanaComponent *comp) { JanaEcalComponent *jcomp; ECalComponent *ecomp; icalcomponent *icalcomp; GError *error = NULL; char *uid; JanaEcalStorePrivate *priv = STORE_PRIVATE (self); if (!(jcomp = get_jana_ecal_comp (self, comp))) return; g_object_get (jcomp, "ecalcomp", &ecomp, NULL); /* Reset the UID to avoid collisions when adding the same JanaComponent * object multiple times. */ uid = e_cal_component_gen_uid (); e_cal_component_set_uid (ecomp, uid); g_free (uid); icalcomp = e_cal_component_get_icalcomponent (ecomp); if (!e_cal_create_object (priv->ecal, icalcomp, &uid, &error)) { g_warning ("Error adding component to store: %s", error->message); } else { /* Note, older versions of eds don't set the uid on object * creation. This is fixed in eds-dbus and svn eds. */ icalcomponent_set_uid (icalcomp, uid); } g_object_unref (ecomp); g_object_unref (jcomp); } static void store_modify_component (JanaStore *self, JanaComponent *comp) { JanaEcalComponent *jcomp; ECalComponent *ecomp; GError *error = NULL; JanaEcalStorePrivate *priv = STORE_PRIVATE (self); if (!(jcomp = get_jana_ecal_comp (self, comp))) return; g_object_get (jcomp, "ecalcomp", &ecomp, NULL); if (!e_cal_modify_object (priv->ecal, e_cal_component_get_icalcomponent (ecomp), CALOBJ_MOD_ALL, &error)) { g_warning ("Error modifying component: %s", error->message); } g_object_unref (ecomp); g_object_unref (jcomp); } static void store_remove_component (JanaStore *self, JanaComponent *comp) { gchar *uid; GError *error = NULL; JanaEcalStorePrivate *priv = STORE_PRIVATE (self); uid = jana_component_get_uid (comp); if (!(e_cal_remove_object (priv->ecal, uid, &error))) { g_warning ("Error removing component: %s", error->message); } g_free (uid); } jana/libjana-ecal/jana-ecal-time.h0000644000175000017500000000444211327631152017126 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef JANA_ECAL_TIME_H #define JANA_ECAL_TIME_H #include #include #include #include #define JANA_ECAL_TYPE_TIME (jana_ecal_time_get_type ()) #define JANA_ECAL_TIME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ JANA_ECAL_TYPE_TIME, JanaEcalTime)) #define JANA_ECAL_TIME_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), \ JANA_ECAL_TYPE_TIME,JanaEcalTimeClass)) #define JANA_ECAL_IS_TIME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ JANA_ECAL_TYPE_TIME)) #define JANA_ECAL_IS_TIME_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), \ JANA_ECAL_TYPE_TIME)) #define JANA_ECAL_TIME_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ JANA_ECAL_TYPE_TIME,JanaEcalTimeClass)) typedef struct _JanaEcalTime JanaEcalTime; typedef struct _JanaEcalTimeClass JanaEcalTimeClass; /** * JanaEcalTime: * * The #JanaEcalTime struct contains only private data. */ struct _JanaEcalTime { GObject parent; }; struct _JanaEcalTimeClass { GObjectClass parent; }; GType jana_ecal_time_get_type (void); JanaTime *jana_ecal_time_new (); JanaTime *jana_ecal_time_new_from_icaltime (const icaltimetype *time); JanaTime *jana_ecal_time_new_from_ecaltime (ECalComponentDateTime *dt); void jana_ecal_time_set_location (JanaEcalTime *self, const gchar *location); const gchar *jana_ecal_time_get_location (JanaEcalTime *self); time_t jana_ecal_time_to_time_t (JanaEcalTime *self); #endif /* JANA_ECAL_TIME_H */ jana/libjana-ecal/jana-ecal-store-view.c0000644000175000017500000004601211327631152020266 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-store-view * @short_description: An implementation of #JanaStoreView using libecal * * #JanaEcalStoreView is an implementation of #JanaStoreView that provides a * wrapper over #ECalView, using libecal. */ #ifdef HAVE_CONFIG_H # include #endif #define HANDLE_LIBICAL_MEMORY 1 #include #include #include #include #include "jana-ecal-component.h" #include "jana-ecal-event.h" #include "jana-ecal-note.h" #include "jana-ecal-task.h" #include "jana-ecal-time.h" #include "jana-ecal-store-view.h" static void store_view_interface_init (gpointer g_iface, gpointer iface_data); static void store_view_get_range (JanaStoreView *self, JanaTime **start, JanaTime **end); static void store_view_set_range (JanaStoreView *self, JanaTime *start, JanaTime *end); static JanaStoreViewMatch *store_view_add_match (JanaStoreView *self, JanaStoreViewField field, const gchar *data); static GList * store_view_get_matches (JanaStoreView *self); static void store_view_remove_match (JanaStoreView *self, JanaStoreViewMatch *match); static void store_view_clear_matches(JanaStoreView *self); static void store_view_start (JanaStoreView *self); static JanaStore *store_view_get_store (JanaStoreView *self); static gboolean store_view_refresh_query (JanaEcalStoreView *self); G_DEFINE_TYPE_WITH_CODE (JanaEcalStoreView, jana_ecal_store_view, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (JANA_TYPE_STORE_VIEW, store_view_interface_init)); #define STORE_VIEW_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ JANA_ECAL_TYPE_STORE_VIEW, JanaEcalStoreViewPrivate)) typedef struct _JanaEcalStoreViewPrivate JanaEcalStoreViewPrivate; struct _JanaEcalStoreViewPrivate { JanaEcalStore *parent; ECalView *query; JanaEcalTime *start; JanaEcalTime *end; GList *matches; guint timeout; GList *current_uids; GList *old_uids; gboolean started; guint remove_id; guint refresh_id; }; enum { PROP_PARENT = 1, PROP_VIEW, PROP_START, PROP_END, PROP_TIMEOUT, }; static void jana_ecal_store_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (object); switch (property_id) { case PROP_PARENT : g_value_set_object (value, priv->parent); break; case PROP_VIEW : g_value_set_object (value, priv->query); break; case PROP_START : g_value_take_object (value, jana_time_duplicate ( JANA_TIME (priv->start))); break; case PROP_END : g_value_take_object (value, jana_time_duplicate ( JANA_TIME (priv->end))); break; case PROP_TIMEOUT : g_value_set_uint (value, priv->timeout); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_store_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (object); switch (property_id) { case PROP_PARENT : priv->parent = JANA_ECAL_STORE (g_value_dup_object (value)); store_view_refresh_query (JANA_ECAL_STORE_VIEW (object)); break; case PROP_START : jana_store_view_set_range (JANA_STORE_VIEW (object), JANA_TIME (g_value_get_object (value)), JANA_TIME (priv->end)); break; case PROP_END : jana_store_view_set_range (JANA_STORE_VIEW (object), JANA_TIME (priv->start), JANA_TIME (g_value_get_object (value))); break; case PROP_TIMEOUT : priv->timeout = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_store_view_dispose (GObject *object) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (object); if (priv->remove_id) { g_source_remove (priv->remove_id); priv->remove_id = 0; } if (priv->refresh_id) { g_source_remove (priv->refresh_id); priv->refresh_id = 0; } if (priv->query) { g_object_unref (priv->query); priv->query = NULL; } if (priv->parent) { g_object_unref (priv->parent); priv->parent = NULL; } if (priv->start) { g_object_unref (priv->start); priv->start = NULL; } if (priv->end) { g_object_unref (priv->end); priv->end = NULL; } if (G_OBJECT_CLASS (jana_ecal_store_view_parent_class)->dispose) G_OBJECT_CLASS (jana_ecal_store_view_parent_class)->dispose ( object); } static void jana_ecal_store_view_finalize (GObject *object) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (object); while (priv->old_uids) { g_free (priv->old_uids->data); priv->old_uids = g_list_delete_link (priv->old_uids, priv->old_uids); } while (priv->current_uids) { g_free (priv->current_uids->data); priv->current_uids = g_list_delete_link (priv->current_uids, priv->current_uids); } G_OBJECT_CLASS (jana_ecal_store_view_parent_class)->finalize (object); } static void store_view_interface_init (gpointer g_iface, gpointer iface_data) { JanaStoreViewInterface *iface = (JanaStoreViewInterface *)g_iface; iface->get_range = store_view_get_range; iface->set_range = store_view_set_range; iface->add_match = store_view_add_match; iface->get_matches = store_view_get_matches; iface->remove_match = store_view_remove_match; iface->clear_matches = store_view_clear_matches; iface->start = store_view_start; iface->get_store = store_view_get_store; } static void jana_ecal_store_view_class_init (JanaEcalStoreViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (JanaEcalStoreViewPrivate)); object_class->get_property = jana_ecal_store_view_get_property; object_class->set_property = jana_ecal_store_view_set_property; object_class->dispose = jana_ecal_store_view_dispose; object_class->finalize = jana_ecal_store_view_finalize; g_object_class_install_property ( object_class, PROP_PARENT, g_param_spec_object ( "parent", "JanaEcalStore *", "The JanaEcalStore this view is filtering.", JANA_ECAL_TYPE_STORE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_VIEW, g_param_spec_object ( "view", "ECalView *", "The ECalView being used to query the parent ECal.", E_TYPE_CAL_VIEW, G_PARAM_READABLE)); g_object_class_install_property ( object_class, PROP_START, g_param_spec_object ( "start", "JanaTime *", "The start of the range being queried.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_END, g_param_spec_object ( "end", "JanaTime *", "The end of the range being queried.", G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_TIMEOUT, g_param_spec_uint ( "timeout", "guint", "The time-out (in milliseconds) before components from " "an old query are removed.", 0, G_MAXUINT, 0, G_PARAM_READWRITE)); } static void jana_ecal_store_view_init (JanaEcalStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); /* FIXME: For timeout to really work, need to store event time * and check if it's still in range when range changes - * but this is complicated by recurring events, so just * setting the default timeout to zero for now. */ priv->timeout = 0; } /** * jana_ecal_store_view_new: * @store: A #JanaEcalStore * * Creates a new #JanaEcalStoreView on the given store. * * Returns: A new #JanaEcalStoreView, cast as a #JanaStoreView. */ JanaStoreView * jana_ecal_store_view_new (JanaEcalStore *store) { return JANA_STORE_VIEW (g_object_new (JANA_ECAL_TYPE_STORE_VIEW, "parent", store, NULL)); } static gboolean store_view_remove_old_cb (JanaEcalStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); if (priv->old_uids) { g_signal_emit_by_name (self, "removed", priv->old_uids); while (priv->old_uids) { g_free (priv->old_uids->data); priv->old_uids = g_list_delete_link (priv->old_uids, priv->old_uids); } } priv->remove_id = 0; return FALSE; } static JanaComponent * store_view_jcomp_from_ecomp (ECalComponent *comp) { JanaComponent *jcomp; switch (e_cal_component_get_vtype (comp)) { case E_CAL_COMPONENT_EVENT : jcomp = JANA_COMPONENT ( jana_ecal_event_new_from_ecalcomp (comp)); break; case E_CAL_COMPONENT_JOURNAL : jcomp = JANA_COMPONENT ( jana_ecal_note_new_from_ecalcomp (comp)); break; case E_CAL_COMPONENT_TODO : jcomp = JANA_COMPONENT ( jana_ecal_task_new_from_ecalcomp (comp)); break; default : jcomp = jana_ecal_component_new_from_ecalcomp (comp); break; } return jcomp; } static void store_view_objects_added_cb (ECalView *query, GList *objects, JanaStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); GList *comps_added = NULL; GList *comps_modified = NULL; for (; objects; objects = objects->next) { JanaComponent *jcomp; const char *uid = icalcomponent_get_uid (objects->data); GList *previous_uid = g_list_find_custom (priv->old_uids, uid, (GCompareFunc)strcmp); ECalComponent *comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (objects->data)); jcomp = store_view_jcomp_from_ecomp (comp); if (previous_uid) { g_free (previous_uid->data); priv->old_uids = g_list_delete_link ( priv->old_uids, previous_uid); comps_modified = g_list_prepend (comps_modified, jcomp); } else comps_added = g_list_prepend (comps_added, jcomp); priv->current_uids = g_list_prepend (priv->current_uids, g_strdup (uid)); } if (comps_added) g_signal_emit_by_name (self, "added", comps_added); if (comps_modified) g_signal_emit_by_name (self, "modified", comps_modified); while (comps_added) { g_object_unref (G_OBJECT (comps_added->data)); comps_added = g_list_delete_link (comps_added, comps_added); } while (comps_modified) { g_object_unref (G_OBJECT (comps_modified->data)); comps_modified = g_list_delete_link ( comps_modified, comps_modified); } } static void store_view_objects_modified_cb (ECalView *query, GList *objects, JanaStoreView *self) { /*JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self);*/ GList *comps_modified = NULL; for (; objects; objects = objects->next) { JanaComponent *jcomp; ECalComponent *comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (objects->data)); jcomp = store_view_jcomp_from_ecomp (comp); comps_modified = g_list_prepend (comps_modified, jcomp); } if (comps_modified) g_signal_emit_by_name (self, "modified", comps_modified); while (comps_modified) { g_object_unref (G_OBJECT (comps_modified->data)); comps_modified = g_list_delete_link ( comps_modified, comps_modified); } } static void store_view_objects_removed_cb (ECalView *query, GList *uids, JanaStoreView *self) { GList *comps_removed = NULL; for (; uids; uids = uids->next) { #ifdef HAVE_ECALCOMPONENTID ECalComponentId *id = uids->data; comps_removed = g_list_prepend (comps_removed, id->uid); #else comps_removed = g_list_prepend (comps_removed, uids->data); #endif } g_signal_emit_by_name (self, "removed", comps_removed); g_list_free (comps_removed); } static void store_view_progress_cb (ECalView *query, gchar *message, gint percent, JanaStoreView *self) { /* Ignore 100%, we'll get the done signal - we don't want to emit 1.0 * twice. */ if (percent < 100) g_signal_emit_by_name (self, "progress", percent); } static void store_view_done_cb (ECalView *query, ECalendarStatus status, JanaStoreView *self) { g_signal_emit_by_name (self, "progress", 100); } static gchar * get_match_string (GList *matches) { GList *m; GString *string; gchar *match_string; if (!matches) return NULL; string = g_string_new (""); for (m = matches; m; m = m->next) { JanaStoreViewMatch *match; const gchar *field; if (m != matches) { g_string_prepend (string, "(or "); g_string_append_c (string, ' '); } match = (JanaStoreViewMatch *)m->data; switch (match->field) { case JANA_STORE_VIEW_AUTHOR : case JANA_STORE_VIEW_SUMMARY : field = "summary"; break; case JANA_STORE_VIEW_RECIPIENT : case JANA_STORE_VIEW_LOCATION : field = "location"; break; case JANA_STORE_VIEW_BODY : case JANA_STORE_VIEW_DESCRIPTION : field = "description"; break; case JANA_STORE_VIEW_ANYFIELD : default : field = "any"; break; } if (match->field == JANA_STORE_VIEW_CATEGORY) { g_string_append_printf (string, "(has-categories? \"%s\")", match->data); } else { g_string_append_printf (string, "(contains? \"%s\" \"%s\")", field, match->data); } if (m != matches) g_string_append_c (string, ')'); } match_string = string->str; g_string_free (string, FALSE); return match_string; } static gboolean store_view_refresh_query (JanaEcalStoreView *self) { ECal *ecal; gchar *query; GError *error = NULL; JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); if (priv->query) { g_object_unref (priv->query); priv->query = NULL; } priv->old_uids = g_list_concat (priv->old_uids, priv->current_uids); priv->current_uids = NULL; if (priv->start || priv->end || priv->matches) { gchar *start, *end; if (priv->start) { icaltimetype *ical_start; g_object_get (priv->start, "icaltime", &ical_start, NULL); start = isodate_from_time_t ( icaltime_as_timet_with_zone (*ical_start, ical_start->zone)); } else start = isodate_from_time_t (0); if (priv->end) { icaltimetype *ical_end; g_object_get (priv->end, "icaltime", &ical_end, NULL); end = isodate_from_time_t (icaltime_as_timet_with_zone ( *ical_end, ical_end->zone)); } else end = isodate_from_time_t (G_MAXLONG); if (priv->matches) { gchar *match = get_match_string (priv->matches); query = g_strdup_printf ("(and %s " "(occur-in-time-range? " "(make-time \"%s\") (make-time \"%s\")))", match, start, end); g_free (match); } else query = g_strdup_printf ("(occur-in-time-range? " "(make-time \"%s\") (make-time \"%s\"))", start, end); g_free (start); g_free (end); } else { query = g_strdup ("#t"); } g_object_get (priv->parent, "ecal", &ecal, NULL); if (!e_cal_get_query (ecal, query, &priv->query, &error)) { g_warning ("Failed to retrieve query '%s': %s", query, error->message); g_error_free (error); } else { g_signal_connect (priv->query, "objects-added", G_CALLBACK (store_view_objects_added_cb), self); g_signal_connect (priv->query, "objects-modified", G_CALLBACK (store_view_objects_modified_cb), self); g_signal_connect (priv->query, "objects-removed", G_CALLBACK (store_view_objects_removed_cb), self); g_signal_connect (priv->query, "view_progress", G_CALLBACK (store_view_progress_cb), self); g_signal_connect (priv->query, "view_done", G_CALLBACK (store_view_done_cb), self); if (priv->started) e_cal_view_start (priv->query); } g_free (query); g_object_unref (ecal); /* Remove old components (but possibly wait to see if they don't need * removing, to prevent 'flickering' when resizing the view). */ if (priv->old_uids) { if (priv->timeout) { if (priv->remove_id) g_source_remove (priv->remove_id); priv->remove_id = g_timeout_add ( priv->timeout, (GSourceFunc) store_view_remove_old_cb, self); } else store_view_remove_old_cb (self); } priv->refresh_id = 0; return FALSE; } static void store_view_get_range (JanaStoreView *self, JanaTime **start, JanaTime **end) { /*JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self);*/ g_object_get (self, "start", start, "end", end, NULL); } static void store_view_set_range (JanaStoreView *self, JanaTime *start, JanaTime *end) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); if (priv->start) g_object_unref (priv->start); if (!start) { priv->start = NULL; } else { if (JANA_ECAL_IS_TIME (start)) priv->start = JANA_ECAL_TIME ( jana_time_duplicate (start)); else priv->start = JANA_ECAL_TIME (jana_utils_time_copy ( start, jana_ecal_time_new ())); } if (priv->end) g_object_unref (priv->end); if (!end) { priv->end = NULL; } else { if (JANA_ECAL_IS_TIME (end)) priv->end = JANA_ECAL_TIME ( jana_time_duplicate (end)); else priv->end = JANA_ECAL_TIME (jana_utils_time_copy ( end, jana_ecal_time_new ())); } store_view_refresh_query (JANA_ECAL_STORE_VIEW (self)); } static JanaStoreViewMatch * store_view_add_match (JanaStoreView *self, JanaStoreViewField field, const gchar *data) { JanaStoreViewMatch *match; JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); g_assert (data); match = g_slice_alloc (sizeof (JanaStoreViewMatch)); match->field = field; match->data = g_strdup (data); priv->matches = g_list_prepend (priv->matches, match); if (!priv->refresh_id) priv->refresh_id = g_idle_add ( (GSourceFunc)store_view_refresh_query, self); return match; } static GList * store_view_get_matches (JanaStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); return g_list_copy (priv->matches); } static void store_view_remove_match (JanaStoreView *self, JanaStoreViewMatch *match) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); priv->matches = g_list_remove (priv->matches, match); g_free (match->data); g_slice_free (JanaStoreViewMatch, match); if (!priv->refresh_id) priv->refresh_id = g_idle_add ( (GSourceFunc)store_view_refresh_query, self); } static void store_view_clear_matches (JanaStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); while (priv->matches) { store_view_remove_match (self, (JanaStoreViewMatch *)priv->matches->data); } } static void store_view_start (JanaStoreView *self) { JanaEcalStoreViewPrivate *priv = STORE_VIEW_PRIVATE (self); if (priv->query && (!priv->started)) { e_cal_view_start (priv->query); } priv->started = TRUE; } static JanaStore * store_view_get_store (JanaStoreView *self) { JanaStore *store; g_object_get (self, "parent", &store, NULL); return store; } jana/libjana-ecal/doc/0000755000175000017500000000000011327631152014747 5ustar paulliupaulliujana/libjana-ecal/doc/Makefile.am0000644000175000017500000000002211327631152016775 0ustar paulliupaulliuSUBDIRS=reference jana/libjana-ecal/doc/reference/0000755000175000017500000000000011327631152016705 5ustar paulliupaulliujana/libjana-ecal/doc/reference/libjana-ecal-docs.sgml0000644000175000017500000000131011327631152023014 0ustar paulliupaulliu libjana-ecal Reference Manual libjana-ecal jana/libjana-ecal/doc/reference/Makefile.am0000644000175000017500000000542511327631152020747 0ustar paulliupaulliu## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libjana-ecal # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=../../ # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/libjana-ecal/*.h CFILE_GLOB=$(top_srcdir)/libjana-ecal/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES= # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) INCLUDES=-I$(top_srcdir)/src -I$(top_builddir) $(GOBJECT_CFLAGS) $(ECAL_CFLAGS) GTKDOC_LIBS=$(top_srcdir)/libjana-ecal/libjana-ecal.la $(GOBJECT_LIBS) $(ECAL_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = version.xml.in jana/libjana-ecal/doc/reference/libjana-ecal-sections.txt0000644000175000017500000000513711327631152023603 0ustar paulliupaulliu
jana-ecal-event JanaEcalEvent JanaEcalEvent jana_ecal_event_new jana_ecal_event_new_from_ecalcomp JANA_ECAL_EVENT JANA_ECAL_IS_EVENT JANA_ECAL_TYPE_EVENT jana_ecal_event_get_type JANA_ECAL_EVENT_CLASS JANA_ECAL_IS_EVENT_CLASS JANA_ECAL_EVENT_GET_CLASS
jana-ecal-note JanaEcalNote JanaEcalNote jana_ecal_note_new jana_ecal_note_new_from_ecalcomp JANA_ECAL_NOTE JANA_ECAL_IS_NOTE JANA_ECAL_TYPE_NOTE jana_ecal_note_get_type JANA_ECAL_NOTE_CLASS JANA_ECAL_IS_NOTE_CLASS JANA_ECAL_NOTE_GET_CLASS
jana-ecal-component JanaEcalComponent JanaEcalComponent jana_ecal_component_new_from_ecalcomp jana_ecal_component_get_summary jana_ecal_component_get_description jana_ecal_component_get_location jana_ecal_component_get_start jana_ecal_component_get_end jana_ecal_component_set_summary jana_ecal_component_set_description jana_ecal_component_set_location jana_ecal_component_set_start jana_ecal_component_set_end JANA_ECAL_COMPONENT JANA_ECAL_IS_COMPONENT JANA_ECAL_TYPE_COMPONENT jana_ecal_component_get_type JANA_ECAL_COMPONENT_CLASS JANA_ECAL_IS_COMPONENT_CLASS JANA_ECAL_COMPONENT_GET_CLASS
jana-ecal-store-view JanaEcalStoreView JanaEcalStoreView jana_ecal_store_view_new JANA_ECAL_STORE_VIEW JANA_ECAL_IS_STORE_VIEW JANA_ECAL_TYPE_STORE_VIEW jana_ecal_store_view_get_type JANA_ECAL_STORE_VIEW_CLASS JANA_ECAL_IS_STORE_VIEW_CLASS JANA_ECAL_STORE_VIEW_GET_CLASS
jana-ecal-store JanaEcalStore JanaEcalStore jana_ecal_store_new jana_ecal_store_new_from_uri JANA_ECAL_STORE JANA_ECAL_IS_STORE JANA_ECAL_TYPE_STORE jana_ecal_store_get_type JANA_ECAL_STORE_CLASS JANA_ECAL_IS_STORE_CLASS JANA_ECAL_STORE_GET_CLASS
jana-ecal-time JanaEcalTime JanaEcalTime jana_ecal_time_new jana_ecal_time_new_from_icaltime jana_ecal_time_new_from_ecaltime jana_ecal_time_set_location jana_ecal_time_get_location JANA_ECAL_TIME JANA_ECAL_IS_TIME JANA_ECAL_TYPE_TIME jana_ecal_time_get_type JANA_ECAL_TIME_CLASS JANA_ECAL_IS_TIME_CLASS JANA_ECAL_TIME_GET_CLASS
jana-ecal-utils jana_ecal_utils_time_now jana_ecal_utils_time_now_local jana_ecal_utils_time_today jana_ecal_utils_guess_location jana_ecal_utils_get_locations JANA_ECAL_LOCATION_KEY JANA_ECAL_LOCATION_KEY_DIR
jana-ecal
jana/libjana-ecal/doc/reference/tmpl/0000755000175000017500000000000011327631152017661 5ustar paulliupaulliujana/libjana-ecal/doc/reference/tmpl/dummy.sgml0000644000175000017500000000000011327631152021666 0ustar paulliupaulliujana/libjana-ecal/doc/reference/version.xml.in0000644000175000017500000000001211327631152021512 0ustar paulliupaulliu@VERSION@ jana/libjana-ecal/doc/reference/libjana-ecal.types0000644000175000017500000000023511327631152022275 0ustar paulliupaulliujana_ecal_event_get_type jana_ecal_note_get_type jana_ecal_component_get_type jana_ecal_store_view_get_type jana_ecal_store_get_type jana_ecal_time_get_type jana/libjana-ecal/jana-ecal-event.c0000644000175000017500000004060511327631152017305 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /** * SECTION:jana-ecal-event * @short_description: An implementation of #JanaEvent using libecal * * #JanaEcalEvent is an implementation of #JanaEvent that provides a * wrapper over #ECalComponent and its event-related functions, using libecal. */ #define HANDLE_LIBICAL_MEMORY 1 #include "jana-ecal-component.h" #include "jana-ecal-event.h" #include "jana-ecal-time.h" #include #include #include #include #include static void event_interface_init (gpointer g_iface, gpointer iface_data); static void component_interface_init (gpointer g_iface, gpointer iface_data); static JanaComponentType component_get_component_type (JanaComponent *self); static gboolean component_is_fully_represented (JanaComponent *self); static gchar * event_get_summary (JanaEvent *self); static gchar * event_get_description (JanaEvent *self); static gchar * event_get_location (JanaEvent *self); static JanaTime * event_get_start (JanaEvent *self); static JanaTime * event_get_end (JanaEvent *self); static gboolean event_supports_alarm (JanaEvent *self); static gboolean event_has_alarm (JanaEvent *self); static JanaTime *event_get_alarm_time (JanaEvent *self); static gboolean event_supports_recurrence (JanaEvent *self); static gboolean event_has_recurrence (JanaEvent *self); static JanaRecurrence * event_get_recurrence (JanaEvent *self); static gboolean event_supports_exceptions (JanaEvent *self); static gboolean event_has_exceptions (JanaEvent *self); static GList * event_get_exceptions (JanaEvent *self); static void event_set_summary (JanaEvent *self, const gchar *summary); static void event_set_description (JanaEvent *self, const gchar *description); static void event_set_location (JanaEvent *self, const gchar *location); static void event_set_start (JanaEvent *self, JanaTime *start); static void event_set_end (JanaEvent *self, JanaTime *end); static void event_set_alarm (JanaEvent *self, JanaTime *time); static void event_set_recurrence (JanaEvent *self, const JanaRecurrence *recurrence); static void event_set_exceptions (JanaEvent *self, GList *exceptions); G_DEFINE_TYPE_WITH_CODE (JanaEcalEvent, jana_ecal_event, JANA_ECAL_TYPE_COMPONENT, G_IMPLEMENT_INTERFACE (JANA_TYPE_COMPONENT, component_interface_init) G_IMPLEMENT_INTERFACE (JANA_TYPE_EVENT, event_interface_init)); #define EVENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ JANA_ECAL_TYPE_EVENT, JanaEcalEventPrivate)) typedef struct _JanaEcalEventPrivate JanaEcalEventPrivate; struct _JanaEcalEventPrivate { }; static void jana_ecal_event_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { /*JanaEcalEventPrivate *priv = EVENT_PRIVATE (object);*/ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_event_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { /*JanaEcalEventPrivate *priv = EVENT_PRIVATE (object);*/ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void jana_ecal_event_dispose (GObject *object) { if (G_OBJECT_CLASS (jana_ecal_event_parent_class)->dispose) G_OBJECT_CLASS (jana_ecal_event_parent_class)->dispose (object); } static void jana_ecal_event_finalize (GObject *object) { G_OBJECT_CLASS (jana_ecal_event_parent_class)->finalize (object); } static void component_interface_init (gpointer g_iface, gpointer iface_data) { JanaComponentInterface *iface = (JanaComponentInterface *)g_iface; iface->get_component_type = component_get_component_type; iface->is_fully_represented = component_is_fully_represented; } static void event_interface_init (gpointer g_iface, gpointer iface_data) { JanaEventInterface *iface = (JanaEventInterface *)g_iface; iface->get_summary = event_get_summary; iface->get_description = event_get_description; iface->get_location = event_get_location; iface->get_start = event_get_start; iface->get_end = event_get_end; iface->supports_alarm = event_supports_alarm; iface->has_alarm = event_has_alarm; iface->get_alarm_time = event_get_alarm_time; iface->supports_recurrence = event_supports_recurrence; iface->has_recurrence = event_has_recurrence; iface->get_recurrence = event_get_recurrence; iface->supports_exceptions = event_supports_exceptions; iface->has_exceptions = event_has_exceptions; iface->get_exceptions = event_get_exceptions; iface->set_summary = event_set_summary; iface->set_description = event_set_description; iface->set_location = event_set_location; iface->set_start = event_set_start; iface->set_end = event_set_end; iface->set_alarm = event_set_alarm; iface->set_recurrence = event_set_recurrence; iface->set_exceptions = event_set_exceptions; } static void jana_ecal_event_class_init (JanaEcalEventClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); /* Don't add a zero-size private, causes memory corruption issues */ /*g_type_class_add_private (klass, sizeof (JanaEcalEventPrivate));*/ object_class->get_property = jana_ecal_event_get_property; object_class->set_property = jana_ecal_event_set_property; object_class->dispose = jana_ecal_event_dispose; object_class->finalize = jana_ecal_event_finalize; } static void jana_ecal_event_init (JanaEcalEvent *self) { } /** * jana_ecal_event_new: * * Creates a new #JanaEcalEvent. * * Returns: A new #JanaEcalEvent. */ JanaEvent * jana_ecal_event_new () { ECalComponent *comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomponent_new (ICAL_VEVENT_COMPONENT)); return JANA_EVENT (g_object_new (JANA_ECAL_TYPE_EVENT, "ecalcomp", comp, NULL)); } /** * jana_ecal_event_new_from_ecalcomp: * @event: An #ECalComponent * * Creates a new #JanaEcalEvent based on the given #ECalComponent. The type of * the given #ECalComponent must be %E_CAL_COMPONENT_EVENT. See * e_cal_component_get_vtype(). * * Returns: A new #JanaEcalEvent that wraps the given #ECalComponent, cast as * a #JanaEvent. */ JanaEvent * jana_ecal_event_new_from_ecalcomp (ECalComponent *event) { return JANA_EVENT (g_object_new (JANA_ECAL_TYPE_EVENT, "ecalcomp", event, NULL)); } static JanaComponentType component_get_component_type (JanaComponent *self) { return JANA_COMPONENT_EVENT; } static gboolean component_is_fully_represented (JanaComponent *self) { gboolean result = TRUE; ECalComponent *comp; g_object_get (self, "ecalcomp", &comp, NULL); /* TODO: We actually support slightly less than ECal simple recurrence, * filter this down some more. */ if (e_cal_component_has_recurrences (comp) && (!e_cal_component_has_simple_recurrence (comp))) result = FALSE; if (e_cal_component_has_rdates (comp)) result = FALSE; /* TODO: Implement exception dates */ if (e_cal_component_has_exdates (comp)) result = FALSE; if (e_cal_component_has_exrules (comp)) result = FALSE; if (e_cal_component_has_organizer (comp)) result = FALSE; if (e_cal_component_has_attendees (comp)) result = FALSE; if (e_cal_component_has_attachments (comp)) result = FALSE; /* TODO: Implement alarms */ if (e_cal_component_has_alarms (comp)) result = FALSE; /* TODO: There are probably more parts of ECalComponent/icalcomponent * that aren't supported. Need to either add more support at the * JanaEvent level, or do more in-depth checking here. This will * catch the most important aspects at least. */ g_object_unref (comp); return result; } static gchar * event_get_summary (JanaEvent *self) { return jana_ecal_component_get_summary (JANA_ECAL_COMPONENT (self)); } static gchar * event_get_description (JanaEvent *self) { return jana_ecal_component_get_description (JANA_ECAL_COMPONENT (self)); } static gchar * event_get_location (JanaEvent *self) { return jana_ecal_component_get_location (JANA_ECAL_COMPONENT (self)); } static JanaTime * event_get_start (JanaEvent *self) { return jana_ecal_component_get_start (JANA_ECAL_COMPONENT (self)); } static JanaTime * event_get_end (JanaEvent *self) { return jana_ecal_component_get_end (JANA_ECAL_COMPONENT (self)); } static gboolean event_supports_alarm (JanaEvent *self) { /* TODO: Implement alarms */ return FALSE; } static gboolean event_has_alarm (JanaEvent *self) { /* TODO: Implement alarms */ return FALSE; } static JanaTime * event_get_alarm_time (JanaEvent *self) { /* TODO: Implement alarms */ return NULL; } static gboolean event_supports_recurrence (JanaEvent *self) { return TRUE; } static gboolean event_has_recurrence (JanaEvent *self) { ECalComponent *comp; gboolean result; g_object_get (self, "ecalcomp", &comp, NULL); result = e_cal_component_has_recurrences (comp); g_object_unref (comp); return result; } /* Following function and define copied from libecal */ /* Counts the elements in the by_xxx fields of an icalrecurrencetype */ static int count_by_xxx (short *field, int max_elements) { int i; for (i = 0; i < max_elements; i++) if (field[i] == ICAL_RECURRENCE_ARRAY_MAX) break; return i; } #define N_HAS_BY(field) (count_by_xxx (field, sizeof (field)/sizeof (field[0]))) static JanaRecurrence * event_get_recurrence (JanaEvent *self) { gint i; GSList *rrule_list; ECalComponent *comp; JanaRecurrence *recur; struct icalrecurrencetype *r; if (!event_has_recurrence (self)) return NULL; /* Fill in our own recurrence struct */ g_object_get (self, "ecalcomp", &comp, NULL); recur = jana_recurrence_new (); e_cal_component_get_rrule_list (comp, &rrule_list); r = rrule_list->data; recur->interval = r->interval; switch (r->freq) { case ICAL_DAILY_RECURRENCE : recur->type = JANA_RECURRENCE_DAILY; break; case ICAL_WEEKLY_RECURRENCE : recur->type = JANA_RECURRENCE_WEEKLY; for (i = 0; (i < 8) && (r->by_day[i] != ICAL_RECURRENCE_ARRAY_MAX); i++) { switch (icalrecurrencetype_day_day_of_week ( r->by_day[i])) { case ICAL_MONDAY_WEEKDAY : recur->week_days[0] = TRUE; break; case ICAL_TUESDAY_WEEKDAY : recur->week_days[1] = TRUE; break; case ICAL_WEDNESDAY_WEEKDAY : recur->week_days[2] = TRUE; break; case ICAL_THURSDAY_WEEKDAY : recur->week_days[3] = TRUE; break; case ICAL_FRIDAY_WEEKDAY : recur->week_days[4] = TRUE; break; case ICAL_SATURDAY_WEEKDAY : recur->week_days[5] = TRUE; break; case ICAL_SUNDAY_WEEKDAY : recur->week_days[6] = TRUE; break; default : break; } } break; case ICAL_MONTHLY_RECURRENCE : recur->type = JANA_RECURRENCE_MONTHLY; if (N_HAS_BY (r->by_month_day)) { /* We don't really support this field at all, we use * the date to determine which day it repeats on. */ recur->by_date = TRUE; } break; case ICAL_YEARLY_RECURRENCE : recur->type = JANA_RECURRENCE_YEARLY; break; default : break; } /* TODO: Also check count and calculated until time from it? */ if (!icaltime_is_null_time (r->until)) { recur->end = jana_ecal_time_new_from_icaltime (&r->until); } e_cal_component_free_recur_list (rrule_list); g_object_unref (comp); return recur; } static gboolean event_supports_exceptions (JanaEvent *self) { /* TODO: Implement exceptions */ return FALSE; } static gboolean event_has_exceptions (JanaEvent *self) { /* TODO: Implement exceptions */ return FALSE; } static GList * event_get_exceptions (JanaEvent *self) { /* TODO: Implement exceptions */ return NULL; } static void event_set_summary (JanaEvent *self, const gchar *summary) { jana_ecal_component_set_summary (JANA_ECAL_COMPONENT (self), summary); } static void event_set_description (JanaEvent *self, const gchar *description) { jana_ecal_component_set_description ( JANA_ECAL_COMPONENT (self), description); } static void event_set_location (JanaEvent *self, const gchar *location) { jana_ecal_component_set_location (JANA_ECAL_COMPONENT (self), location); } static void event_set_start (JanaEvent *self, JanaTime *start) { jana_ecal_component_set_start (JANA_ECAL_COMPONENT (self), start); } static void event_set_end (JanaEvent *self, JanaTime *end) { jana_ecal_component_set_end (JANA_ECAL_COMPONENT (self), end); } static void event_set_alarm (JanaEvent *self, JanaTime *time) { /* TODO: Implement alarms */ } static void event_set_recurrence (JanaEvent *self, const JanaRecurrence *recur) { gint i, c; ECalComponent *comp; GSList *rrule_list; struct icalrecurrencetype r; g_object_get (self, "ecalcomp", &comp, NULL); if (!recur) { /* Remove recurrence */ e_cal_component_set_rrule_list (comp, NULL); g_object_unref (comp); return; } /* Set week start to Monday */ r.week_start = ICAL_MONDAY_WEEKDAY; /* Set interval */ r.interval = recur->interval; /* Clear by_* fields */ for (i = 0; i < ICAL_BY_SECOND_SIZE; i++) r.by_second[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_MINUTE_SIZE; i++) r.by_minute[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_HOUR_SIZE; i++) r.by_hour[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_DAY_SIZE; i++) r.by_day[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_MONTHDAY_SIZE; i++) r.by_month_day[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_YEARDAY_SIZE; i++) r.by_year_day[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_WEEKNO_SIZE; i++) r.by_week_no[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_MONTH_SIZE; i++) r.by_month[i] = ICAL_RECURRENCE_ARRAY_MAX; for (i = 0; i < ICAL_BY_SETPOS_SIZE; i++) r.by_set_pos[i] = ICAL_RECURRENCE_ARRAY_MAX; /* Set type and by_* fields, where appropriate */ switch (recur->type) { case JANA_RECURRENCE_DAILY : r.freq = ICAL_DAILY_RECURRENCE; break; case JANA_RECURRENCE_WEEKLY : r.freq = ICAL_WEEKLY_RECURRENCE; for (i = 0, c = 0; i < 7; i++) { if (recur->week_days[i]) { switch (i) { case 0 : /* Monday */ r.by_day[c] = ICAL_MONDAY_WEEKDAY; break; case 1 : /* Tuesday */ r.by_day[c] = ICAL_TUESDAY_WEEKDAY; break; case 2 : /* Wednesday */ r.by_day[c] = ICAL_WEDNESDAY_WEEKDAY; break; case 3 : /* Thursday */ r.by_day[c] = ICAL_THURSDAY_WEEKDAY; break; case 4 : /* Friday */ r.by_day[c] = ICAL_FRIDAY_WEEKDAY; break; case 5 : /* Saturday */ r.by_day[c] = ICAL_SATURDAY_WEEKDAY; break; case 6 : /* Sunday */ r.by_day[c] = ICAL_SUNDAY_WEEKDAY; break; } c++; } } break; case JANA_RECURRENCE_MONTHLY : r.freq = ICAL_MONTHLY_RECURRENCE; if (recur->by_date) { JanaTime *start = jana_event_get_start (self); r.by_month_day[0] = jana_time_get_day (start); g_object_unref (start); } break; case JANA_RECURRENCE_YEARLY : r.freq = ICAL_YEARLY_RECURRENCE; break; } /* Set ending time */ r.count = 0; if (recur->end) { icaltimetype *time; if (JANA_ECAL_IS_TIME (recur->end)) { g_object_get (G_OBJECT (recur->end), "icaltime", &time, NULL); r.until = *time; } else { JanaTime *ecaltime = jana_ecal_time_new (); jana_utils_time_copy (recur->end, ecaltime); g_object_get (G_OBJECT (recur->end), "icaltime", &time, NULL); r.until = *time; g_object_unref (ecaltime); } } else { r.until = icaltime_null_time (); } /* Set the recurrence */ rrule_list = g_slist_append (NULL, &r); e_cal_component_set_rrule_list (comp, rrule_list); g_slist_free (rrule_list); g_object_unref (comp); } static void event_set_exceptions (JanaEvent *self, GList *exceptions) { /* TODO: Implement exceptions */ } jana/ChangeLog0000644000175000017500000032551411327631152013464 0ustar paulliupaulliu2009-03-20 Chris Lord * libjana-ecal/jana-ecal.h: Define HANDLE_LIBICAL_MEMORY if it isn't already defined 2009-03-19 Rob Bradford * libjana-ecal/jana-ecal-store.c (get_jana_ecal_comp): Teach the ecal store about JanaEcalTask. 2009-03-19 Rob Bradford * libjana-ecal/jana-ecal-task.c (task_get_due_date): Only get a due date if one is set. 2009-03-19 Rob Bradford * libjana/jana-utils.c (jana_utils_task_copy): * libjana/jana-utils.h: Add the jana_utils_task_copy function. 2009-03-18 Rob Bradford * libjana-ecal/jana-ecal-store-view.c (store_view_jcomp_from_ecomp): Make the JanaEcalStoreView create JanaEcalTasks for tasks when it encounters appropriate ECalComponents. 2009-03-18 Rob Bradford * libjana-ecal/jana-ecal-task.c (component_interface_init), (task_interface_init), (jana_ecal_task_class_init), (jana_ecal_task_init), (jana_ecal_task_new), (jana_ecal_task_new_from_ecalcomp), (component_get_component_type), (component_is_fully_represented), (task_get_summary), (task_get_description), (task_get_completed), (task_get_due_date), (task_get_priority), (task_set_summary), (task_set_description), (task_set_completed), (task_set_due_date), (task_set_priority): * libjana-ecal/jana-ecal-task.h: * libjana-ecal/jana-ecal.h: * Makefile.am: Implement the JanaTask interface in the ECal backend. 2009-03-18 Rob Bradford * libjana/jana-task.c (jana_task_get_summary), (jana_task_get_description), (jana_task_get_completed), (jana_task_get_due_date), (jana_task_get_priority), (jana_task_set_summary), (jana_task_set_description), (jana_task_set_completed), (jana_task_set_due_date), (jana_task_set_priority): * libjana/jana-task.h: Fill out the JanaTask interface with some function pointers for task functionality and implement functions to uses these vfuncs. 2009-03-16 Rob Bradford * libjana-ecal/jana-ecal-store.c (jana_ecal_store_get_uri): * libjana-ecal/jana-ecal-store.h: Add a jana_ecal_store_get_uri function to return the URI of the calendar behind the store. 2009-03-11 Rob Bradford * libjana-ecal/jana-ecal-utils.c (jana_ecal_utils_guess_location): Avoid unreffing the GRegex twice. 2009-03-11 Rob Bradford * libjana-ecal/jana-ecal-utils.c (jana_ecal_utils_guess_location): Remove another duplicate fclose (..) on an already closed fp. 2009-03-11 Rob Bradford * libjana-ecal/jana-ecal-utils.c: Avoid duplicate fclose (..) calls on the same fp. 2009-02-26 Rob Bradford * COPYING: * README: * libjana-*/*.[ch]: * examples/*.[ch]: * tests/*.[ch]: Relicense under LGPLv2.1 2009-02-23 Rob Bradford * libjana-ecal/jana-ecal-utils.c (jana_ecal_utils_guess_location): Loosen the regex used for extracting the location from /etc/sysconfig/clock to work with that found on Fedora. 2009-02-17 Rob Bradford * libjana/jana-utils.c (jana_utils_time_to_tm): Assign the minutes when creating the struct tm from a JanaTime. 2009-01-12 Rob Bradford * libjana-ecal/jana-ecal-store-view.c (jana_ecal_store_view_set_property), (store_view_set_range): Make jana_store_view_set_range () an atomic operation on JanaEcalStoreView. This avoids potential races when setting up the range on the ECalView. 2008-12-31 Rob Bradford * libjana-ecal/jana-ecal-component.c (component_interface_init), (component_peek_uid): * libjana/jana-component.c (jana_component_peek_uid): * libjana/jana-component.h: Add jana_component_peek_uid which returns a constant string over jana_component_get_uid which returns a newly allocated one. 2008-11-27 Chris Lord * libjana-gtk/jana-gtk-day-view.c (create_layouts): Fix buffer overflow 2008-08-18 Chris Lord * libjana-gtk/data/libjana-gtk-catalog.xml: Hide useless properties for JanaGtkEventList * libjana-gtk/jana-gtk-event-list.c (jana_gtk_event_list_class_init): Fix property names 2008-08-18 Chris Lord * libjana-gtk/jana-gtk-event-list.c (jana_gtk_event_list_class_init): Make show-headers property writable * libjana/jana-component.c (jana_component_get_type): * libjana/jana-event.c (jana_event_get_type): * libjana/jana-note.c (jana_note_get_type): * libjana/jana-store-view.c (jana_store_view_get_type): * libjana/jana-store.c (jana_store_get_type): * libjana/jana-task.c (jana_task_get_type): * libjana/jana-time.c (jana_time_get_type): Add GObject prerequisites to interfaces 2008-08-17 Chris Lord Fix up remaining crashers with Month/YearView in glade-3. All jana-gtk widgets now work correctly in glade-3, however, day/month/list views display blank * libjana-gtk/data/libjana-gtk-catalog.xml: Enable JanaGtkYearView and disable relevant properties for JanaGtkMonthView and JanaGtkYearView * libjana-gtk/jana-gtk-month-view.c (jana_gtk_month_view_get_property), (jana_gtk_month_view_expose_event), (relayout), (button_press_event_cb), (jana_gtk_month_view_class_init): Fix property getter for highlighted-time, name properties correctly and fix crashing when some properties are unset * libjana-gtk/jana-gtk-year-view.c (recount_events), (jana_gtk_year_view_get_property), (jana_gtk_year_view_set_property), (jana_gtk_year_view_class_init), (regenerate_labels), (jana_gtk_year_view_init), (jana_gtk_year_view_set_year): Fix property getter for year and highlighted-time, name properties correctly and fix property setter for year 2008-08-15 Chris Lord * libjana-gtk/data/libjana-gtk-catalog.xml: Hide some properties and remove the post-create function for JanaGtkDayView * libjana-gtk/jana-gtk-day-view.c (jana_gtk_day_view_get_property), (jana_gtk_day_view_class_init): Fix the get-property code for highlighted-time (fixes crash in glade). Note, the widget works in glade-3 but doesn't display nicely 2008-08-15 Chris Lord * libjana-gtk/data/libjana-gtk-catalog.xml: Don't disable the 'time' property on classes, hide some properties on JanaGtkWorldMap and JanaGtkRecurrence. Also add the JanaGtkWorldMap post-create function * libjana-gtk/jana-gtk-recurrence.c (jana_gtk_recurrence_class_init): Name properties correctly * libjana-gtk/jana-gtk-world-map.c (refresh_buffer), (jana_gtk_world_map_class_init), (placeholder_realize_cb), (jana_gtk_world_map_glade_add_cb), (jana_gtk_world_map_glade_remove_cb), (jana_gtk_world_map_glade_post_create): Check the buffer exists before spawning drawing thread (fixes crash), add bits from JanaGtkClock to display correctly in glade-3 2008-08-15 Chris Lord * libjana-gtk/data/libjana-gtk-catalog.xml: Update properties and post-create function for JanaGtkTreeLayout * libjana-gtk/jana-gtk-tree-layout.c (jana_gtk_tree_layout_get_property), (jana_gtk_tree_layout_set_property), (jana_gtk_tree_layout_class_init): Fix property names and types to work nicely with glade (and be correct) 2008-08-15 Chris Lord Beginnings of glade-3 integration bits - JanaGtkClock and JanaGtkDateTime work correctly, other widgets are likely to crash glade-3 * configure.ac: Add a --enable-glade switch * libjana-ecal/jana-ecal-component.c (jana_ecal_component_get_start): Fix a compiler warning * libjana-gtk/Makefile.am: Link against gladeui * libjana-gtk/data/Makefile.am: * libjana-gtk/data/libjana-gtk-catalog.xml: Add glade catalog file * libjana-gtk/jana-gtk-clock.c (jana_gtk_clock_class_init), (placeholder_realize_cb), (jana_gtk_clock_glade_add_cb), (jana_gtk_clock_glade_remove_cb), (jana_gtk_clock_glade_post_create): Add post-create function for glade that uses some hacks to display nicely in glade * libjana-gtk/jana-gtk-date-time.c (jana_gtk_date_time_set_property), (jana_gtk_date_time_constructor), (jana_gtk_date_time_class_init), (jana_gtk_date_time_glade_post_create): Add a post-create function to set the time label, so it doesn't look broken in glade 2008-07-14 Chris Lord * libjana-gtk/jana-gtk-clock.c (draw_analogue_clock), (draw_digital_clock): Fix drawing of analogue clock when height > width 2008-07-14 Chris Lord * libjana-gtk/jana-gtk-clock.c: (stop_draw_thread), (draw_analogue_face), (draw_digital_face), (idle_redraw), (draw_clock), (refresh_buffer), (jana_gtk_clock_map), (jana_gtk_clock_unmap), (jana_gtk_clock_class_init): Fix some concurrency / thread memory-access issues, still draw the clock when time == NULL 2008-07-11 Chris Lord * configure.ac: Rename gettext package from 'Dates' to 'Jana' * tests/Makefile.am: * examples/Makefile.am: Define HANDLE_LIBICAL_MEMORY to silence warnings * libjana-gtk/jana-gtk-world-map-marker-pixbuf.h: fix duplicate jana_gtk_world_map_marker_get_type typo 2008-07-02 Chris Lord * libjana/jana-utils.c: (jana_utils_event_get_instances_cb): Don't consider instances once the end range has been passed 2008-07-01 Chris Lord * libjana/jana-utils.c: (jana_utils_event_get_instances): Try not to consider instances that occur outside of the specified time range with recurring events 2008-07-01 Chris Lord * libjana-ecal/jana-ecal-component.c: (jana_ecal_component_get_start): Don't return NULL start times, instead create the earliest valid time 2008-05-30 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (jana_gtk_day_view_set_range): Free layouts before changing the range - fixes crash/leak when adjusting the range 2008-05-23 Chris Lord * libjana-ecal/jana-ecal-component.c (component_get_custom_props_list), (component_get_custom_prop): * libjana-ecal/jana-ecal-event.c: * libjana-ecal/jana-ecal-note.c: * libjana-ecal/jana-ecal-store-view.c: * libjana-ecal/jana-ecal-store.c: * libjana-ecal/jana-ecal-time.c: * libjana-ecal/jana-ecal-utils.c: Update, as per http://bugzilla.gnome.org/show_bug.cgi?id=516408 2008-02-25 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_get_size): Fix requesting too large a size when a cell width is set (we ellipsize into the available size in this case, so no need to request a size) 2008-01-16 Chris Lord * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_expose_event): Fix incorrect week numbers (Openmoko bug #1184) 2007-12-21 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-note.c: (jana_gtk_cell_renderer_note_get_property), (jana_gtk_cell_renderer_note_set_property), (jana_gtk_cell_renderer_note_finalize), (jana_gtk_cell_renderer_note_class_init), (cell_renderer_note_render), (cell_renderer_note_get_size): Add category-icon (emblems) support 2007-12-18 Chris Lord * libjana/jana-utils.c: (jana_utils_component_insert_category), (jana_utils_component_remove_category): Fix possible segfaults in category insertion/removal 2007-12-10 Chris Lord * libjana-ecal/jana-ecal-store.c: (store_get_component): Fix jana_ecal_store_get_component for journal components 2007-12-07 Chris Lord * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_component_has_category): * libjana/jana-utils.h: Add new utility function jana_utils_component_has_category 2007-12-06 Chris Lord * libjana-gtk/jana-gtk-clock.c: (jana_gtk_clock_expose_event), (draw_clock): Don't draw the clock until the entire clock is ready to draw (cosmetic issue, fixes OpenMoko bug #1037) 2007-11-19 Chris Lord * libjana-ecal/jana-ecal-store.c: (get_jana_ecal_comp): Fix/implement adding notes to a store * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (copy_component_fields), (jana_utils_event_copy), (jana_utils_note_copy): * libjana/jana-utils.h: Add new utility function jana_utils_note_copy 2007-11-14 Chris Lord * libjana-ecal/jana-ecal-store-view.c: (get_match_string): * libjana/jana-store-view.h: Allow matching on categories as well as fields 2007-11-14 Chris Lord * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: * libjana/jana-utils.h: Add utility functions to insert and remove categories from components 2007-11-14 Chris Lord * examples/jana-gtk-example-8.c: (main): Add a scrolled window around the treeview 2007-11-13 Chris Lord * libjana-ecal/jana-ecal.h: Add jana-ecal-note.h to the global include 2007-11-13 Chris Lord * libjana-ecal/jana-ecal-note.c: (note_interface_init), (jana_ecal_note_new), (note_set_creation_time): * libjana/doc/reference/libjana-sections.txt: * libjana/jana-note.c: (jana_note_set_creation_time): * libjana/jana-note.h: Allow explicit setting of creation time for JanaNote objects 2007-11-12 Chris Lord * libjana-gtk/jana-gtk-note-store.c: (note_store_added_cb), (note_store_modified_cb): Don't forget to add created/modified time to the note store 2007-11-12 Chris Lord * libjana-ecal/jana-ecal-store-view.c: (get_match_string): Fix matching queries 2007-11-12 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-note.c: (cell_renderer_note_get_size): Still set height when cell width is set 2007-11-12 Chris Lord * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_get_property), (jana_ecal_store_view_set_property), (store_view_interface_init), (jana_ecal_store_view_class_init), (jana_ecal_store_view_init), (get_match_string), (store_view_refresh_query), (store_view_add_match), (store_view_get_matches), (store_view_remove_match), (store_view_clear_matches): * libjana/doc/reference/libjana-sections.txt: * libjana/jana-store-view.c: (jana_store_view_add_match), (jana_store_view_get_matches), (jana_store_view_remove_match), (jana_store_view_clear_matches): * libjana/jana-store-view.h: Re-design/implement Jana[Ecal]StoreView to allow for multiple matching queries on one view 2007-11-12 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-note.c: (cell_renderer_note_get_size): Fit into allocated width when a cell width is set 2007-11-09 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-note.c: (cell_renderer_note_get_size): Fix size calculation 2007-11-09 Chris Lord * examples/jana-gtk-example-1.c: (main): * examples/jana-gtk-example-2.c: (main): * examples/jana-gtk-example-3.c: (main): * examples/jana-gtk-example-4.c: (main): * examples/jana-gtk-example-5.c: (main): * examples/jana-gtk-example-8.c: (main): Fix warnings due to function prototype change * libjana-gtk/jana-gtk-event-store.c: (jana_gtk_event_store_init): * libjana-gtk/jana-gtk-event-store.h: * libjana-gtk/jana-gtk-note-store.c: (jana_gtk_note_store_init): * libjana-gtk/jana-gtk-note-store.h: Change return type to GtkTreeModel, to better follow convention 2007-11-09 Chris Lord * libjana/jana-event.c: (jana_event_get_categories): Fix typo in docs 2007-11-09 Chris Lord * examples/jana-gtk-example-8.c: (main): Use JanaGtkCellRendererNote and jana_gtk_utils_treeview_resize * libjana-gtk/jana-gtk.h: * libjana-gtk/Makefile.am: Add jana-gtk-cell-renderer-note.[ch] and jana-gtk-utils.[ch] * libjana-gtk/doc/reference/libjana-gtk-docs.sgml: * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/doc/reference/libjana-gtk.types: Refresh docs * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_finalize): Unref the category-colours hash table on finalize * libjana-gtk/jana-gtk-cell-renderer-note.[ch]: Add new JanaGtkCellRendererNote * libjana-gtk/jana-gtk-utils.[ch]: Add jana-gtk utility functions - currently only contains a callback to resize cell renderers on treeview resize 2007-11-08 Chris Lord * configure.ac: * examples/Makefile.am: * libjana-gtk/Makefile.am: Link against gthread-2.0... Not sure why this error only just cropped up? * examples/jana-gtk-example-8.c: (opened_cb), (main): Add example for JanaGtkNoteStore * libjana-ecal/doc/reference/libjana-ecal-sections.txt: Update documentation * libjana-ecal/jana-ecal-component.c: (jana_ecal_component_get_start), (jana_ecal_component_get_end): Use jana_ecal_time_new_from_ecaltime * libjana-ecal/jana-ecal-note.c: (note_get_creation_time), (note_get_modified_time): Get the creation/last-modified time if dtstart/dtend are missing * libjana-ecal/jana-ecal-time.h: * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_new_from_ecaltime): Add new jana_ecal_time_new_from_ecaltime to create time objects from ECalComponentDateTime structs * libjana-gtk/jana-gtk-note-store.[ch]: * libjana-gtk/jana-gtk.h: Add new JanaGtkNoteStore * libjana-gtk/libjana-gtk.pc.in: Add gthread-2.0 to dependencies 2007-11-07 Chris Lord * libjana-ecal/jana-ecal-note.[ch]: * libjana-ecal/Makefile.am: Add JanaEcalNote, providing for journal functionality * libjana-ecal/doc/reference/libjana-ecal-docs.sgml: * libjana-ecal/doc/reference/libjana-ecal-sections.txt: * libjana-ecal/doc/reference/libjana-ecal.types: Update documentation for new functions/classes * libjana-ecal/jana-ecal-component.c: (component_interface_init), (jana_ecal_component_get_summary), (jana_ecal_component_get_description), (jana_ecal_component_get_location), (jana_ecal_component_set_summary), (jana_ecal_component_set_description), (jana_ecal_component_set_location), (jana_ecal_component_get_start), (jana_ecal_component_get_end), (jana_ecal_component_set_start), (jana_ecal_component_set_end), (component_get_categories), (component_set_categories): * libjana-ecal/jana-ecal-component.h: * libjana-ecal/jana-ecal-event.c: (event_interface_init), (event_get_summary), (event_get_description), (event_get_location), (event_get_start), (event_get_end), (event_set_summary), (event_set_description), (event_set_location), (event_set_start), (event_set_end): Move code from JanaEcalEvent to JanaEcalComponent, to make sub-classing easier * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_get_property), (jana_ecal_store_view_set_property), (store_view_interface_init), (jana_ecal_store_view_class_init), (store_view_jcomp_from_ecomp), (store_view_progress_cb), (store_view_done_cb), (store_view_refresh_query), (store_view_get_match), (store_view_set_match): Add support for JanaEcalNote and add string-matching queries * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_time_now_local): * libjana-ecal/jana-ecal-utils.h: New utility function jana_ecal_utils_time_now_local * libjana/doc/reference/libjana-sections.txt: Update documentation for new interfaces/functions * libjana/jana-component.c: (jana_component_get_categories), (jana_component_set_categories): * libjana/jana-component.h: * libjana/jana-event.c: (jana_event_get_categories), (jana_event_set_categories): * libjana/jana-event.h: Every component should have categories, move categories from JanaEvent to JanaComponent, jana_event_[gs]et_categories now just calls the JanaComponent functions * libjana/jana-store-view.c: (jana_store_view_base_init), (jana_store_view_get_match), (jana_store_view_set_match): * libjana/jana-store-view.h: Add string-matching queries 2007-11-06 Chris Lord * libjana/doc/reference/libjana-sections.txt: * libjana/jana-note.c: (jana_note_get_author), (jana_note_get_recipient), (jana_note_get_body), (jana_note_get_creation_time), (jana_note_get_modified_time), (jana_note_set_author), (jana_note_set_recipient), (jana_note_set_body): * libjana/jana-note.h: Flesh out JanaNote interface 2007-11-02 Chris Lord * examples/jana-gtk-example-6.c: (clicked_cb), (main): * examples/jana-gtk-example-7.c: (clicked_cb), (main): Update examples to use new 'clicked' signal * libjana-gtk/jana-gtk-clock.c: (jana_gtk_clock_enter_notify_event), (jana_gtk_clock_leave_notify_event), (jana_gtk_clock_button_press_event), (jana_gtk_clock_button_release_event), (jana_gtk_clock_class_init), (jana_gtk_clock_init): * libjana-gtk/jana-gtk-clock.h: * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_enter_notify_event), (jana_gtk_world_map_leave_notify_event), (jana_gtk_world_map_button_press_event), (jana_gtk_world_map_button_release_event), (jana_gtk_world_map_class_init), (jana_gtk_world_map_init): * libjana-gtk/jana-gtk-world-map.h: Add 'clicked' signals to world-map and clock widgets 2007-11-02 Chris Lord * libjana-gtk/doc/reference/libjana-gtk-sections.txt: Refresh * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_get_markers): * libjana-gtk/jana-gtk-world-map.h: Add jana_gtk_world_map_get_markers 2007-11-02 Chris Lord * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_set_location): Don't call icaltimezone_convert_time with a NULL timezone, fixes possible error in UTC -> x conversions 2007-11-02 Chris Lord * libjana-ecal/jana-ecal-time.c: (time_normalise), (time_set_day), (time_set_month), (time_set_year): Don't adjust the time too early when creating new time objects * libjana/jana-utils.c: (jana_utils_time_to_tm): Un-adjust for DST when converting to broken-down time format 2007-11-01 Chris Lord * configure.ac: * libjana-gtk/jana-gtk-world-map.c: (draw_map): * libjana/Makefile.am: * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_time_daylight_hours): * libjana/jana-utils.h: Move daylight hours calculation code outside of JanaGtkWorldMap to jana-utils 2007-11-01 Chris Lord * libjana/jana-utils.c: (number_suffix): Fix '13rd' -> '13th' 2007-11-01 Chris Lord * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location): Check if libc timezone is UTC before searching for an ecal location * libjana/jana-utils.c: (jana_utils_get_local_tzname): Don't put a '/' after timezones that don't have a 'sub-section' 2007-11-01 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_get_property), (jana_gtk_world_map_set_property), (jana_gtk_world_map_expose_event), (jana_gtk_world_map_size_allocate), (jana_gtk_world_map_class_init), (jana_gtk_world_map_set_static), (jana_gtk_world_map_get_static), (jana_gtk_world_map_set_width), (jana_gtk_world_map_get_width), (jana_gtk_world_map_set_height), (jana_gtk_world_map_get_height): * libjana-gtk/jana-gtk-world-map.h: Add a 'static' mode to render the map once at a specific size and scale the buffer to fit the allocated space 2007-11-01 Chris Lord * libjana-gtk/jana-gtk-clock.c: (jana_gtk_clock_init): Initialise threads 2007-10-31 Chris Lord * libjana-gtk/jana-gtk-clock.c: (draw_digital_face), (draw_digital_clock): Reduce the digital clock frame width slightly to better match the analogue clock 2007-10-31 Chris Lord * examples/jana-gtk-example-7.c: (button_press_event_cb): Change spacing * libjana-gtk/jana-gtk-clock.c: (stop_draw_thread), (jana_gtk_clock_dispose), (draw_analogue_face), (draw_analogue_clock), (draw_digital_face), (draw_digital_clock), (jana_gtk_clock_expose_event), (idle_redraw), (draw_clock), (refresh_buffer), (jana_gtk_clock_size_allocate), (jana_gtk_clock_map_event), (jana_gtk_clock_class_init): * libjana-gtk/jana-gtk-clock.h: Add threaded drawing * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_size_allocate): Stop the drawing thread before destroying the buffer surface 2007-10-31 Chris Lord * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location): Check /etc/localtime symlink if it exists; also verify that whatever timezone returned has a matching built-in ecal timezone 2007-10-29 Chris Lord * libjana-gtk/jana-gtk-world-map-marker-pixbuf.c: (render), (jana_gtk_world_map_marker_pixbuf_new): Don't crash when a NULL pixbuf is set - fallback to parent render 2007-10-26 Chris Lord * configure.ac: * examples/Makefile.am: * examples/data/Makefile.am: * examples/jana-gtk-example-7.c: (main): Add JanaGtkWorldMapMarkerPixbuf to example 7 * libjana-gtk/Makefile.am: * libjana-gtk/doc/reference/libjana-gtk-docs.sgml: * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/doc/reference/libjana-gtk.types: * libjana-gtk/jana-gtk-world-map-marker-pixbuf.[ch]: * libjana-gtk/jana-gtk-world-map-marker.[ch]: * libjana-gtk/jana-gtk-world-map.c: (draw_marks), (jana_gtk_world_map_expose_event), (jana_gtk_world_map_init), (jana_gtk_world_map_add_marker), (jana_gtk_world_map_remove_marker), (jana_gtk_world_map_move_marker): * libjana-gtk/jana-gtk-world-map.h: * libjana-gtk/jana-gtk.h: Tidy up and integrate map marker patch from Iain Holmes 2007-10-25 Chris Lord * libjana/doc/reference/libjana-sections.txt: Add missing JanaComponentType 2007-10-24 Chris Lord * configure.ac: Check for GConf * examples/jana-gtk-example-3.c: (clicked_cb), (main): Add button to toggle showing of day headers * libjana-ecal/Makefile.am: * libjana-ecal/doc/reference/libjana-ecal-sections.txt: * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location): * libjana-ecal/jana-ecal-utils.h: Check the Evolution timezone key when guessing location - also add defines so apps can hook onto change notifications * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/jana-gtk-event-list.c: (recalculate_headers), (jana_gtk_event_list_get_property), (jana_gtk_event_list_set_property), (jana_gtk_event_list_class_init), (style_set_cb), (jana_gtk_event_list_init), (jana_gtk_event_list_set_show_headers), (jana_gtk_event_list_get_show_headers): * libjana-gtk/jana-gtk-event-list.h: Add new property+functions to toggle the showing of day headers 2007-10-24 Chris Lord * libjana-gtk/jana-gtk-clock.c: (draw_digital_number), (draw_digital_face), (draw_digital_clock): Make the border frame a bit thinner, the numbers a bit bigger and add a seconds 'ticking' indicator to the digital clock - also tweak the background colour slightly to add contrast 2007-10-24 Chris Lord * configure.ac: Change package name to 'jana' from 'dates' 2007-10-23 Chris Lord * examples/jana-gtk-example-6.c: (button_press_event_cb), (main): Click to toggle between digital/analogue display * libjana-gtk/jana-gtk-clock.c: (jana_gtk_clock_get_property), (draw_analogue_face), (draw_analogue_clock), (draw_digital_number), (draw_digital_face), (draw_digital_clock), (jana_gtk_clock_expose_event), (refresh_buffer), (jana_gtk_clock_get_time), (jana_gtk_clock_get_digital), (jana_gtk_clock_get_show_seconds), (jana_gtk_clock_get_buffer_time), (jana_gtk_clock_get_draw_shadow): * libjana-gtk/jana-gtk-clock.h: Finish up get/set functions, make analogue hour hand take minutes into account, make sure the background is *really* cleared before drawing and implement digital clock. 2007-10-22 Chris Lord * libjana-gtk/jana-gtk-clock.c: (jana_gtk_clock_style_set), (jana_gtk_clock_class_init): * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_style_set), (jana_gtk_world_map_class_init): Redraw on style_set 2007-10-22 Chris Lord * libjana-ecal/Makefile.am: * libjana-ecal/libjana-ecal.pc.in: * libjana-gtk/Makefile.am: * libjana-gtk/libjana-gtk.pc.in: * libjana/Makefile.am: * libjana/libjana.pc.in: Configure libjana[{-ecal,-gtk}] as dynamic libraries 2007-10-22 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (idle_redraw), (draw_map): Don't send render_stop signal when rendering interrupted, call idle callback after rendering with high priority so the signal emission doesn't get blocked by other things 2007-10-21 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (idle_stop), (draw_map), (refresh_buffer), (jana_gtk_world_map_class_init): * libjana-gtk/jana-gtk-world-map.h: Don't use a radial gradient to fill the map, it was too subtle to notice anyway and takes too long on slower machines. Add render_start and render_stop signals for drawing. 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (stop_draw_thread), (draw_map), (refresh_buffer), (jana_gtk_world_map_set_time): Check the dirty flag while drawing and break out of drawing thread 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (jana_gtk_world_map_set_time): Make sure to stop drawing thread before unref'ing time object 2007-10-19 Chris Lord * libjana-ecal/libjana-ecal.pc.in: * libjana-gtk/libjana-gtk.pc.in: * libjana/libjana.pc.in: Fix linking flags 2007-10-19 Chris Lord * libjana-gtk/doc/reference/libjana-gtk-docs.sgml: * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/doc/reference/libjana-gtk.types: Refresh/update docs for JanaGtkWorldMap 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (refresh_buffer), (jana_gtk_world_map_map_event), (jana_gtk_world_map_class_init): Defer draw until the widget is mapped 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (stop_draw_thread), (jana_gtk_world_map_dispose), (idle_redraw), (draw_map), (refresh_buffer), (jana_gtk_world_map_init), (jana_gtk_world_map_set_time): Draw map in a thread 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (draw_map): Make LOD more aggressive 2007-10-19 Chris Lord * libjana-gtk/jana-gtk-world-map.c: (draw_map): Add adaptive level-of-detail 2007-10-19 Chris Lord * examples/jana-gtk-example-7.c: (set_time): Only update the world map every minute, instead of every second * libjana-gtk/jana-gtk-world-map.c: (read_vmf): Increase the allocation size 2007-10-19 Chris Lord * examples/jana-gtk-example-7.c: (main): Make clock scale with window size * libjana-gtk/jana-gtk-clock.c: (draw_analogue_face): Make sure clock hands are always visible * libjana-gtk/jana-gtk-world-map.c: (read_vmf): Don't constantly realloc when loading data 2007-10-18 Chris Lord * libjana-gtk/libjana-gtk.pc.in: Link correct library, as spotted by Iain Holmes 2007-10-18 Rob Bradford * Makefile.am: * configure.ac: * hildon/Makefile.am: * hildon/dates-main.c: (main): Start adding infrastructure for Hildon port. 2007-10-18 Chris Lord * README: Add note about landwater.vmf copyright * configure.ac: * libjana-gtk/Makefile.am: * libjana-gtk/data/Makefile.am: * libjana-gtk/data/landwater.vmf: Add data for JanaGtkWorldMap * examples/Makefile.am: * examples/jana-gtk-example-7.c: Add new example for JanaGtkWorldMap * libjana-gtk/jana-gtk-clock.c: (draw_analogue_face), (draw_analogue_clock), (jana_gtk_clock_expose_event): Fix drawing when widget isn't at position 0,0 * libjana-gtk/jana-gtk.h: * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-world-map.[ch]: Add new widget JanaGtkWorldMap that shows a world map with an optional daylight visualisation * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_time_day_of_year): * libjana/jana-utils.h: Add new utility function jana_utils_time_day_of_year 2007-10-17 Chris Lord * libjana-gtk/jana-gtk-clock.c: * libjana-gtk/jana-gtk-clock.h: Add licence header 2007-10-16 Chris Lord * examples/Makefile.am: * examples/jana-gtk-example-6.c: (set_time), (main): Add new example for JanaGtkClock * libjana-gtk/doc/reference/libjana-gtk-docs.sgml: * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/doc/reference/libjana-gtk.types: Refresh * libjana-gtk/jana-gtk.h: * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-clock.[ch]: Add new clock widget * libjana-gtk/jana-gtk-recurrence.c: (jana_gtk_recurrence_class_init): Fix typo with 'time' property 2007-10-14 Chris Lord * Makefile.am: * configure.ac: * tests/Makefile.am: * examples/Makefile.am: Add --enable-tests and --enable-examples, build and install tests and examples when these are specified * libjana-gtk/doc/reference/libjana-gtk-docs.sgml: * libjana-gtk/doc/reference/libjana-gtk-sections.txt: * libjana-gtk/doc/reference/libjana-gtk.types: Refresh documentation * libjana-gtk/jana-gtk-month-view.c: (relayout): Hide out-of-range events 2007-10-12 Chris Lord * libjana/jana-utils.c: (jana_utils_event_get_instances): Really fix weekly recurrence instance generation (was OOB array access, not off-by-one) 2007-10-12 Chris Lord * libjana/jana-utils.c: (jana_utils_event_get_instances): Fix off-by-1 error with weekly recurrence instance generation 2007-10-12 Chris Lord * libjana-ecal/jana-ecal-event.c: (event_set_recurrence): Fix crash when committing an event with recurrence set by libjana-ecal * libjana-gtk/jana-gtk.h: * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-recurrence.[ch]: Add a recurrence editing/display widget, JanaGtkRecurrence * libjana-gtk/jana-gtk-date-time.c: (create_edit_page), (jana_gtk_date_time_init), (jana_gtk_date_time_new): * libjana-gtk/jana-gtk-date-time.h: Set gtk_widget_set_no_show_all for internal widgets, don't leave setting format to the user (should be locale-dependent) * libjana/jana-event.c: (jana_recurrence_new): Make a new JanaRecurrence valid by default, update docs to reflect this * libjana/jana-utils.c: (jana_utils_recurrence_to_string), (jana_utils_recurrence_diff): Still return a recurrence string, even without a start time * openmoko/dates.h: * openmoko/dates-view.c: (clear_details), (fill_details), (edit_event), (page_shown), (edit_toggled_cb), (time_toggled_cb), (start_changed_cb), (recur_toggled_cb), (dates_create_view_page): Fix typo that meant that event was committed every time it was edited, add recurrence editing/display (still quite rough) 2007-10-10 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (create_layouts): Use jana_utils_ab_day * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_expose_event): Use jana_utils_ab_day * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_recurrence_to_string), (jana_utils_ab_day): * libjana/jana-utils.h: Add new function jana_utils_ab_day to get the first letter of the locale-correct abbreviated day name (UTF-8 friendly). 2007-10-09 Chris Lord * configure.ac: * libjana-ecal/Makefile.am: * libjana-ecal/libjana-ecal.pc.in: * libjana-gtk/Makefile.am: * libjana-gtk/libjana-gtk.pc.in: * libjana/Makefile.am: * libjana/libjana.pc.in: Configure libjana/-ecal/-gtk as static libraries instead of convenience libraries, as suggested in the autotools manual. Also install static libraries, headers and pkg-config files for easy development * libjana-gtk/jana-gtk.h: Add short section description 2007-10-09 Chris Lord * libjana-ecal/jana-ecal-event.c: (event_get_recurrence): Implement recurrence setting * libjana/jana-event.h: Remove @indefinite property of JanaRecurrence, was redundant * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_event_get_instances), (jana_utils_recurrence_to_string): * libjana/jana-utils.h: Add new function, jana_utils_recurrence_diff, that determines if two recurrences are the same * tests/test-jana-ecal-event.c: (main): Add recurrence setting/retrieval to the JanaEcalEvent test 2007-10-08 Chris Lord * examples/Makefile.am: * examples/jana-ecal-example-1.c: (display_event), (added_cb), (modified_cb), (removed_cb), (opened_cb), (main): Add a libjana-ecal example that just lists all events in a store and listens for changes * libjana-ecal/jana-ecal-event.c: (component_is_fully_represented), (event_supports_recurrence), (event_has_recurrence), (count_by_xxx), (event_get_recurrence): Add support for reading recurrence properties * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_set_property), (store_view_refresh_query): Add support for boundless queries * libjana-gtk/jana-gtk-event-store.c: (event_store_added_cb), (event_store_modified_cb): Add support for recurrence * libjana/doc/reference/libjana-sections.txt: Add missing JanaRecurrenceType * libjana/jana-event.c: (jana_recurrence_copy), (jana_recurrence_free): Don't crash when copying or freeing recurrences with no end time * libjana/jana-event.h: Amend documentation * libjana/jana-utils.h: * libjana/jana-utils.c: (jana_utils_time_diff), (jana_utils_event_get_instances_cb), (jana_utils_event_get_instances), (number_suffix), (jana_utils_recurrence_to_string): Fix typo in jana_utils_time_diff, add recurrence support to jana_utils_event_get_instances and add a new function, jana_utils_recurrence_to_string that returns human-readable text that represents a recurrence structure * openmoko/dates-view.c: (start_changed_cb), (end_changed_cb), (timezone_search_changed_cb), (timezone_combo_changed_cb): Fix warnings and adapt to an API change 2007-10-05 Chris Lord * openmoko/dates-view.c: (timezone_combo_changed_cb): Don't use an undecorated window for the timezone selection, or matchbox won't place it correctly when the keyboard pops up 2007-10-04 Chris Lord * openmoko/Makefile.am: * openmoko/dates-timezone-tile.[ch]: Add DatesTimezoneTile, an extension of TakuIconTile that displays searchable timezone information * openmoko/dates-view.c: (clear_details), (fill_details), (edit_toggled_cb), (set_location), (timezone_tile_clicked_cb), (timezone_search_changed_cb), (timezone_combo_changed_cb), (dates_create_view_page): Add extended timezone selector using libtaku 2007-10-03 Chris Lord * examples/Makefile.am: * tests/Makefile.am: Unbreak build flags 2007-10-03 Chris Lord * configure.ac: * libjana-ecal/Makefile.am: * libjana-ecal/doc/reference/Makefile.am: * libjana-gtk/Makefile.am: * libjana-gtk/doc/reference/Makefile.am: * libjana/Makefile.am: * libjana/doc/reference/Makefile.am: * openmoko/Makefile.am: Make build flags more fine-grained and build libtaku * openmoko/dates-view.c: (timezone_combo_changed_cb), (dates_create_view_page): Make the timezone combo box functional 2007-10-03 Chris Lord * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_set_location), (jana_ecal_time_get_location): Return "UTC" instead of a NULL location in case a zone isn't set, accept a NULL location to mean "UTC" and special-case NULL / "UTC" to set the UTC timezone * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location): Also make sure the offset of the local timezone is honoured when using the fallback method * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_get_property): Don't crash when trying to retrieve a selection when none is set * openmoko/dates-view.c: (clear_details), (fill_details), (edit_toggled_cb), (dates_create_view_page): * openmoko/dates.h: Add a timezone combo box (displays correctly, but can't set timezone currently) 2007-10-02 Chris Lord * libjana-ecal/doc/reference/libjana-ecal-sections.txt: * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location), (jana_ecal_utils_get_locations): * libjana-ecal/jana-ecal-utils.h: Add new function jana_ecal_utils_get_locations() and add a glib version check around use of GRegex 2007-10-02 Chris Lord * libjana-ecal/doc/reference/libjana-ecal-sections.txt: * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_guess_location): * libjana-ecal/jana-ecal-utils.h: Add new function jana_ecal_utils_guess_location() that checks common system files for the timezone location * libjana/doc/reference/libjana-sections.txt: * libjana/jana-utils.c: (jana_utils_time_now): * libjana/jana-utils.h: Add new function jana_utils_time_now() that fills in a JanaTime with the current local time * openmoko/dates-main.c: (main): Use jana_ecal_utils_guess_location() 2007-10-01 Chris Lord * openmoko/dates-view.c: (dates_create_view_page): Put the view/edit page in a MokoFingerScroll, now that text selection and holding work correctly 2007-09-30 Chris Lord * libjana-ecal/jana-ecal-component.[ch]: * libjana-ecal/jana-ecal-event.[ch]: * libjana-ecal/jana-ecal-store-view.[ch]: * libjana-ecal/jana-ecal-store.[ch]: * libjana-ecal/jana-ecal-time.[ch]: * libjana-ecal/jana-ecal-utils.c: * libjana-ecal/jana-ecal.h: 100% symbol docs coverage (40 symbols documented, 0 symbols incomplete, 0 not documented) 2007-09-29 Chris Lord * libjana-ecal/jana-ecal-store.c: (jana_ecal_store_class_init): * libjana/doc/reference/libjana-sections.txt: * libjana/jana-component.[ch]: * libjana/jana-event.[ch]: * libjana/jana-note.[ch]: * libjana/jana-store-view.[ch]: * libjana/jana-store.[ch]: * libjana/jana-task.[ch]: * libjana/jana-time.[ch]: * libjana/jana-utils.c: (jana_utils_duration_contains), (jana_utils_event_copy): * libjana/jana.h: 100% symbol docs coverage (121 symbols documented, 0 symbols incomplete, 0 not documented) 2007-09-29 Chris Lord * libjana/jana-time.c: (jana_time_get_type), (jana_time_get_offset), (jana_time_set_seconds), (jana_time_set_minutes), (jana_time_set_hours), (jana_time_set_day), (jana_time_set_month), (jana_time_set_year), (jana_time_set_isdate), (jana_time_set_tzname), (jana_time_set_offset), (jana_time_duplicate), (jana_duration_get_type), (jana_duration_new), (jana_duration_copy), (jana_duration_set_start), (jana_duration_set_end), (jana_duration_valid): * libjana/jana-time.h: Complete documentation 2007-09-29 Chris Lord * libjana/doc/reference/libjana-sections.txt: Correct section titles (use CamelCase) * libjana/jana-store-view.c: (jana_store_view_base_init), (jana_store_view_get_type), (jana_store_view_get_range), (jana_store_view_set_range): Complete documentation 2007-09-29 Chris Lord * libjana/jana-note.c: (jana_note_get_type): * libjana/jana-task.c: (jana_task_get_type): Remove unnecessary commented out code * libjana/jana-store.c: (jana_store_base_init), (jana_store_get_type): Complete documentation 2007-09-29 Chris Lord * libjana/jana-component.h: Document JanaComponentType enum * libjana/jana-event.c: (jana_recurrence_get_type), (jana_recurrence_copy), (jana_recurrence_free), (jana_exceptions_free): * libjana/jana-event.h: Complete documentation 2007-09-29 Chris Lord * libjana/doc/reference/libjana-sections.txt: Re-add ommitted jana_utils_time_to_tm * libjana/jana-utils.c: (jana_utils_time_is_leap_year), (jana_utils_time_days_in_month), (jana_utils_time_day_of_week), (jana_utils_time_week_of_year), (jana_utils_time_set_start_of_week), (jana_utils_time_set_end_of_week), (jana_utils_time_to_gdate), (jana_utils_time_to_tm), (jana_utils_strftime), (jana_utils_time_compare), (jana_utils_time_diff), (jana_utils_time_adjust), (jana_utils_duration_contains), (jana_utils_event_copy), (jana_utils_event_get_instances), (jana_utils_instance_list_free): Complete documentation 2007-09-28 Chris Lord * openmoko/dates-main.c: (main): Typo s/g_timeout_add_seconds/g_timeout_add 2007-09-28 Chris Lord * libjana-gtk/jana-gtk-event-store.c: (change_events_cb), (jana_gtk_event_store_set_offset): Don't use g_hash_table_get_keys(). 2007-09-28 Chris Lord * openmoko/dates-month.c: (year_clicked_cb): Set the dialog window hint on the year view 2007-09-28 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (relayout): Fix bug with non-24-hour events ending before 1am 2007-09-28 Chris Lord * libjana-ecal/jana-ecal-event.c: (event_get_start), (event_get_end): Set the timezone from tzid when available * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_time_now), (jana_ecal_utils_time_today): Set the timezone after retrieving the time with zone (it isn't set otherwise, despite having provided a zone for it to set) * libjana-gtk/doc/reference/libjana-gtk-sections.txt: Update * libjana-gtk/jana-gtk-event-store.c: (event_store_added_cb), (event_store_modified_cb), (jana_gtk_event_store_get_property), (jana_gtk_event_store_set_property), (jana_gtk_event_store_class_init), (jana_gtk_event_store_new_full), (jana_gtk_event_store_set_offset): * libjana-gtk/jana-gtk-event-store.h: Allow specifying an offset to use when instancing events * libjana/jana-utils.c: (jana_utils_event_get_instances): * libjana/jana-utils.h: Require an offset when instancing events * openmoko/dates-main.c: (opened_cb), (main): Use GLIB_CHECK_VERSION to determine whether to use g_timeout_add_seconds 2007-09-27 Chris Lord * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_finalize): Free highlighted time on finalize * libjana-gtk/jana-gtk-year-view.c: (recount_events), (jana_gtk_year_view_get_property), (jana_gtk_year_view_set_property), (jana_gtk_year_view_finalize), (jana_gtk_year_view_class_init), (regenerate_labels), (jana_gtk_year_view_init), (jana_gtk_year_view_new), (jana_gtk_year_view_set_year), (jana_gtk_year_view_get_year), (jana_gtk_year_view_set_selected_month), (jana_gtk_year_view_set_highlighted_time): * libjana-gtk/jana-gtk-year-view.h: Use a JanaTime to set year (so we can consider timezones) and add a function to set a highlighted time * openmoko/dates-list.c: (update_header): * openmoko/dates-month.c: (set_range), (year_clicked_cb): * openmoko/dates-week.c: (refresh_view): Use shorter window titles and highlight the current month on year view * openmoko/dates-main.c: (main): Correct some comments and use GNOME stock names for tab icons 2007-09-27 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (relayout): Consider time offset when laying out events * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_get_property), (jana_gtk_month_view_set_property), (jana_gtk_month_view_expose_event), (jana_gtk_month_view_class_init), (jana_gtk_month_view_set_highlighted_time): * libjana-gtk/jana-gtk-month-view.h: Add function to set a highlighted time * openmoko/dates-main.c: (time_update_idle): Set highlighted time on month view 2007-09-27 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (create_layouts), (time_to_cell_coords), (jana_gtk_day_view_get_property), (jana_gtk_day_view_set_property), (jana_gtk_day_view_dispose), (jana_gtk_day_view_finalize), (layout_expose_event_cb), (end_selection), (jana_gtk_day_view_class_init), (adjustment_changed_after_size_allocate_cb), (viewport_size_allocate_cb), (jana_gtk_day_view_scroll_to_time), (recalculate_cell_coords), (jana_gtk_day_view_set_range), (jana_gtk_day_view_set_selection), (jana_gtk_day_view_set_cells), (jana_gtk_day_view_set_highlighted_time), (jana_gtk_day_view_set_active_range): * libjana-gtk/jana-gtk-day-view.h: Add new functions to set an active range (times outside of the active range will be low-lighted) and a highlighted time (which will have a bold day header + a Marcus Bains line). Also fix the adjustments changing the visible area when the widget is resized and fix various time offset bugs that probably existed. * libjana/jana-utils.c: (jana_utils_time_compare), (days_between), (jana_utils_time_diff): Make jana_utils_time_diff accumulate time difference when parameters are missing. Also don't unnecessarily create a new time in jana_utils_time_compare when both times have the same offset * openmoko/dates.h: * openmoko/dates-main.c: (delete_event_cb), (time_update_idle), (main): Set the highlighted time on the week view and update every minute to get a Marcus Bains line * openmoko/dates-week.c: (refresh_view), (dates_create_week_page): Set the active time to work hours (9am - 5pm) 2007-09-26 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (layout_expose_event_cb), (start_selection), (end_selection): Store the selection cell co-ordinates and don't use jana_time functions when redrawing main grid - should speed up selections * openmoko/dates-view.c: (edit_toggled_cb): Remove bogus hidden check when editing events (fixes not saving events when switching away from view tab without first switching out of edit mode) 2007-09-26 Chris Lord * libjana*/doc/reference/tmpl/dummy.sgml: Move dummy -> dummy.sgml to fix first-time gtk-doc build 2007-09-26 Chris Lord * Makefile.am: * configure.ac: * doc/libjana-ecal/Makefile.am: * doc/libjana-ecal/libjana-ecal-docs.sgml: * doc/libjana-ecal/libjana-ecal-sections.txt: * doc/libjana-ecal/libjana-ecal.types: * doc/libjana-gtk/Makefile.am: * doc/libjana-gtk/libjana-gtk-docs.sgml: * doc/libjana-gtk/libjana-gtk-sections.txt: * doc/libjana-gtk/libjana-gtk.types: * doc/libjana/Makefile.am: * doc/libjana/libjana-docs.sgml: * doc/libjana/libjana-overrides.txt: * doc/libjana/libjana-sections.txt: * doc/libjana/libjana.types: * libjana-ecal/Makefile.am: * libjana-ecal/doc/reference/Makefile.am: * libjana-gtk/Makefile.am: * libjana-gtk/doc/reference/Makefile.am: * libjana/Makefile.am: * libjana/doc/reference/Makefile.am: Move libjana-* documentation to their respective source directories 2007-09-26 Chris Lord * doc/libjana-ecal/libjana-ecal-sections.txt: * doc/libjana-ecal/libjana-ecal.types: * doc/libjana-gtk/libjana-gtk-docs.sgml: * doc/libjana-gtk/libjana-gtk-sections.txt: * doc/libjana-gtk/libjana-gtk.types: * doc/libjana/Makefile.am: * doc/libjana/libjana-overrides.txt: * doc/libjana/libjana-sections.txt: * doc/libjana/libjana.types: * libjana/jana-utils.h: Fix some gtk-doc issues 2007-09-25 Chris Lord * configure.ac: * openmoko/Makefile.am: * openmoko/data/Makefile.am: * openmoko/data/openmoko-dates.desktop: Add .desktop file 2007-09-25 Chris Lord * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk.h: * libjana-gtk/jana-gtk-year-view.[ch]: Add new widget JanaGtkYearView * openmoko/dates-month.c: (year_selection_changed_cb), (year_clicked_cb), (dates_create_month_page): Add a year view month selector * openmoko/dates-view.c: (dates_create_view_page): Change button names for start/time toggle buttons 2007-09-24 Chris Lord * openmoko/dates-month.c: (set_range): Set month title correctly when days from the previous month are visible 2007-09-24 Chris Lord * openmoko/dates-list.c: (update_header), (page_shown), (page_hidden): * openmoko/dates-main.c: (main): * openmoko/dates-month.c: (set_range), (page_shown), (page_hidden): * openmoko/dates-utils.c: (dates_utils_title_idle_cb): * openmoko/dates-utils.h: * openmoko/dates-view.c: (page_shown), (page_hidden), (notify_visible_cb), (visibility_notify_event_cb), (unmap_cb): * openmoko/dates-week.c: (refresh_view), (page_shown), (page_hidden): * openmoko/dates.h: Set window title when changing views/ranges/editing 2007-09-24 Chris Lord * libjana-ecal/jana-ecal-utils.[ch]: Remove jana_ecal_utils_time_to_tm and jana_ecal_utils_strftime * libjana-gtk/jana-gtk-event-list.c: (recalculate_headers): * openmoko/dates-list.c: (update_header): Use jana-utils functions for printing formatted time * libjana/jana-utils.c: (jana_utils_time_to_tm), (jana_utils_strftime): * libjana/jana-utils.h: Add functions for converting JanaTime to libc broken-down time format and printing formatted time strings 2007-09-24 Chris Lord,,, * Makefile.am: Add doc subdir * libjana/jana-component.c: (jana_component_get_type), (jana_component_is_fully_represented), (jana_component_get_uid), (jana_component_supports_custom_props), (jana_component_get_custom_props_list), (jana_component_get_custom_prop), (jana_component_set_custom_prop): Add documentation 2007-09-24 Chris Lord,,, * configure.ac: * doc/libjana-ecal/Makefile.am: * doc/libjana-ecal/libjana-ecal-docs.sgml: * doc/libjana-gtk/Makefile.am: * doc/libjana-gtk/libjana-gtk-docs.sgml: Add gtkdoc framework for libjana-ecal and libjana-gtk 2007-09-23 Chris Lord,,, * configure.ac: * doc/libjana/Makefile.am: * doc/libjana/libjana-docs.sgml: Add gtkdoc framework for libjana 2007-09-21 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (jana_gtk_day_view_set_visible_func), (jana_gtk_day_view_refilter): * libjana-gtk/jana-gtk-day-view.h: * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_set_visible_func), (jana_gtk_month_view_refilter): * libjana-gtk/jana-gtk-month-view.h: Add visibility filter callback setting functions for internal layouts * libjana-gtk/jana-gtk-tree-layout.c: (tree_layout_row_changed_cb), (get_visible_cells), (jana_gtk_tree_layout_get_property), (jana_gtk_tree_layout_set_property), (jana_gtk_tree_layout_expose_event), (tree_layout_get_size), (jana_gtk_tree_layout_size_allocate), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event), (jana_gtk_tree_layout_class_init), (jana_gtk_tree_layout_init), (tree_layout_add_cell), (tree_layout_remove_cell_with_list), (jana_gtk_tree_layout_set_visible_func), (jana_gtk_tree_layout_refilter): * libjana-gtk/jana-gtk-tree-layout.h: Implement visibility filtering support * openmoko/dates-month.c: (refilter), (page_shown), (search_text_changed_cb), (search_combo_changed_cb), (dates_create_month_page): * openmoko/dates-week.c: (page_shown), (search_text_changed_cb), (search_combo_changed_cb), (dates_create_week_page): Set visibility filter and refilter when search changes * openmoko/dates-utils.c: (dates_utils_event_store_filter_cb), (dates_utils_event_list_filter_cb): * openmoko/dates-utils.h: Split dates_utils_event_store_filter_cb out of dates_utils_event_list_filter_cb so it can be used with day and month views 2007-09-21 Chris Lord * libjana/jana-utils.c: (jana_utils_time_diff), (jana_utils_time_adjust), (jana_utils_get_local_tzname): * libjana/jana-utils.h: Add function to get local tzname, add FIXME note to time_diff about accumulating diff in provided variables and only adjust time components when parameters are non-zero * openmoko/dates-view.c: (clear_details), (fill_details), (notify_visible_cb), (unmap_cb), (allday_toggled_cb), (edit_toggled_cb), (dates_create_view_page): * openmoko/dates.h: Add all-day event check-button 2007-09-20 Chris Lord * openmoko/dates-view.c: (edit_event), (set_entry_editable), (set_text_view_editable), (entry_focus_in_cb), (entry_focus_out_cb), (text_view_focus_in_cb), (text_view_focus_out_cb), (edit_toggled_cb), (dates_create_view_page): Don't mess with widget focus to set hint text 2007-09-20 Chris Lord * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_class_init), (jana_ecal_store_view_init): Set default removal timeout to zero, add FIXME note * libjana-gtk/jana-gtk-day-view.c: (relayout): Hide out-of-range all-day events * libjana/jana-utils.c: (jana_utils_duration_contains): * libjana/jana-utils.h: Add new function jana_utils_duration_contains 2007-09-20 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_render): Pick text colour depending on intensity of background 2007-09-20 Chris Lord * openmoko/dates-main.c: (repopulate_category_list), (main): Assign Tango-based unique colours per category 2007-09-20 Chris Lord * libjana-gtk/jana-gtk-date-time.c: (jana_gtk_date_time_set_property), (jana_gtk_date_time_set_editable), (jana_gtk_date_time_get_editable), (jana_gtk_date_time_get_time), (jana_gtk_date_time_set_time): * libjana-gtk/jana-gtk-day-view.c: (jana_gtk_day_view_set_property), (jana_gtk_day_view_set_range), (jana_gtk_day_view_get_range), (jana_gtk_day_view_get_selection), (jana_gtk_day_view_set_selection), (jana_gtk_day_view_set_spacing), (jana_gtk_day_view_set_cells), (jana_gtk_day_view_get_cells), (jana_gtk_day_view_get_spacing), (jana_gtk_day_view_get_visible_ratio), (jana_gtk_day_view_get_selected_event), (jana_gtk_day_view_set_selected_event): * libjana-gtk/jana-gtk-day-view.h: * libjana-gtk/jana-gtk-event-store.c: (jana_gtk_event_store_set_property), (jana_gtk_event_store_set_view), (jana_gtk_event_store_get_view): * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_set_property), (jana_gtk_month_view_set_month), (jana_gtk_month_view_get_month), (jana_gtk_month_view_set_spacing), (jana_gtk_month_view_get_spacing), (jana_gtk_month_view_set_selection), (jana_gtk_month_view_get_selection): * libjana-gtk/jana-gtk-month-view.h: Stop doing so much unnecessary property getting/setting, add various missing API for accessing commonly-used properties 2007-09-20 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (end_selection), (motion_notify_event_cb): Don't unnecessarily change/redraw the selection 2007-09-19 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_get_property), (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (cell_renderer_event_render): * libjana-gtk/jana-gtk-day-view.c: (relayout), (row_changed_cb), (row_inserted_cb): * libjana-gtk/jana-gtk-month-view.c: (row_inserted_cb): Add support for category colours * openmoko/dates-main.c: (main): * openmoko/dates-month.c: (dates_create_month_page): * openmoko/dates-week.c: (dates_create_week_page): * openmoko/dates.h: Add support for category colours (colours not yet generated) 2007-09-19 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_set_property), (get_description_layout): * libjana-gtk/jana-gtk-day-view.c: (row_inserted_cb): Don't forget to render location text 2007-09-19 Chris Lord * libjana-gtk/jana-gtk-date-time.c: (create_edit_page), (refresh), (jana_gtk_date_time_set_property): Fire changed signal when time property set, don't show time-editing widgets or print time label when time is date-only * libjana/jana-utils.c: (jana_utils_time_diff), (jana_utils_time_adjust): * libjana/jana-utils.h: Add utility functions for diffing and adjusting times * openmoko/dates-view.c: (start_changed_cb), (end_changed_cb), (dates_create_view_page): Move the end time with the start time and move the start time back when the end time is moved before the start time 2007-09-19 Chris Lord * libjana-gtk/jana-gtk-event-list.c: (size_allocate_cb): Fix continuous, unnecessary redrawing 2007-09-18 Chris Lord * configure.ac: Update libmokoui version * libjana-gtk/jana-gtk-day-view.c: (row_deleted_cb): Unselect the selected event when it gets deleted from the store * libjana-gtk/jana-gtk-event-list.c: (jana_gtk_event_list_compare): Don't crash when sorting events without summaries * openmoko/dates.h: * openmoko/dates-view.c: (clear_details), (edit_event), (set_entry_editable), (edit_toggled_cb), (dates_create_view_page): Add support for MokoHintEntry (#def'd out at the moment), add frames around the start/end times to match om-contacts 2007-09-18 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (jana_gtk_day_view_get_property), (jana_gtk_day_view_set_property), (button_press_event_cb), (jana_gtk_day_view_class_init), (compare_selection), (layout_selection_changed_cb), (layout24hr_selection_changed_cb), (jana_gtk_day_view_init), (jana_gtk_day_view_get_selected_event), (jana_gtk_day_view_set_selected_event): * libjana-gtk/jana-gtk-day-view.h: Keep a reference to the event between selections, don't fire event selection events when selection hasn't really changed and add functions to get and set selected event * openmoko/dates-week.c: (page_shown), (new_clicked_cb), (event_selected_cb): Use the time of the currently selected event when creating a new event, set the selected event when selecting an event on the view and re-set the selected event when re-focusing the page 2007-09-18 Chris Lord * libjana-gtk/jana-gtk-day-view.c: (relayout): Use the correct cell renderer when laying out 24-hour events * openmoko/dates-week.c: (dates_create_week_page): Increase inner padding on y-axis for 24-hour events 2007-09-17 Chris Lord * openmoko/dates-week.c: (page_shown), (dates_create_week_page): Set event cell renderers not to draw text 2007-09-17 Chris Lord * libjana-gtk/jana-gtk-cell-renderer-event.c: (get_description_layout): Don't crash when there isn't enough room to draw the description * libjana-gtk/jana-gtk-day-view.c: (button_press_event_cb), (jana_gtk_day_view_size_request), (jana_gtk_day_view_class_init): * libjana-gtk/jana-gtk-day-view.h: Allow shrinking when not viewing a sub-section of the set range * openmoko/dates-week.c: (event_selected_cb), (preview_box_size_allocate_cb), (preview_box_expose_event_cb), (dates_create_week_page): * openmoko/dates.h: Add an event preview pane to the week view 2007-09-17 Chris Lord * examples/jana-gtk-example-5.c: (realize_cb), (main): Scroll to 9am on realize, don't set unnecessary renderer props * libjana-gtk/jana-gtk-day-view.c: (set_alignments), (create_layouts), (jana_gtk_day_view_set_property), (layout_expose_event_cb), (layout24hr_expose_event_cb), (jana_gtk_day_view_expose_event), (relayout), (button_press_event_cb), (jana_gtk_day_view_set_scroll_adjustments), (jana_gtk_day_view_class_init), (viewport_size_allocate_cb), (layout24hr_selection_changed_cb), (cell_activated_cb), (jana_gtk_day_view_init), (row_changed_cb), (row_inserted_cb), (jana_gtk_day_view_scroll_to_cell), (jana_gtk_day_view_scroll_to_time), (jana_gtk_day_view_get_24hr_cell_renderer), (jana_gtk_day_view_set_selection): * libjana-gtk/jana-gtk-day-view.h: Add special all-day event visualisation, scroll_to_(cell|time) functions and signals for event selection/activation * openmoko/dates-week.c: (page_shown), (dates_create_week_page): Set 12-hours visible in week view, scroll to 8am when switching to the week-view tab 2007-09-17 Chris Lord,,, * libjana-gtk/jana-gtk-day-view.c: (button_press_event_cb), (button_release_event_cb), (motion_notify_event_cb): Don't redraw the whole widget when selecting cells 2007-09-15 Chris Lord,,, * libjana-gtk/jana-gtk-day-view.c: (relayout): Fix memory leak in relayout function 2007-09-14 Chris Lord,,, * libjana-gtk/jana-gtk-day-view.c: (jana_gtk_day_view_expose_event_cb), (relayout), (button_release_event_cb): Fix all-day events appearing invisible and backwards-selections being one cell too short * libjana/jana-utils.c: (jana_utils_time_compare), (jana_utils_event_get_instances): Fix silly bug comparing date-only times to normal times, don't create zero-length events in get_instances 2007-09-14 Chris Lord,,, * examples/jana-gtk-example-5.c: (main): Draw event text/detail in JanaGtkDayView example 2007-09-13 Chris Lord,,, * examples/jana-gtk-example-2.c: (main): * examples/jana-gtk-example-4.c: (main): * examples/jana-gtk-example-5.c: (main): Don't set the style-hint on the event renderer * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (cell_renderer_event_render): Set the default style hint to "button" again, also draw with GTK_SHADOW_IN when state == active * libjana-gtk/jana-gtk-day-view.c: (create_layouts), (jana_gtk_day_view_get_property), (jana_gtk_day_view_set_property), (paint_box), (jana_gtk_day_view_expose_event_cb), (jana_gtk_day_view_expose_event), (adjustment_changed_cb), (jana_gtk_day_view_set_scroll_adjustments), (marshal_VOID__OBJECT_OBJECT), (jana_gtk_day_view_class_init), (viewport_size_allocate_cb), (jana_gtk_day_view_init), (jana_gtk_day_view_set_visible_ratio), (jana_gtk_day_view_get_visible_ratio): * libjana-gtk/jana-gtk-day-view.h: Add native scrolling support, draw cells with shadows + flat boxes. Also, don't modify the style to use the base colour as bg * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_expose_event), (jana_gtk_month_view_init): Don't modify the style to use the base colour as bg, draw cells with flat box and shadow * openmoko/dates-week.c: (dates_create_week_page): Pack the week view straight into a scrolled window 2007-09-12 Chris Lord,,, * openmoko/Makefile.am: * openmoko/dates.h: * openmoko/dates-week.[ch]: * openmoko/dates-main.c: (opened_cb), (main): * openmoko/dates-utils.c: (dates_utils_update_category_bars): Add a (very preliminary) week view, using JanaGtkDayView 2007-09-12 Chris Lord,,, * libjana-gtk/jana-gtk-day-view.c: (style_set_cb), (jana_gtk_day_view_init): * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_expose_event), (style_set_cb), (jana_gtk_month_view_init): Use base instead of bg colour when drawing event boxes 2007-09-12 Chris Lord,,, * libjana-gtk/jana-gtk-day-view.c: (create_layouts), (jana_gtk_day_view_set_property), (jana_gtk_day_view_expose_event), (relayout), (start_selection), (end_selection), (button_press_event_cb), (jana_gtk_day_view_class_init), (jana_gtk_day_view_set_range), (jana_gtk_day_view_get_range), (jana_gtk_day_view_get_selection), (jana_gtk_day_view_get_spacing), (jana_gtk_day_view_get_layout): * libjana-gtk/jana-gtk-day-view.h: Finish writing property accessors, fix typo g_object_set instead of g_object_get in property accessors, fix bugs in relayout/drawing with 24-hour range 2007-09-12 Chris Lord,,, * examples/Makefile.am: * examples/jana-gtk-example-5.c: (opened_cb), (main): Add example for new JanaGtkDayView * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk.h: * libjana-gtk/jana-gtk-day-view.[ch]: Add new JanaGtkDayView widget * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_set_property), (jana_gtk_month_view_finalize), (size_request_cb), (jana_gtk_month_view_init): Override size request (fixes odd behaviour resizing), free memory on finalize and redraw when setting spacing and style hint * libjana/jana-time.c: (jana_duration_set_start), (jana_duration_set_end), (jana_duration_valid): * libjana/jana-time.h: Free old start/end when setting start/end on a JanaDuration, add new function jana_duration_valid to check if a duration specifies a positive length of time 2007-09-10 Chris Lord,,, * openmoko/dates-month.c: (search_text_changed_cb): Don't forget to refilter when search text changes in month-view 2007-09-10 Chris Lord,,, * openmoko/dates-list.c: (new_clicked_cb), (row_activated_cb): Use the currently selected date header/event to determine the starting time of a new event * openmoko/dates-month.c: (new_clicked_cb), (day_selection_changed_cb), (dates_create_month_page): Change the year-view button to a new-event button, allow new events to be created. When selecting a date on the month view that isn't in the list, clear the selection. * openmoko/dates-utils.c: (dates_utils_create_new_event), (dates_utils_event_list_selection_changed_cb), (dates_utils_event_list_get_time): * openmoko/dates-utils.h: Fix trying to unref the selected store instead of the selected event, add functions to get the time from a JanaGtkEventList and to set the currently selected event/store from a JanaGtkEventList selection * openmoko/dates-view.c: (delete_clicked_cb), (edit_toggled_cb): Switch back to the last active page after deleting in every case, except when the new event was created from the view page 2007-09-10 Chris Lord,,, * openmoko/dates-utils.h: * openmoko/dates-utils.c: (dates_utils_event_list_selection_changed_cb): * openmoko/dates-list.c: (page_shown), (selection_changed_cb): Moved selection_changed_cb to dates-utils, make sure to re-set the selected event when page is shown * openmoko/dates-month.c: (set_range), (day_selection_changed_cb), (list_selection_changed_cb), (dates_create_month_page): Allow events to be selected for viewing/editing via the list view panel 2007-09-10 Chris Lord,,, * examples/jana-gtk-example-4.c: (main): Set "button" style hint for event renderer * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_get_property), (jana_gtk_month_view_set_property), (jana_gtk_month_view_expose_event), (relayout), (button_press_event_cb), (jana_gtk_month_view_class_init), (jana_gtk_month_view_init): * libjana-gtk/jana-gtk-month-view.h: Add support for selecting a day, with selection_changed signal. Also create the internal layout with selections disabled * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_button_press_event), (tree_layout_add_cell), (jana_gtk_tree_layout_set_selection), (jana_gtk_tree_layout_get_cell), (jana_gtk_tree_layout_set_cell_sensitive): * libjana-gtk/jana-gtk-tree-layout.h: Add support for marking a cell insensitive, and functions to set the selection and get particular cells from row references * openmoko/dates-month.c: (selection_changed_cb), (dates_create_month_page): When the selected day changes, scroll to and highlight it in the event list 2007-09-10 Chris Lord,,, * openmoko/dates-utils.h: * openmoko/dates-utils.c: (dates_utils_event_list_filter_cb): * openmoko/dates-list.c: (dates_create_list_page): Move event-list filtering function to dates-utils * openmoko/dates-month.c: (page_shown), (page_hidden), (notify_visible_cb), (visibility_notify_event_cb), (unmap_cb), (search_combo_changed_cb), (view_size_allocate_cb), (dates_create_month_page): Add an event-list to the month view * openmoko/dates-view.c: (delete_clicked_cb): Switch to the last selected page after deleting a contact * openmoko/dates-main.c: (opened_cb), (switch_page_cb), (main): * openmoko/dates.h: Store last selected notebook page, keep month event list updated 2007-09-08 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init): Revert setting the default style hint to "button", unnecessary * libjana-gtk/jana-gtk-month-view.c: (jana_gtk_month_view_set_property), (jana_gtk_month_view_add_store), (jana_gtk_month_view_set_month), (jana_gtk_month_view_get_month), (jana_gtk_month_view_set_spacing), (jana_gtk_month_view_get_spacing): * libjana-gtk/jana-gtk-month-view.h: Add accessor methods for properties, make sure to connect signals after to prevent crashes during relayout due to inconsistent tree row references in JanaGtkTreeLayout * openmoko/dates-main.c: (opened_cb), (main): * openmoko/dates-month.[ch]: * openmoko/Makefile.am: Add preliminary month view page * openmoko/dates-list.c: (page_shown), (page_hidden), (notify_visible_cb), (visibility_notify_event_cb), (unmap_cb): Save the last time shown when switching away and check if it's still in range when switching back, to stop the time progressing backwards when switching to and from month view * openmoko/dates-utils.c: (dates_utils_update_category_bars): Update the month view category bar in update_category_bars * openmoko/dates.h: Store month view widget and last time shown in list/week views 2007-09-07 Chris Lord,,, * examples/Makefile.am: * examples/jana-gtk-example-4.c: Add a new example for JanaGtkMonthView * libjana-gtk/jana-gtk.h: * libjana-gtk/jana-gtk-month-view.[ch]: * libjana-gtk/Makefile.am: Add first run at new JanaGtkMonthView widget * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init): Set default style hint to "button" * libjana-gtk/jana-gtk-event-list.c: (row_deleted_cb), (insert_rows), (delete_rows), (jana_gtk_event_list_add_store), (jana_gtk_event_list_remove_store): Add all rows from a store when adding, and remove rows when removing * libjana-gtk/jana-gtk-tree-layout.c: (tree_layout_row_changed_cb), (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event), (jana_gtk_tree_layout_init): Draw cells correct, with regard to the origin of the widget allocation * libjana/jana-utils.c: (jana_utils_time_day_of_week), (jana_utils_time_week_of_year), (jana_utils_time_set_start_of_week), (jana_utils_time_set_end_of_week), (jana_utils_time_copy): * libjana/jana-utils.h: Add new utility functions, remove debugging output that got left in jana_utils_time_copy * openmoko/Makefile.am: Fix linker warnings 2007-09-05 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_get_property), (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (get_summary_layout): Add and use first-instance/last-instance properties to display something sensible when events span across multiple days or have unset start or end 2007-09-05 Chris Lord,,, * configure.ac: * libjana-ecal/jana-ecal-store.c: (e_cal_new_system_memos): Add check for e_cal_new_system_memos 2007-09-05 Chris Lord,,, * openmoko/dates-list.c: (update_header), (new_clicked_cb): Shorten the header text, use new dates_utils function to create new events * openmoko/dates.h: * openmoko/dates-main.c: (main): Store the main window in the global data structure * openmoko/dates-utils.c: (dates_utils_create_new_event): * openmoko/dates-utils.h: Add utility function to create a new event * openmoko/dates-view.c: (edit_event), (delete_clicked_cb), (edit_toggled_cb): When creating a new event, don't forget to ref the Store. Implement deletion of events. When clicking the edit button with no event selected, prompt whether to create a new event. 2007-09-04 Chris Lord,,, * libjana-ecal/jana-ecal-event.c: (event_set_categories): Check the category list exists before setting an empty category list * openmoko/dates-list.c: (new_clicked_cb): Hook up the new event button * openmoko/dates-main.c: (main): Store a pointer to the main notebook in the global data structure * openmoko/dates-view.c: (clear_details), (edit_event), (notify_visible_cb), (visibility_notify_event_cb), (unmap_cb): Commit an event when switching away from the tab, also create new events when no store is selected * openmoko/dates.h: Keep a pointer to the main notebook 2007-09-04 Chris Lord,,, * openmoko/dates-list.c: (dates_create_list_page): Don't update the category bar when creating the list page, all category bars get updated after creating the interface * openmoko/dates-main.c: (repopulate_category_list), (main): Use g_utf8_collate to sort categories and update category bars on initialisation * openmoko/dates-utils.c: (dates_utils_fill_category_bar), (dates_utils_insert_preset_categories): * openmoko/dates-utils.h: Make dates_utils_update_category_bar private and add a new function that adds the global categories to a combo box * openmoko/dates-view.c: (clear_details), (fill_details), (edit_event), (edit_toggled_cb), (entry_focus_in_cb), (entry_focus_out_cb), (combo_changed_cb), (dates_create_view_page): Implement category editing/display * openmoko/dates.h: Add category combo entry widget 2007-09-04 Chris Lord,,, * libjana-gtk/jana-gtk-date-time.c: (clear): Don't try to set invalid values when clearing * openmoko/dates-view.c: (clear_details), (fill_details), (visibility_notify_event_cb), (set_entry_editable), (set_text_view_editable), (edit_toggled_cb), (dates_create_view_page): Add 'Starts' and 'Ends' labels to times and hide widgets in view mode when they're empty. * openmoko/dates.h: Add variables for Starts/Ends labels in view/edit tab 2007-09-04 Chris Lord,,, * libjana-gtk/jana-gtk-event-list.c: (row_changed_cb): Re-filter on row changed * openmoko/dates-list.c: (visibility_notify_event_cb), (filter_cb), (search_text_changed_cb), (search_combo_changed_cb), (search_toggled_cb), (dates_create_list_page): Fix category filter and implement category search * openmoko/dates-main.c: (repopulate_category_list), (row_inserted_cb), (row_changed_cb), (row_deleted_cb), (opened_cb): Hook up row changed/deleted correctly and make a copy of the category when adding it to the category list * openmoko/dates-utils.c: (dates_utils_update_category_bar): Don't assume a GtkComboBox-text is backed by a GtkListStore (it is, but that could change?) 2007-09-04 Chris Lord,,, * libjana-gtk/jana-gtk-event-list.c: (recalculate_headers), (jana_gtk_event_list_init), (jana_gtk_event_list_add_store), (jana_gtk_event_list_remove_store), (jana_gtk_event_list_get_filter), (jana_gtk_event_list_refilter): * libjana-gtk/jana-gtk-event-list.h: Put a filter on the private model and add accessor functions. Only allow JanaGtkEventStore's to be added, due to evil hackiness, filters won't work. * openmoko/dates-list.c: (selection_changed_cb), (filter_cb), (search_text_changed_cb), (dates_create_list_page): * openmoko/dates-main.c: (repopulate_category_list), (row_inserted_cb), (row_changed_cb), (row_deleted_cb), (opened_cb), (main): Update to new method of filtering, fixes crashes but no less evil. Also add code to collect currently visible categories (disabled). * openmoko/dates-utils.c: (dates_utils_update_category_bar), (dates_utils_update_category_bars), (dates_utils_insert_preset_categories): * openmoko/dates-utils.h: Add new functions for adding categories to MokoSearchBar * openmoko/dates.h: Add variables to store event categories 2007-09-03 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_set_property): Don't check that the model in a row reference is a JanaGtkEventStore * libjana-gtk/jana-gtk-event-list.h: * libjana-gtk/jana-gtk-event-list.c: (jana_gtk_event_list_add_store), (jana_gtk_event_list_remove_store): Add GtkTreeModel's instead of JanaGtkEventStore's * openmoko/dates-list.c: (selection_changed_cb), (search_text_changed_cb), (dates_create_list_page): Set search text when searching * openmoko/dates-main.c: (delete_event_cb), (filter_cb), (opened_cb), (main): Add GtkTreeModelFilter's to the JanaGtkEventStore's, allows for searching * openmoko/dates-utils.c: (dates_utils_casefold_replace), (dates_utils_refilter): * openmoko/dates-utils.h: Add utility functions to update filter and utf8 casefold string replace * openmoko/dates.h: Add variables for storing search category/filter string 2007-08-31 Chris Lord,,, * openmoko/dates-view.c: (edit_toggled_cb), (dates_create_view_page): * openmoko/dates.h: Set wrapping on the text view and add padding/background to time editing widgets 2007-08-31 Chris Lord,,, * libjana-gtk/jana-gtk-date-time.c: (jana_gtk_date_time_get_property): Don't crash when getting time property without time set * openmoko/dates-view.c: (edit_event), (visibility_notify_event_cb), (edit_toggled_cb): Implement editing of events * openmoko/dates.h: Remove 'dirty' flag, unnecessary 2007-08-31 Chris Lord,,, * libjana-gtk/jana-gtk-date-time.c: (adjust_entry), (activate_button), (button_repeat_cb), (button_start_fast_repeat_cb), (button_start_repeat_cb), (button_pressed_cb), (button_released_cb), (insert_text_cb), (minute_entry_changed_cb), (hour_entry_changed_cb), (day_entry_changed_cb), (month_entry_changed_cb), (year_entry_changed_cb), (create_edit_page), (refresh), (clear), (jana_gtk_date_time_get_property), (jana_gtk_date_time_set_property), (jana_gtk_date_time_class_init), (jana_gtk_date_time_init): Finish basic functionality * openmoko/dates-main.c: (main): Make sure to initialise editing to FALSE * openmoko/dates-utils.c: (dates_utils_toolbutton_new), (dates_utils_toggle_toolbutton_new): Use new_from_stock instead of creating an icon with a specific size * openmoko/dates-view.c: (dates_create_view_page): Pack start/end times closely to their editing buttons 2007-08-31 Chris Lord,,, * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_strftime): Fix jana_ecal_utils_strftime * openmoko/dates-list.c: (update_header), (visibility_notify_event_cb), (back_clicked_cb), (home_clicked_cb), (forward_clicked_cb), (selection_changed_cb), (dates_create_list_page): Add a header to the list view * openmoko/dates-view.c: (edit_toggled_cb), (dates_create_view_page): Don't put 'Description' in empty descriptions after editing * openmoko/dates.h: Add an 'editing' flag 2007-08-30 Chris Lord,,, * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk.h: * libjana-gtk/jana-gtk-date-time.[ch]: Add new widget for editing JanaTime's (unfinished) * openmoko/dates-list.c: (dates_create_list_page): * openmoko/dates-main.c: (main): * openmoko/dates-view.c: (clear_details), (fill_details), (edit_toggled_cb), (toggled_cb), (dates_create_view_page): * openmoko/dates.h: Add time-editing widgets to the edit/view page (unfinished) 2007-08-30 Chris Lord,,, * libjana/jana-store.h: * libjana/jana-store-view.h: * libjana/jana-store-view.c: (jana_store_view_get_store): * libjana-ecal/jana-ecal-store-view.c: (store_view_interface_init), (jana_ecal_store_view_class_init), (jana_ecal_store_view_init), (store_view_get_store): Add accessor function to get the JanaStore from a JanaStoreView * libjana/jana-time.h: * libjana/jana-time.c: (jana_time_set_seconds), (jana_time_set_minutes), (jana_time_set_hours), (jana_time_set_day), (jana_time_set_month), (jana_time_set_year): * libjana-ecal/jana-ecal-time.c: (time_set_seconds), (time_set_minutes), (time_set_hours), (time_set_day), (time_set_month), (time_set_year): Make time setting functions use signed integers so that normalisation works as expected. * libjana-gtk/jana-gtk-event-store.c: (jana_gtk_event_store_get_store): * libjana-gtk/jana-gtk-event-store.h: Add accessor function to get the JanaStore * openmoko/Makefile.am: * openmoko/dates-view.[ch]: Add viewing/editing pane * openmoko/dates-list.c: Hook up some signals for event selection/range changing * openmoko/dates-main.c: (delete_event_cb), (startup_cb), (main): Initialise time query range times before starting * openmoko/dates-utils.h: * openmoko/dates-utils.c: (dates_utils_toggle_toolbutton_new), (dates_utils_refresh_query): Add utility functions for refreshing queries and creating toggle tool-buttons * openmoko/dates.h: Store timezone, JanaStore[View]s, widgets and an edited indicator 2007-08-28 Chris Lord,,, * Makefile.am: * configure.ac: Add --with-frontend option * openmoko/Makefile.am: * openmoko/dates-list.c: (new_clicked_cb), (back_clicked_cb), (home_clicked_cb), (forward_clicked_cb), (dates_create_list_page): * openmoko/dates-list.h: * openmoko/dates-main.c: (dates_notebook_add_page_with_icon), (delete_event_cb), (opened_cb), (startup_cb), (main): * openmoko/dates-utils.c: (dates_utils_toolbutton_new): * openmoko/dates-utils.h: * openmoko/dates.h: Add start of openmoko interface * pimlico/Makefile.am: * pimlico/dates-main.c: (delete_event_cb), (main): * pimlico/dates.h: Add skeleton for pimlico interface 2007-08-26 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_size_allocate), (select_idle_cb), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_class_init), (tree_layout_add_cell), (tree_layout_move_cell), (tree_layout_remove_cell_with_list): * libjana-gtk/jana-gtk-tree-layout.h: Add new signals "selection-changed" and "cell-activated" 2007-08-26 Chris Lord,,, * libjana-gtk/jana-gtk-event-store.c: (event_store_added_cb), (event_store_modified_cb): Specify range when getting event instances, fixes multi-day events that start or end outside of a StoreView range appearing more than they should * libjana/jana-utils.c: (jana_utils_event_copy), (jana_utils_event_get_instances): * libjana/jana-utils.h: Allow a range to be specified when getting event instances 2007-08-26 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_get_property), (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (get_description_layout), (cell_renderer_event_render), (cell_renderer_event_get_size): Do sizing in a slightly saner way, fix bug where descriptions needing ellipsizing on the first line would not get shown * libjana-gtk/jana-gtk-event-list.c: (tree_autosize_idle): Adapt to new event cell sizing * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_size_allocate): Set the fixed size on the cell where necessary * examples/jana-gtk-example-1.c: Remove hack to get correctly sized tree rows, it doesn't work anymore. Also set time to UTC instead of Europe/London. * examples/jana-gtk-example-2.c: Set time to UTC instead of Europe/London * examples/jana-gtk-example-3.c: Rename treeview -> event_list, to avoid confusion. Also set time to UTC instead of Europe/London. 2007-08-26 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_get_property), (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (cell_renderer_event_render), (cell_renderer_event_get_size): Make inner padding of events customisable, reduce default to 3 (from 6) 2007-08-26 Chris Lord,,, * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_set_property): If it's a JanaEcalTime, just duplicate instead of copying * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_set_property), (time_get_daylight), (time_get_tzname), (time_normalise), (time_get_offset), (time_set_seconds), (time_set_minutes), (time_set_hours), (time_set_day), (time_set_month), (time_set_year), (time_set_isdate), (time_set_tzname), (time_set_offset): Only normalise when it's a valid date, don't set tzname or offset when they're already equal to the value called with * libjana-gtk/jana-gtk-event-store.c: (event_store_added_cb), (event_store_modified_cb), (event_store_removed_cb), (jana_gtk_event_store_dispose), (jana_gtk_event_store_finalize), (jana_gtk_event_store_class_init), (jana_gtk_event_store_compare), (event_store_free_iter_list), (jana_gtk_event_store_init): * libjana-gtk/jana-gtk-event-store.h: Store multiple instances when an event spans across multiple days * libjana/jana-time.c: * libjana/jana-time.h: Add new boxed type JanaDuration * libjana/jana-utils.c: (jana_utils_time_copy), (jana_utils_event_copy): * libjana/jana-utils.h: Add new function to get a list of durations for all the separate instances of an event across multiple days. Also make time copying set variables in a more sensible order. 2007-08-25 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (get_description_layout): Fix and comment multiple-line ellipsis (was broken on wrapped lines that needed to be truncated to provide room for ellipsis) 2007-08-25 Chris Lord,,, * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_strftime): * libjana-ecal/jana-ecal-utils.h: Add new utility function jana_ecal_utils_strftime * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (get_summary_layout): Change time rendering style slightly and make sure to set properties to NULL before returning when a NULL row is set. * libjana-gtk/jana-gtk-event-list.c: (jana_gtk_event_list_compare), (recalculate_headers), (row_deleted_cb), (row_changed_cb), (row_inserted_cb), (jana_gtk_event_list_get_property), (jana_gtk_event_list_class_init), (style_set_cb), (jana_gtk_event_list_init): * libjana-gtk/jana-gtk-event-list.h: Fix event removal, add day headers, add properties to access cell renderers and tree columns. Also, don't show the column header by default. Day headers don't interact correctly with events spanning multiple days, this is probably better fixed at the EventStore level by splitting multi-day events into separate events with times adjusted accordingly. * libjana/jana-utils.c: (jana_utils_time_to_gdate), (jana_utils_time_compare): * libjana/jana-utils.h: Add new utility function jana_utils_time_to_gdate and fix non-date comparisons involving dates 2007-08-24 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (get_summary_layout), (get_description_layout), (cell_renderer_event_render), (cell_renderer_event_get_size): Request the correct size and add multiple-line ellipsis 2007-08-22 Chris Lord,,, * examples/jana-gtk-example-1.c: (opened_cb), (main): Simplify * examples/Makefile.am: * examples/jana-gtk-example-3.c: (opened_cb), (main): Example for JanaGtkEventList * libjana-ecal/jana-ecal-utils.c: (jana_ecal_utils_time_to_tm): * libjana-ecal/jana-ecal-utils.h: New utility function jana_ecal_utils_time_to_tm * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-event-list.[ch]: New widget JanaGtkEventList that aggregates multiple JanaGtkEventStore's * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (cell_renderer_event_render), (cell_renderer_event_get_size): Add a property to allow setting properties via a GtkTreeRowReference, don't allow drawing of resize grip when not drawing box, request zero size and don't draw when draw_box and draw_text are both FALSE, and change the default of draw_resize to FALSE. 2007-08-22 Chris Lord,,, * examples/jana-gtk-example-2.c: (animate_cb): Fix memory leak, use new utility function to get correct time for today * libjana/jana.h: * libjana/Makefile.am: * libjana-ecal/jana-ecal.h: * libjana-ecal/Makefile.am: * libjana-gtk/jana-gtk.h: * libjana-gtk/Makefile.am: Add new convenience 'include-all' headers for libjana, libjana-ecal and libjana-gtk * libjana-ecal/jana-ecal-time.c: (time_set_isdate): Zero the hours/minutes/seconds when setting isdate * libjana-ecal/jana-ecal-utils.c: * libjana-ecal/jana-ecal-utils.h: Add new utility functions for getting the time now and the time today, for a particular location * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_dispose), (get_layout), (cell_renderer_event_render), (cell_renderer_event_get_size): Simplify a little, free memory on dispose/destroy * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_finalize), (tree_layout_set_properties), (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_size_allocate): Make sure to set the properties of the cell renderer before retrieving its size 2007-08-21 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_get_size): Make sure to set x_offset and y_offset to zero * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_expose_event), (tree_layout_get_size), (jana_gtk_tree_layout_size_allocate), (tree_layout_add_cell), (tree_layout_move_cell), (jana_gtk_tree_layout_add_cell), (jana_gtk_tree_layout_move_cell): * libjana-gtk/jana-gtk-tree-layout.h: Fix issues with resizing with fill_width/height and hover 2007-08-21 Chris Lord,,, * examples/jana-gtk-example-2.c: (row_inserted_cb): Use height-for-width size allocation * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_render), (cell_renderer_event_get_size): Add support for height-for-width size allocation * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_expose_event): If width and/or height are -1, ask the cell renderer for the size 2007-08-21 Chris Lord,,, * examples/jana-gtk-example-2.c: (main): Add a note about fill_width/fill_height on JanaGtkTreeLayout * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_render): Do more safety checks to avoid critical warnings when painting * libjana-gtk/jana-gtk-tree-layout.c: (find_point_cb), (tree_layout_row_changed_cb), (jana_gtk_tree_layout_get_property), (jana_gtk_tree_layout_set_property), (jana_gtk_tree_layout_expose_event), (tree_layout_get_size), (jana_gtk_tree_layout_size_request), (jana_gtk_tree_layout_size_allocate), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event), (jana_gtk_tree_layout_class_init), (tree_layout_style_set_cb), (jana_gtk_tree_layout_init), (tree_layout_add_cell), (tree_layout_move_cell): * libjana-gtk/jana-gtk-tree-layout.h: Add fill_width and fill_height properties 2007-08-21 Chris Lord,,, * examples/jana-gtk-example-2.c: (delete_event_cb), (main): Remove animation function before quitting * libjana-gtk/jana-gtk-event-store.c: (jana_gtk_event_store_compare): Don't leak memory when sorting 2007-08-21 Chris Lord,,, * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_render): Fix rendering glitch on some themes with resize grip 2007-08-20 Chris Lord,,, * examples/jana-gtk-example-2.c: (animate_cb), (row_inserted_cb), (opened_cb), (main): Make example a lot more interesting :) * libjana-gtk/jana-gtk-tree-layout.c: (tree_layout_move_cell), (jana_gtk_tree_layout_get_selection): * libjana-gtk/jana-gtk-tree-layout.h: Add accessor functions for cells and selection, unset prelight cell after it gets moved 2007-08-20 Chris Lord,,, * examples/jana-gtk-example-1.c: * examples/jana-gtk-example-2.c: * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-event-store.c: * libjana-gtk/jana-gtk-event-store.h: * libjana-gtk/jana-gtk-events-store.c: * libjana-gtk/jana-gtk-events-store.h: Rename JanaGtkEventsStore -> JanaGtkEventStore 2007-08-20 Chris Lord,,, * examples/jana-gtk-example-2.c: (row_inserted_cb), (opened_cb), (main): Make example more interesting * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_motion_notify_event): Make rendering consistent with mouse actions 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_dispose), (jana_gtk_tree_layout_finalize): Free memory/release references on dispose/finalize 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (tree_layout_row_deleted_cb), (tree_layout_add_cell), (tree_layout_move_cell), (tree_layout_remove_cell_with_list): Request widget (re)size correctly 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event): Add cell activation, allow cells to be deselected when already selected 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (jana_gtk_tree_layout_get_property), (jana_gtk_tree_layout_set_property), (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event), (jana_gtk_tree_layout_class_init), (jana_gtk_tree_layout_init), (tree_layout_remove_cell_with_list), (jana_gtk_tree_layout_get_selection): * libjana-gtk/jana-gtk-tree-layout.h: Add support for different selection modes 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (find_point_cb), (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_button_press_event), (jana_gtk_tree_layout_motion_notify_event), (jana_gtk_tree_layout_class_init), (jana_gtk_tree_layout_init), (tree_layout_remove_cell_with_list): Allow hovering over and selection of cells 2007-08-20 Chris Lord,,, * libjana-gtk/jana-gtk-tree-layout.c: (tree_layout_clear): Fix jana_gtk_tree_layout_clear 2007-08-20 Chris Lord,,, * examples/jana-gtk-example-2.c: (row_inserted_cb), (opened_cb), (main): Change example to just show the local calendar * libjana-gtk/jana-gtk-tree-layout.c: (find_path_cb), (find_row_cb), (tree_layout_row_changed_cb), (tree_layout_row_deleted_cb), (jana_gtk_tree_layout_expose_event), (jana_gtk_tree_layout_init), (tree_layout_add_cell), (tree_layout_remove_cell_with_list), (tree_layout_remove_cell): Monitor changes on tree models and remove rows/redraw when necessary 2007-08-20 Chris Lord,,, * examples/jana-gtk-example-1.c: (opened_cb), (main): Change example to just show the local calendar * libjana-gtk/jana-gtk-events-store.c: (events_store_added_cb), (events_store_modified_cb), (events_store_removed_cb), (events_store_free_iter), (jana_gtk_events_store_init): Just use GtkTreeIter instead of GtkTreeRowReference - GtkListStore guarantees life-time. 2007-08-20 Chris Lord,,, * configure.ac: * libjana-ecal/jana-ecal-store-view.c: (store_view_objects_removed_cb): Make sure to check for ECalComponentId, fixes delete signal 2007-08-17 Chris Lord,,, * examples/Makefile.am: * examples/jana-gtk-example-2.c: (row_inserted_cb), (opened_cb), (main): Add new example for JanaGtkTreeLayout * libjana-gtk/jana-gtk-cell-renderer-event.c: (get_layout), (cell_renderer_event_render), (cell_renderer_event_get_size): Don't render outside of the allocated cell area * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-tree-layout.[ch]: Add new widget JanaGtkTreeLayout to arbitrarily place cells related to a GtkTreeModel (unfinished). 2007-08-17 Chris Lord,,, * examples/jana-gtk-example-1.c: (tree_autosize_idle), (resize_tree): Don't constantly refresh column size * libjana-gtk/jana-gtk-cell-renderer-event.c: (jana_gtk_cell_renderer_event_get_property), (jana_gtk_cell_renderer_event_set_property), (jana_gtk_cell_renderer_event_class_init), (jana_gtk_cell_renderer_event_init), (get_layout), (cell_renderer_event_render), (cell_renderer_event_get_size): Add new properties "style_hint", "draw_text" and "draw_resize" 2007-08-16 Chris Lord,,, * examples/jana-gtk-example-1.c: (opened_cb), (main): Add dynamic GtkTreeView column resizing * libjana-gtk/jana-gtk-cell-renderer-event.c: (cell_renderer_event_get_size): Don't request full width, to allow resizing 2007-08-16 Chris Lord,,, * Makefile.am: * configure.ac: * examples/Makefile.am: * examples/jana-gtk-example-1.c: (added_cb), (modified_cb), (removed_cb), (opened_cb), (main): Add examples of libjana(-ecal/-gtk) use * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-cell-renderer-event.[ch]: * libjana-gtk/jana-gtk-events-store.[ch]: Add licence blocks, a GtkCellRenderer for events (unfinished) and HAS_ALARM column to JanaGtkEventsStore 2007-08-16 Chris Lord,,, * Makefile.am: * configure.ac: * libjana-gtk/Makefile.am: * libjana-gtk/jana-gtk-events-store.[ch]: Add new libjana-gtk with a GtkTreeModel * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_get_property), (jana_ecal_store_view_set_property), (jana_ecal_store_view_class_init), (store_view_jcomp_from_ecomp), (store_view_objects_added_cb): Fix typo (adding ECalComponent instead of JanaComponent to the added list) * libjana/jana-time.[ch]: * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_set_property), (jana_ecal_time_dispose), (jana_ecal_time_finalize), (time_interface_init), (jana_ecal_time_init), (time_duplicate): Add new 'duplicate' function * libjana/jana-event.c: (jana_recurrence_get_type), (jana_recurrence_copy), (jana_recurrence_free): * libjana/jana-event.h: Make JanaRecurrence a boxed type * libjana/jana-utils.c: (jana_utils_time_is_leap_year), (jana_utils_time_days_in_month), (jana_utils_time_compare): * libjana/jana-utils.h: Add new utility functions, time_is_leap_year, time_days_in_month and time_compare 2007-08-15 Chris Lord,,, * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_class_init), (store_view_jcomp_from_ecomp), (store_view_objects_added_cb), (store_view_objects_modified_cb), (store_view_objects_removed_cb), (store_view_refresh_query): * libjana-ecal/jana-ecal-store.c: (store_interface_init): * libjana/jana-store.c: * libjana/jana-store.h: Don't assume we're storing events in a JanaEcalStoreView, remove get_component_type from JanaStore, as it may contain multiple types of component. 2007-08-15 Chris Lord,,, * libjana-ecal/jana-ecal-event.c: (jana_ecal_event_class_init): Don't add a zero-size private to the class * tests/test-jana-ecal-event.c: Include string.h 2007-08-15 Rob Bradford * libjana-ecal/Makefile.am: * libjana/Makefile.am: * tests/Makefile.am: Use libtool archives for linking. 2007-08-15 Thomas Wood * po/POTFILES.in: * autogen.sh: Added 2007-08-15 Thomas Wood * configure.ac: * libjana-ecal/Makefile.am: * libjana/Makefile.am: * tests/Makefile.am: First go at adding autotools support * libjana/jana-note.c: (jana_note_get_type): * libjana/jana-note.h: * libjana/jana-task.c: (jana_task_get_type): * libjana/jana-task.h: Correct some possible typos to fix the build 2007-08-14 Chris Lord,,, * libjana-ecal/jana-ecal-store.c: (store_interface_init), (store_get_component): * libjana/jana-store.c: (jana_store_get_component): * libjana/jana-store.h: Add a get_component function to JanaStore/JanaEcalStore that lets you retrieve a JanaComponent via uid (untested). * tests/test-jana-ecal-store-view.c: (main): Don't display the success message before success is guaranteed. 2007-08-14 Chris Lord,,, * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_set_property), (jana_ecal_store_view_dispose), (jana_ecal_store_view_finalize), (jana_ecal_store_view_init), (store_view_remove_old_cb), (store_view_objects_added_cb), (store_view_refresh_query), (store_view_start): Fix memory freeing, query updating and ECalView callbacks * libjana-ecal/jana-ecal-store.c: (store_add_component): Reset component UIDs before adding to a store (prevents uid collisions) * libjana-ecal/jana-ecal-time.c: (time_get_tzname): Return "UTC" for the tzname when no timezone is set * tests/test-jana-ecal-store-view.c: (added_cb), (modified_cb), (removed_cb), (opened_cb), (timeout_cb), (main): Add test for JanaStore/JanaStoreView 2007-08-14 Chris Lord,,, * libjana-ecal/jana-ecal-component.c: (jana_ecal_component_dispose), (component_interface_init), (component_supports_custom_props), (component_get_custom_props_list), (component_get_custom_prop), (component_set_custom_prop): * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_finalize): * libjana-ecal/jana-ecal-store.c: (jana_ecal_store_dispose): * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_dispose): * libjana/jana-component.c: (jana_component_supports_custom_props), (jana_component_get_custom_props_list), (jana_component_get_custom_prop), (jana_component_set_custom_prop), (jana_component_props_list_free): * libjana/jana-component.h: Add support for custom properties on components 2007-08-14 Chris Lord,,, * libjana-ecal/jana-ecal-component.c: (jana_ecal_component_dispose): * libjana-ecal/jana-ecal-store-view.c: (jana_ecal_store_view_dispose), (jana_ecal_store_view_finalize): * libjana-ecal/jana-ecal-store.c: (jana_ecal_store_dispose): * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_dispose): Unref objects on dispose, free memory on finalize 2007-08-13 Chris Lord,,, * libjana-ecal/jana-ecal-component.h: * libjana-ecal/jana-ecal-event.c: * libjana-ecal/jana-ecal-event.h: * libjana-ecal/jana-ecal-store-view.[ch]: * libjana-ecal/jana-ecal-store.[ch]: * libjana-ecal/jana-ecal-time.[ch]: * libjana/jana-store-view.[ch]: * libjana/jana-store.[ch]: * tests/test-jana-ecal-event.c: Add new JanaStore, JanaStoreView and implementations (allowing queries and general calendar interaction). Also, fix lots of bugs. 2007-08-10 Chris Lord,,, * libjana/jana-component.[ch]: * libjana-ecal/jana-ecal-component.[ch]: Move get_uid function to JanaComponent, implement JanaEcalComponent * libjana/jana-event.[ch]: * libjana-ecal/jana-ecal-event.c: Remove get_uid function from JanaEvent * tests/test-jana-ecal-event.c: Update compile line 2007-08-10 Chris Lord,,, * libjana-ecal/jana-ecal-event.c: Implement has_exceptions. * libjana-ecal/jana-ecal-time.[ch]: Remove new_from_time (replaced with utility function), fix up icaltimezone warnings and fix use of g_slice * libjana/jana-utils.[ch]: Add utility functions to copy times and events * libjana/jana-event.[ch]: Add has_exceptions to make API more consistent. * tests/test-jana-ecal-event.c: Update compile line 2007-08-09 Chris Lord,,, * libjana-ecal/jana-ecal-event.c: (jana_ecal_event_set_property): * libjana-ecal/jana-ecal-time.c: (jana_ecal_time_set_property), (jana_ecal_time_init): Use g_slice instead of malloc (thanks Rob Bradford) * libjana/jana-component.h: Fix typo (thanks Ross Burton) 2007-08-09 Chris Lord,,, * AUTHORS: * libjana-ecal/jana-ecal-event.c: * libjana-ecal/jana-ecal-event.h: * libjana-ecal/jana-ecal-time.c: * libjana-ecal/jana-ecal-time.h: * libjana/jana-component.c: * libjana/jana-component.h: * libjana/jana-event.c: * libjana/jana-event.h: * libjana/jana-note.c: * libjana/jana-note.h: * libjana/jana-task.c: * libjana/jana-task.h: * libjana/jana-time.c: * libjana/jana-time.h: * tests/lstz.c: * tests/test-jana-ecal-event.c: * tests/test-jana-ecal-time-2.c: * tests/test-jana-ecal-time.c: Initial check-in jana/README0000644000175000017500000000100711327631152012556 0ustar paulliupaulliulibjana - An interface library for time-related personal information management related data libjana-ecal - An implementation of the above using evolution-data-server libjana-gtk - A set of GTK widgets to use with libjana libjana, libjana-ecal and libjana-gtk are released under licensed under the terms of LPGLv2.1 Note; the data file 'landwater.vmf' distributed as part of libjana-gtk was originally from the application, 'sunclock', released under GPLv2 and copyright John Mackin, jana/AUTHORS0000644000175000017500000000004311327631152012745 0ustar paulliupaulliuChris Lord jana/tests/0000755000175000017500000000000011327631152013042 5ustar paulliupaulliujana/tests/test-jana-ecal-time.c0000644000175000017500000000535411327631152016741 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include /* To build: * gcc -o test-jana-ecal-time test-jana-ecal-time.c ../libjana/jana-time.c ../libjana-ecal/jana-ecal-time.c `pkg-config --cflags --libs glib-2.0 libecal-1.2 gobject-2.0` -I../ -g */ /* Test if DST auto-adjust works: * This test creates a time object for 2:00 1/1/2007, GMT/BST and changes the * month to July. If all goes well, the time should be adjusted forward by * an hour and it should be in daylight savings. * Returns 0 on success and 1 on error. */ int main (int argc, char **argv) { gint error = 0; JanaTime *jtime; icaltimetype itime; icaltimezone *zone = icaltimezone_get_builtin_timezone ( "Europe/London"); /* Test DST conversions */ itime = icaltime_null_time (); itime.second = 0; itime.minute = 0; itime.hour = 2; itime.day = 1; itime.month = 1; itime.year = 2007; itime = icaltime_convert_to_zone (itime, zone); g_type_init (); jtime = jana_ecal_time_new_from_icaltime (&itime); /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : ""); g_debug ("Setting time forward to BST");*/ jana_time_set_month (jtime, 7); if ((jana_time_get_hours (jtime) != 3) || (!jana_time_get_daylight (jtime))) error = 1; /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : "");*/ g_object_unref (jtime); if (error) g_warning ("Error (%d)", error); else g_message ("Success"); return error; } jana/tests/test-jana-ecal-store-view.c0000644000175000017500000001642711327631152020112 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* To build: * gcc -o test-jana-ecal-store-view test-jana-ecal-store-view.c ../libjana/jana-utils.c ../libjana/jana-event.c ../libjana/jana-component.c ../libjana/jana-time.c ../libjana/jana-store.c ../libjana/jana-store-view.c ../libjana-ecal/jana-ecal-component.c ../libjana-ecal/jana-ecal-event.c ../libjana-ecal/jana-ecal-store.c ../libjana-ecal/jana-ecal-store-view.c ../libjana-ecal/jana-ecal-time.c `pkg-config --cflags --libs glib-2.0 libecal-1.2 gobject-2.0` -I../ -g -Wall -DHAVE_CID_TYPE */ /* Test if basic functions work for JanaEcalStore and JanaEcalStoreView: * Open up the system calendar and add three events on differing dates. Then * open a view on this calendar, initially narrowed to see just one date, then * widen to view all events. Finally, close and delete the calendar. * * Test runs for 10 seconds, or until it is successful, whichever occurs * first. If the test does not complete within 10 seconds, it will count as a * failure, however, it may not necessarily have failed. This test should * really never take more than a couple of seconds, however. * * Note that this test can pass when really it should fail... Should check * event UIDs to verify results properly. * * Returns 0 on success, 1 on libjana error and 2 on error removing calendar. */ static GMainLoop *main_loop; static int error_code; static gboolean first_run = TRUE; static gboolean add_success = FALSE; static JanaTime *range_start, *range_end; static JanaStoreView *store_view; static void added_cb (JanaStoreView *store_view, GList *components, gpointer user_data) { guint length = g_list_length (components); if ((!first_run) && (length == 2)) add_success = TRUE; for (; components; components = components->next) { /*GList *p, *props; JanaEvent *event = JANA_EVENT (components->data); props = jana_component_get_custom_props_list ( JANA_COMPONENT (event)); for (p = props; p; p = p->next) { gchar **prop_pair = (gchar **)p->data; g_debug ("%s = %s", prop_pair[0], prop_pair[1]); } jana_component_props_list_free (props);*/ } if (first_run && (length == 1)) { /* Successful, widen the view */ first_run = FALSE; jana_time_set_day (range_end, jana_time_get_day (range_end) + 2); jana_time_set_day (range_start, jana_time_get_day (range_start) - 2); jana_store_view_set_range (store_view, range_start, range_end); } } static void modified_cb (JanaStoreView *store_view, GList *components, gpointer user_data) { guint length = g_list_length (components); if ((!first_run) && (length == 1) && (add_success)) { error_code = 0; g_main_loop_quit (main_loop); } for (; components; components = components->next) { JanaEvent *event = JANA_EVENT (components->data); gchar *summary = jana_event_get_summary (event); g_free (summary); } } static void removed_cb (JanaStoreView *store_view, GList *uids, gpointer user_data) { for (; uids; uids = uids->next) { } } static void opened_cb (JanaStore *store, gpointer user_data) { JanaEvent *event; icaltimetype ical_time; const icaltimezone *zone; JanaTime *start, *end; event = jana_ecal_event_new (); jana_event_set_summary (event, "libjana event 1"); jana_event_set_description (event, "A description"); jana_event_set_location (event, "A location"); zone = (const icaltimezone *)icaltimezone_get_builtin_timezone ( "Europe/London"); ical_time = icaltime_current_time_with_zone (zone); ical_time.zone = zone; range_start = jana_ecal_time_new_from_icaltime (&ical_time); range_end = jana_ecal_time_new_from_icaltime (&ical_time); start = jana_ecal_time_new_from_icaltime (&ical_time); end = jana_ecal_time_new_from_icaltime (&ical_time); jana_time_set_hours (end, jana_time_get_hours (end) + 1); jana_event_set_start (event, start); jana_event_set_end (event, end); jana_time_set_day (range_end, jana_time_get_day (range_end) + 1); jana_time_set_day (range_start, jana_time_get_day (range_start) - 1); store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); g_signal_connect (G_OBJECT (store_view), "added", G_CALLBACK (added_cb), NULL); g_signal_connect (G_OBJECT (store_view), "modified", G_CALLBACK (modified_cb), NULL); g_signal_connect (G_OBJECT (store_view), "removed", G_CALLBACK (removed_cb), NULL); jana_store_view_start (store_view); jana_store_add_component (store, JANA_COMPONENT (event)); jana_event_set_summary (event, "libjana event 2"); jana_time_set_day (start, jana_time_get_day (start) - 2); jana_time_set_day (end, jana_time_get_day (end) - 2); jana_event_set_start (event, start); jana_event_set_end (event, end); jana_store_add_component (store, JANA_COMPONENT (event)); jana_event_set_summary (event, "libjana event 3"); jana_time_set_day (start, jana_time_get_day (start) + 4); jana_time_set_day (end, jana_time_get_day (end) + 4); jana_event_set_start (event, start); jana_event_set_end (event, end); jana_store_add_component (store, JANA_COMPONENT (event)); g_object_unref (event); g_object_unref (start); g_object_unref (end); } static gboolean timeout_cb (gpointer user_data) { g_main_loop_quit (main_loop); return FALSE; } int main (int argc, char **argv) { JanaStore *store; gchar *uri; ECal *ecal; GError *error = NULL; error_code = 1; g_type_init (); uri = g_strdup_printf ("file://%s%slibjana-test", g_get_tmp_dir (), G_DIR_SEPARATOR_S); store = jana_ecal_store_new_from_uri (uri, JANA_COMPONENT_EVENT); g_free (uri); g_signal_connect (G_OBJECT (store), "opened", G_CALLBACK (opened_cb), NULL); jana_store_open (store); g_object_get (store, "ecal", &ecal, NULL); g_timeout_add (10000, (GSourceFunc)timeout_cb, NULL); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); if (!e_cal_remove (ecal, &error)) { g_warning ("Error removing calendar: %s", error->message); g_error_free (error); error_code = 2; } if (error_code != 0) g_warning ("Error"); else g_message ("Success"); g_object_unref (range_start); g_object_unref (range_end); g_object_unref (store_view); g_object_unref (store); return error_code; } jana/tests/Makefile.am0000644000175000017500000000142711327631152015102 0ustar paulliupaulliu localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" $(ECAL_CFLAGS) -Wall -DHANDLE_LIBICAL_MEMORY AM_LDFLAGS = $(ECAL_LIBS) bin_PROGRAMS = jana-ecal-event jana-ecal-store-view jana-ecal-time-2 jana-ecal-time jana_ecal_event_SOURCES = test-jana-ecal-event.c jana_ecal_event_LDADD = ../libjana/libjana.la ../libjana-ecal/libjana-ecal.la jana_ecal_store_view_SOURCES = test-jana-ecal-store-view.c jana_ecal_store_view_LDADD = ../libjana/libjana.la ../libjana-ecal/libjana-ecal.la jana_ecal_time_2_SOURCES = test-jana-ecal-time-2.c jana_ecal_time_2_LDADD = ../libjana/libjana.la ../libjana-ecal/libjana-ecal.la jana_ecal_time_SOURCES = test-jana-ecal-time.c jana_ecal_time_LDADD = ../libjana/libjana.la ../libjana-ecal/libjana-ecal.la jana/tests/lstz.c0000644000175000017500000000303011327631152014176 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include /* List ical time-zones. Compile with: * gcc -o lstz lstz.c `pkg-config --cflags --libs glib-2.0 libecal-1.2` -Wall */ int main (int argc, char **argv) { gint i; icaltimetype today = icaltime_today (); icalarray *builtin = icaltimezone_get_builtin_timezones (); for (i = 0; i < builtin->num_elements; i++) { icaltimezone *zone = (icaltimezone *)icalarray_element_at ( builtin, i); gchar *zone_tz; gdouble offset = ((gdouble)icaltimezone_get_utc_offset ( zone, &today, NULL)/60.0)/60.0; zone_tz = icaltimezone_get_tznames (zone); g_print ("%s (%s, +%lf)\n", icaltimezone_get_display_name (zone), icaltimezone_get_tznames (zone), offset); } return 0; } jana/tests/test-jana-ecal-event.c0000644000175000017500000001107411327631152017120 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include /* Test if basic event functions work for JanaEcalEvent: * Create a new event, set the summary, description, start, end and categories, * then read them back to verify they were set correctly. * Returns 0 on success and 1 on error. */ int main (int argc, char **argv) { int error_code = 0; gchar *event_summary, *event_description, *event_location; const gchar *summary = "Event summary"; const gchar *description = "Event description"; const gchar *location = "Event location"; JanaEvent *event; JanaTime *start, *end; JanaRecurrence *recur, *recur_n; g_type_init (); event = jana_ecal_event_new (); jana_event_set_summary (event, summary); jana_event_set_description (event, description); jana_event_set_location (event, location); start = jana_ecal_time_new (); jana_time_set_seconds (start, 0); jana_time_set_minutes (start, 0); jana_time_set_hours (start, 0); jana_time_set_day (start, 1); jana_time_set_month (start, 1); jana_time_set_year (start, 2007); /*jana_time_set_tzname (start, "GMT/BST");*/ jana_ecal_time_set_location (JANA_ECAL_TIME (start), "Europe/London"); jana_event_set_start (event, start); g_object_unref (start); end = jana_ecal_time_new (); jana_time_set_seconds (end, 0); jana_time_set_minutes (end, 0); jana_time_set_hours (end, 2); jana_time_set_day (end, 1); jana_time_set_month (end, 1); jana_time_set_year (end, 2007); /*jana_time_set_tzname (start, "GMT/BST");*/ jana_ecal_time_set_location (JANA_ECAL_TIME (end), "Europe/London"); jana_event_set_end (event, end); jana_time_set_year (end, jana_time_get_year (end) + 1); recur = jana_recurrence_new (); recur->type = JANA_RECURRENCE_WEEKLY; recur->interval = 2; recur->week_days[1] = TRUE; recur->week_days[6] = TRUE; recur->end = end; jana_event_set_recurrence (event, recur); /* Read back the values, check they're correct */ start = jana_event_get_start (event); end = jana_event_get_end (event); event_summary = jana_event_get_summary (event); event_description = jana_event_get_description (event); event_location = jana_event_get_location (event); recur_n = jana_event_get_recurrence (event); /*g_debug ("\n%s\n%s\n%s\n%02d/%02d/%04d %02d:%02d:%02d %s\n" "%02d/%02d/%04d %02d:%02d:%02d %s", event_summary, event_description, event_location, jana_time_get_day (start), jana_time_get_month (start), jana_time_get_year (start), jana_time_get_hours (start), jana_time_get_minutes (start), jana_time_get_seconds (start), jana_time_get_tzname (start), jana_time_get_day (end), jana_time_get_month (end), jana_time_get_year (end), jana_time_get_hours (end), jana_time_get_minutes (end), jana_time_get_seconds (end), jana_time_get_tzname (end));*/ if ((strcmp (summary, event_summary) != 0) || (strcmp (description, event_description) != 0) || (strcmp (location, event_location) != 0) || (jana_time_get_seconds (start) != 0) || (jana_time_get_minutes (start) != 0) || (jana_time_get_hours (start) != 0) || (jana_time_get_day (start) != 1) || (jana_time_get_month (start) != 1) || (jana_time_get_year (start) != 2007) || (jana_time_get_seconds (end) != 0) || (jana_time_get_minutes (end) != 0) || (jana_time_get_hours (end) != 2) || (jana_time_get_day (end) != 1) || (jana_time_get_month (end) != 1) || (jana_time_get_year (end) != 2007) || (jana_utils_recurrence_diff (recur, recur_n))) { g_warning ("Error"); error_code = 1; } g_free (event_summary); g_free (event_description); g_free (event_location); g_object_unref (start); g_object_unref (end); g_object_unref (event); if (error_code == 0) g_message ("Success"); return error_code; } jana/tests/test-jana-ecal-time-2.c0000644000175000017500000000534011327631152017073 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include /* To build: * gcc -o test-jana-ecal-time-2 test-jana-ecal-time-2.c ../libjana/jana-time.c ../libjana-ecal/jana-ecal-time.c `pkg-config --cflags --libs glib-2.0 libecal-1.2 gobject-2.0` -I../ -g */ /* Test if DST+Zone auto-adjust works: * This test creates a time object for 2:00 1/1/2007, GMT/BST (+1) and changes * the timezone to FJT (+12). If all goes well, the time should be adjusted * forward by 11 hours. * Returns 0 on success and 1 on error. */ int main (int argc, char **argv) { gint error = 0; JanaTime *jtime; icaltimetype itime; icaltimezone *zone = icaltimezone_get_builtin_timezone ( "Europe/London"); /* Test DST conversions */ itime = icaltime_null_time (); itime.second = 0; itime.minute = 0; itime.hour = 2; itime.day = 1; itime.month = 7; itime.year = 2007; itime = icaltime_convert_to_zone (itime, zone); g_type_init (); jtime = jana_ecal_time_new_from_icaltime (&itime); /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : ""); g_debug ("Setting time forward to FJT");*/ jana_time_set_tzname (jtime, "FJT"); if ((jana_time_get_hours (jtime) != 13) || (jana_time_get_daylight (jtime))) error = 1; /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : "");*/ g_object_unref (jtime); if (error) g_warning ("Error (%d)", error); else g_message ("Success"); return error; } jana/examples/0000755000175000017500000000000011327631152013516 5ustar paulliupaulliujana/examples/jana-gtk-example-1.c0000644000175000017500000000551411327631152017152 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static void opened_cb (JanaStore *store, JanaGtkEventStore *event_store) { JanaTime *range_start, *range_end; range_start = jana_ecal_utils_time_today ("UTC"); range_end = jana_time_duplicate (range_start); jana_time_set_day (range_end, jana_time_get_day (range_end) + 5); jana_time_set_day (range_start, jana_time_get_day (range_start) - 5); store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); jana_gtk_event_store_set_view (event_store, store_view); jana_store_view_start (store_view); g_object_unref (range_start); g_object_unref (range_end); } int main (int argc, char **argv) { JanaStore *store; GtkTreeModel *event_store; GtkWidget *window, *treeview; GtkCellRenderer *renderer; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); event_store = jana_gtk_event_store_new (); treeview = gtk_tree_view_new_with_model (event_store); renderer = jana_gtk_cell_renderer_event_new (); g_object_set (renderer, "draw_time", TRUE, "draw_box", FALSE, NULL); gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (treeview), -1, "Events", renderer, "uid", JANA_GTK_EVENT_STORE_COL_UID, "summary", JANA_GTK_EVENT_STORE_COL_SUMMARY, "description", JANA_GTK_EVENT_STORE_COL_DESCRIPTION, "start", JANA_GTK_EVENT_STORE_COL_START, "end", JANA_GTK_EVENT_STORE_COL_END, NULL); gtk_container_add (GTK_CONTAINER (window), treeview); gtk_window_set_default_size (GTK_WINDOW (window), 300, 400); g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all (window); g_signal_connect (G_OBJECT (store), "opened", G_CALLBACK (opened_cb), event_store); jana_store_open (store); gtk_main (); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/jana-gtk-example-6.c0000644000175000017500000000412311327631152017152 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include static gchar *location; static gboolean set_time (JanaGtkClock *clock) { JanaTime *time; time = jana_ecal_utils_time_now (location); jana_gtk_clock_set_time (JANA_GTK_CLOCK (clock), time); g_object_unref (time); return TRUE; } static void clicked_cb (JanaGtkClock *clock, GdkEventButton *event) { jana_gtk_clock_set_digital (clock, !jana_gtk_clock_get_digital (clock)); } int main (int argc, char **argv) { guint id; GtkWidget *window, *clock; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); clock = jana_gtk_clock_new (); location = jana_ecal_utils_guess_location (); jana_gtk_clock_set_show_seconds (JANA_GTK_CLOCK (clock), TRUE); jana_gtk_clock_set_draw_shadow (JANA_GTK_CLOCK (clock), TRUE); gtk_container_add (GTK_CONTAINER (window), clock); gtk_window_set_default_size (GTK_WINDOW (window), 480, 480); gtk_widget_show_all (window); g_signal_connect (clock, "clicked", G_CALLBACK (clicked_cb), NULL); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); set_time (JANA_GTK_CLOCK (clock)); id = g_timeout_add (1000, (GSourceFunc)set_time, clock); gtk_main (); g_source_remove (id); g_free (location); return 0; } jana/examples/jana-gtk-example-5.c0000644000175000017500000000646511327631152017164 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static JanaTime *range_start, *range_end; static void opened_cb (JanaStore *store, JanaGtkEventStore *event_store) { store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); jana_gtk_event_store_set_view (event_store, store_view); jana_store_view_start (store_view); } static void realize_cb (GtkWidget *widget, gpointer user_data) { /* Scroll to 9am */ jana_gtk_day_view_scroll_to_cell (JANA_GTK_DAY_VIEW (widget), 0, 3); } int main (int argc, char **argv) { JanaStore *store; JanaDuration *duration; GtkTreeModel *event_store; GtkWidget *window, *week_view, *scroll; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); event_store = jana_gtk_event_store_new (); range_start = jana_ecal_utils_time_today ("UTC"); jana_utils_time_set_start_of_week (range_start); jana_time_set_isdate (range_start, TRUE); range_end = jana_time_duplicate (range_start); jana_time_set_day (range_end, jana_time_get_day (range_end) + 7); duration = jana_duration_new (range_start, range_end); jana_time_set_isdate (duration->start, FALSE); jana_time_set_hours (duration->start, 6); jana_time_set_isdate (duration->end, FALSE); jana_time_set_hours (duration->end, 18); scroll = gtk_scrolled_window_new (NULL, NULL); week_view = jana_gtk_day_view_new (duration, 12); jana_duration_free (duration); /* Set 5 days and 8 hours visible */ jana_gtk_day_view_set_visible_ratio (JANA_GTK_DAY_VIEW (week_view), 5.0/7.0, 2.0/3.0); jana_utils_time_set_start_of_week (range_start); jana_utils_time_set_end_of_week (range_end); gtk_container_add (GTK_CONTAINER (window), scroll); gtk_container_add (GTK_CONTAINER (scroll), week_view); gtk_window_set_default_size (GTK_WINDOW (window), 512, 384); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (week_view, "realize", G_CALLBACK (realize_cb), NULL); gtk_widget_show_all (window); g_signal_connect (store, "opened", G_CALLBACK (opened_cb), event_store); jana_gtk_day_view_add_store (JANA_GTK_DAY_VIEW (week_view), JANA_GTK_EVENT_STORE (event_store)); jana_store_open (store); gtk_main (); g_object_unref (range_start); g_object_unref (range_end); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/jana-gtk-example-3.c0000644000175000017500000000617211327631152017155 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static void clicked_cb (GtkButton *button, JanaGtkEventList *event_list) { jana_gtk_event_list_set_show_headers (event_list, !jana_gtk_event_list_get_show_headers (event_list)); } static void opened_cb (JanaStore *store, JanaGtkEventStore *event_store) { JanaTime *range_start, *range_end; range_start = jana_ecal_utils_time_today ("UTC"); range_end = jana_time_duplicate (range_start); jana_time_set_day (range_end, jana_time_get_day (range_end) + 5); jana_time_set_day (range_start, jana_time_get_day (range_start) - 5); store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); jana_gtk_event_store_set_view (event_store, store_view); jana_store_view_start (store_view); g_object_unref (range_start); g_object_unref (range_end); } int main (int argc, char **argv) { JanaStore *store; GtkTreeModel *event_store; GtkWidget *window, *event_list, *scroll, *vbox, *button; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); event_store = jana_gtk_event_store_new (); event_list = jana_gtk_event_list_new (); scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scroll), event_list); vbox = gtk_vbox_new (FALSE, 0); button = gtk_button_new_with_label ("Toggle headers"); g_signal_connect (button, "clicked", G_CALLBACK (clicked_cb), event_list); gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); gtk_window_set_default_size (GTK_WINDOW (window), 300, 400); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all (window); g_signal_connect (store, "opened", G_CALLBACK (opened_cb), event_store); jana_gtk_event_list_add_store (JANA_GTK_EVENT_LIST (event_list), JANA_GTK_EVENT_STORE (event_store)); jana_store_open (store); gtk_main (); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/Makefile.am0000644000175000017500000000373611327631152015563 0ustar paulliupaulliu SUBDIRS=data localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" $(ECAL_CFLAGS) $(GTK_CFLAGS) $(GTHREAD_CFLAGS) -Wall -DHANDLE_LIBICAL_MEMORY AM_LDFLAGS = $(ECAL_LIBS) $(GTK_LIBS) $(GTHREAD_LIBS) bin_PROGRAMS = jana-gtk-example-1 jana-gtk-example-2 jana-gtk-example-3 \ jana-gtk-example-4 jana-gtk-example-5 jana-gtk-example-6 \ jana-gtk-example-7 jana-gtk-example-8 jana-ecal-example-1 jana_gtk_example_1_SOURCES = jana-gtk-example-1.c jana_gtk_example_1_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_2_SOURCES = jana-gtk-example-2.c jana_gtk_example_2_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_3_SOURCES = jana-gtk-example-3.c jana_gtk_example_3_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_4_SOURCES = jana-gtk-example-4.c jana_gtk_example_4_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_5_SOURCES = jana-gtk-example-5.c jana_gtk_example_5_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_6_SOURCES = jana-gtk-example-6.c jana_gtk_example_6_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_7_SOURCES = jana-gtk-example-7.c jana_gtk_example_7_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_gtk_example_8_SOURCES = jana-gtk-example-8.c jana_gtk_example_8_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la \ ../libjana-gtk/libjana-gtk.la jana_ecal_example_1_SOURCES = jana-ecal-example-1.c jana_ecal_example_1_LDADD = ../libjana/libjana.la \ ../libjana-ecal/libjana-ecal.la jana/examples/jana-gtk-example-4.c0000644000175000017500000000511111327631152017146 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static JanaTime *range_start, *range_end; static void opened_cb (JanaStore *store, JanaGtkEventStore *event_store) { store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); jana_gtk_event_store_set_view (event_store, store_view); jana_store_view_start (store_view); } int main (int argc, char **argv) { JanaStore *store; GtkTreeModel *event_store; GtkWidget *window, *month_view; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); event_store = jana_gtk_event_store_new (); range_start = jana_ecal_utils_time_today ("UTC"); jana_time_set_day (range_start, 1); range_end = jana_time_duplicate (range_start); jana_time_set_day (range_end, jana_utils_time_days_in_month ( jana_time_get_year (range_end), jana_time_get_month (range_end))); month_view = jana_gtk_month_view_new (range_start); jana_utils_time_set_start_of_week (range_start); jana_utils_time_set_end_of_week (range_end); gtk_container_add (GTK_CONTAINER (window), month_view); gtk_window_set_default_size (GTK_WINDOW (window), 300, 400); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all (window); g_signal_connect (store, "opened", G_CALLBACK (opened_cb), event_store); jana_gtk_month_view_add_store (JANA_GTK_MONTH_VIEW (month_view), JANA_GTK_EVENT_STORE (event_store)); jana_store_open (store); gtk_main (); g_object_unref (range_start); g_object_unref (range_end); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/data/0000755000175000017500000000000011327631152014427 5ustar paulliupaulliujana/examples/data/Makefile.am0000644000175000017500000000015411327631152016463 0ustar paulliupaulliuresdir = $(pkgdatadir) res_DATA = flag-uk.png MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(res_DATA) jana/examples/data/flag-uk.png0000644000175000017500000000111311327631152016457 0ustar paulliupaulliu‰PNG  IHDR {ü}~bKGDÿÿÿ ½§“tIME× )®ÓñíIDAT(‘“OH“Æß7×´õm•sNrý¡C¬Á–ÔALŒÅåÁ9jŒˆ’.#I‚ ìàÁ›I…ÕvH‰ÁÈ“E1š˜ÓlN«¹L×h_‡Ê\ÿV>Ç÷yßçyy^^!ÚtRÖ{ZQíÜÆðýWï ‘J/³O.¹È9݈þA¬'nåñ’Z…×iÂýþ)Âd½§ñºÅNâö]âmíØ "Éà)݇ÑJÅ‚¤VÑÕ²‡ðÁÍãAÊ›ê1öú½É!v\£êžÈÿüM°Ì~‘Fï‚ëÌ ùû@‰JICõj§`n­Ã†²¼ŒÏéDªlì‡x7ò ü|– þq>.}Z1&=ò/+ý„ìÔ #£hêjQVVŒIëÌ…ׂ¢ÒWÁ¦5m¼:ãõ%ë8í´°w—žl"Ij8:›êjò2VHòøQu%wN³”É®+"oMÓ‰4çíãì+›ç¼>çcáeŒÅvŽ^~FCµù¦€ùCõ˜Ü×0›*°:jM?4’¥‚/GfG²cÿ2ѳ=}È[ n4ÓíŸ ½˜þü Z©˜+6~7_d3ˆÄÛÚ¿,öo‚cÿt Tz™FïЃ^™hŒæž>¾žÙ&ÔtIEND®B`‚jana/examples/jana-gtk-example-7.c0000644000175000017500000000542311327631152017157 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include static GtkWidget *map; static gchar *location; gboolean first = TRUE; static gboolean set_time (GtkWidget *clock) { JanaTime *time; time = jana_ecal_utils_time_now (location); jana_gtk_clock_set_time (JANA_GTK_CLOCK (clock), time); if (first || (jana_time_get_seconds (time) == 0)) { /* Update every minute */ jana_gtk_world_map_set_time (JANA_GTK_WORLD_MAP (map), time); first = FALSE; } g_object_unref (time); return TRUE; } static void clicked_cb (JanaGtkWorldMap *map, GdkEventButton *event) { gdouble lat, lon; jana_gtk_world_map_get_latlon (map, event->x, event->y, &lat, &lon); g_message ("Map clicked at latitude, longitude: %lg, %lg", lat, lon); } int main (int argc, char **argv) { guint id; GtkWidget *window, *align, *clock; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); map = jana_gtk_world_map_new (); jana_gtk_world_map_add_marker (JANA_GTK_WORLD_MAP (map), jana_gtk_world_map_marker_pixbuf_new( gdk_pixbuf_new_from_file ( PKGDATADIR "/flag-uk.png", NULL)), 51.75, -2.25); clock = jana_gtk_clock_new (); jana_gtk_clock_set_show_seconds (JANA_GTK_CLOCK (clock), TRUE); jana_gtk_clock_set_draw_shadow (JANA_GTK_CLOCK (clock), TRUE); align = gtk_alignment_new (1.0, 1.0, 0.3, 0.3); gtk_container_add (GTK_CONTAINER (align), clock); gtk_container_add (GTK_CONTAINER (map), align); gtk_container_add (GTK_CONTAINER (window), map); gtk_window_set_default_size (GTK_WINDOW (window), 480, 320); gtk_widget_show_all (window); g_signal_connect (map, "clicked", G_CALLBACK (clicked_cb), NULL); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); location = jana_ecal_utils_guess_location (); id = g_timeout_add (1000, (GSourceFunc)set_time, clock); set_time (clock); gtk_main (); g_source_remove (id); g_free (location); return 0; } jana/examples/jana-gtk-example-2.c0000644000175000017500000001127511327631152017154 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #define DEG2RAD(x) ((x)*(M_PI/180)) static JanaStoreView *store_view = NULL; static GtkCellRenderer *renderer; static const gint r = 240; static gdouble angle = 0; static gboolean animate_cb (gpointer data) { GList *cell, *cells, *selected; gint n_cells, i; JanaGtkTreeLayout *layout = (JanaGtkTreeLayout *)data; if (!(cells = jana_gtk_tree_layout_get_cells (layout))) return TRUE; selected = jana_gtk_tree_layout_get_selection (layout); n_cells = g_list_length (cells); for (i = 0, cell = cells; cell; cell = cell->next, i++) { gint x, y; gdouble local_angle; JanaGtkTreeLayoutCellInfo *info = (JanaGtkTreeLayoutCellInfo *)cell->data; local_angle = angle + ((360 / n_cells) * i); while (local_angle > 360) local_angle -= 360; if (g_list_find (selected, info)) { x = 240; y = 240; } else { x = (r * cos (DEG2RAD (local_angle))) + 240; y = (r * sin (DEG2RAD (local_angle))) + 240; } jana_gtk_tree_layout_move_cell (layout, info->row, (info->x + x) / 2, (info->y + y) / 2, info->width, info->height); } angle ++; if (angle > 360) angle -= 360; g_list_free (cells); g_list_free (selected); return TRUE; } static void row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, JanaGtkTreeLayout *layout) { GtkTreeRowReference *row = gtk_tree_row_reference_new (model, path); jana_gtk_tree_layout_add_cell (JANA_GTK_TREE_LAYOUT (layout), row, -150, 240, 150, -1, renderer, "uid", JANA_GTK_EVENT_STORE_COL_UID, "summary", JANA_GTK_EVENT_STORE_COL_SUMMARY, "description", JANA_GTK_EVENT_STORE_COL_DESCRIPTION, "start", JANA_GTK_EVENT_STORE_COL_START, "end", JANA_GTK_EVENT_STORE_COL_END, NULL); gtk_tree_row_reference_free (row); } static void opened_cb (JanaStore *store, JanaGtkEventStore *event_store) { JanaTime *range_start, *range_end; range_start = jana_ecal_utils_time_today ("UTC"); range_end = jana_time_duplicate (range_start); jana_time_set_day (range_end, jana_time_get_day (range_end) + 1); store_view = jana_store_get_view (store); jana_store_view_set_range (store_view, range_start, range_end); jana_gtk_event_store_set_view (event_store, store_view); jana_store_view_start (store_view); g_object_unref (range_start); g_object_unref (range_end); } static gboolean delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { g_source_remove_by_user_data (user_data); gtk_main_quit (); return FALSE; } int main (int argc, char **argv) { JanaStore *store; GtkWidget *window; GtkWidget *tree_layout; GtkTreeModel *event_store; guint animate_id; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); event_store = jana_gtk_event_store_new (); tree_layout = jana_gtk_tree_layout_new (); /* These allow the widget to resize correctly when sizing the window, * but looks weird due to the variable required size in this example. */ /*g_object_set (tree_layout, "fill_width", TRUE, "fill_height", TRUE, NULL);*/ renderer = jana_gtk_cell_renderer_event_new (); g_object_set (renderer, "draw_time", TRUE, NULL); gtk_container_add (GTK_CONTAINER (window), tree_layout); gtk_window_set_default_size (GTK_WINDOW (window), 630, 630); gtk_window_set_title (GTK_WINDOW (window), "Today's Events"); g_signal_connect (event_store, "row-inserted", G_CALLBACK (row_inserted_cb), tree_layout); g_signal_connect (window, "delete-event", G_CALLBACK (delete_event_cb), tree_layout); gtk_widget_show_all (window); g_signal_connect (G_OBJECT (store), "opened", G_CALLBACK (opened_cb), event_store); jana_store_open (store); animate_id = g_timeout_add (1000/30, animate_cb, tree_layout); gtk_main (); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/jana-gtk-example-8.c0000644000175000017500000000561511327631152017163 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static void opened_cb (JanaStore *store, JanaGtkNoteStore *note_store) { store_view = jana_store_get_view (store); jana_gtk_note_store_set_view (note_store, store_view); jana_store_view_start (store_view); } int main (int argc, char **argv) { JanaStore *store; GtkTreeModel *note_store; GtkWidget *window, *treeview, *scroll; GtkCellRenderer *renderer; GdkPixbuf *pixbuf; gtk_init (&argc, &argv); store = jana_ecal_store_new (JANA_COMPONENT_NOTE); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); note_store = jana_gtk_note_store_new (); treeview = gtk_tree_view_new_with_model (note_store); renderer = jana_gtk_cell_renderer_note_new (); pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), GTK_STOCK_EDIT, 48, 0, NULL); g_object_set (G_OBJECT (renderer), "icon", pixbuf, "justify", GTK_JUSTIFY_CENTER, NULL); g_object_unref (pixbuf); gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (treeview), -1, "Notes", renderer, "author", JANA_GTK_NOTE_STORE_COL_AUTHOR, "recipient", JANA_GTK_NOTE_STORE_COL_RECIPIENT, "body", JANA_GTK_NOTE_STORE_COL_BODY, "created", JANA_GTK_NOTE_STORE_COL_CREATED, "modified", JANA_GTK_NOTE_STORE_COL_MODIFIED, NULL); g_signal_connect (treeview, "size-allocate", G_CALLBACK (jana_gtk_utils_treeview_resize), renderer); scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scroll), treeview); gtk_container_add (GTK_CONTAINER (window), scroll); gtk_window_set_default_size (GTK_WINDOW (window), 300, 400); g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all (window); g_signal_connect (store, "opened", G_CALLBACK (opened_cb), note_store); jana_store_open (store); gtk_main (); g_object_unref (store); if (store_view) g_object_unref (store_view); return 0; } jana/examples/jana-ecal-example-1.c0000644000175000017500000000736011327631152017272 0ustar paulliupaulliu/* * Author: Chris Lord * Copyright (c) 2007 OpenedHand Ltd * Copyright (C) 2008 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static JanaStoreView *store_view = NULL; static void display_event (JanaEvent *event) { gchar *uid, *summary, *location, *description, *recur_string; JanaTime *start, *end; JanaRecurrence *recur; uid = jana_component_get_uid (JANA_COMPONENT (event)); summary = jana_event_get_summary (event); location = jana_event_get_location (event); description = jana_event_get_description (event); start = jana_event_get_start (event); end = jana_event_get_end (event); recur = jana_event_get_recurrence (event); recur_string = jana_utils_recurrence_to_string (recur, start); g_print ("UID: %s\n" "Summary: %s\n" "Location: %s\n" "Description: %s\n" "Starts: %d:%02d %d/%d/%04d\n" "End: %d:%02d %d/%d/%04d\n" "Recurrence: %s\n\n", uid, summary, location, description, jana_time_get_hours (start), jana_time_get_minutes (start), jana_time_get_day (start), jana_time_get_month (start), jana_time_get_year (start), jana_time_get_hours (end), jana_time_get_minutes (end), jana_time_get_day (end), jana_time_get_month (end), jana_time_get_year (end), jana_event_has_recurrence (event) ? recur_string : "None"); g_free (uid); g_free (summary); g_free (location); g_free (description); g_object_unref (start); g_object_unref (end); jana_recurrence_free (recur); g_free (recur_string); } static void added_cb (JanaStoreView *store_view, GList *components, gpointer user_data) { for (; components; components = components->next) { JanaEvent *event = JANA_EVENT (components->data); g_message ("Event added:"); display_event (event); } } static void modified_cb (JanaStoreView *store_view, GList *components, gpointer user_data) { for (; components; components = components->next) { JanaEvent *event = JANA_EVENT (components->data); g_message ("Event modified:"); display_event (event); } } static void removed_cb (JanaStoreView *store_view, GList *uids, gpointer user_data) { for (; uids; uids = uids->next) { g_message ("Event removed:"); g_print ("UID: %s\n", (gchar *)uids->data); } g_print ("\n"); } static void opened_cb (JanaStore *store, gpointer user_data) { store_view = jana_store_get_view (store); g_signal_connect (G_OBJECT (store_view), "added", G_CALLBACK (added_cb), NULL); g_signal_connect (G_OBJECT (store_view), "modified", G_CALLBACK (modified_cb), NULL); g_signal_connect (G_OBJECT (store_view), "removed", G_CALLBACK (removed_cb), NULL); jana_store_view_start (store_view); } int main (int argc, char **argv) { GMainLoop *main_loop; JanaStore *store; g_type_init (); store = jana_ecal_store_new (JANA_COMPONENT_EVENT); g_signal_connect (G_OBJECT (store), "opened", G_CALLBACK (opened_cb), NULL); jana_store_open (store); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); if (store_view) g_object_unref (store_view); g_object_unref (store); return 0; } jana/bindings/0000755000175000017500000000000011327631152013475 5ustar paulliupaulliujana/bindings/autogen.sh0000755000175000017500000000010211327631152015467 0ustar paulliupaulliu#!/bin/sh REQUIRED_AUTOMAKE_VERSION=1.7 exec gnome-autogen.sh $@ jana/bindings/Makefile.am0000644000175000017500000000007111327631152015527 0ustar paulliupaulliuSUBDIRS=@build_vala@ MAINTAINERCLEANFILES = Makefile.in jana/bindings/configure.ac0000644000175000017500000000213411327631152015763 0ustar paulliupaulliuAC_PREREQ(2.53) AC_INIT(jana-bindings, 0.0, http://www.openedhand.com/) AM_INIT_AUTOMAKE() AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE AC_ARG_ENABLE([vala], AC_HELP_STRING([--enable-vala], [Enable building of vala bindings]), [build_vala=vala]) AC_PATH_PROG(VALAC, valac, no) AC_PATH_PROG(VAPIGEN, vapigen, no) PKG_PROG_PKG_CONFIG() if test "$build_vala" = "vala"; then if test "x$VALAC" = "xno"; then AC_MSG_ERROR([Cannot find the "valac" compiler in your PATH]) fi if test "x$VAPIGEN" = "xno"; then AC_MSG_ERROR([Cannot find the "vapigen" binary in your PATH]) fi if test "x$PKG_CONFIG" = "xno"; then AC_MSG_ERROR([Cannot find the "pkg-config" program in your PATH]) fi PKG_CHECK_MODULES(VALA, [vala-1.0 >= 0.3.1]) m4_define([default_vapidir], [${datarootdir}/jana/vala/vapi]) AC_ARG_WITH([vapidir], [AC_HELP_STRING([--with-vapidir=@<:@default_vapidir@:>@], [define where to install the VAPI files])], [VAPIDIR=$with_vapidir], [VAPIDIR=default_vapidir]) AC_SUBST(VAPIDIR) fi AC_SUBST([build_vala]) AC_SUBST([VAPIDIR]) AC_OUTPUT([ Makefile vala/Makefile vala/jana-vala.pc ]) jana/bindings/NEWS0000644000175000017500000000000011327631152014162 0ustar paulliupaulliujana/bindings/ChangeLog0000644000175000017500000000304111327631152015245 0ustar paulliupaulliu2008-08-21 Chris Lord * vala/Makefile.am: Add .metadata/.gi dependencies to the .vapi targets * vala/libjana.metadata: Add transfer_ownership note for jana_duration_copy, fixes memory leaks in vala applications using JanaDuration 2008-08-18 Chris Lord * vala/libjana-gtk.gi: Regenerate to make show-headers writable in JanaGtkEventList * vala/libjana.gi: Regenerate to get GObject prerequisites for all interfaces 2008-08-18 Chris Lord * vala/libjana-ecal.metadata: * vala/libjana-gtk.metadata: Use the correct namespace 2008-08-15 Chris Lord * configure.ac: Use PKG_PROG_PKG_CONFIG macro 2008-08-12 Chris Lord Copy bits from clutter-vala, make vapidir configurable and install a pkg-config file * configure.ac: * vala/Makefile.am: * vala/jana-vala.pc.in: 2008-08-12 Chris Lord * vala/Makefile.am: Fix generation of .vapi files and correct depedencies 2008-07-11 Chris Lord * Makefile.am: * autogen.sh: * configure.ac: * vala/libjana-ecal.deps: * vala/libjana-ecal.files: * vala/libjana-ecal.gi: * vala/libjana-ecal.metadata: * vala/libjana-ecal.namespace: * vala/libjana-gtk.deps: * vala/libjana-gtk.files: * vala/libjana-gtk.gi: * vala/libjana-gtk.metadata: * vala/libjana-gtk.namespace: * vala/libjana.deps: * vala/libjana.files: * vala/libjana.gi: * vala/libjana.metadata: * vala/libjana.namespace: Initial check-in of vala bindings jana/bindings/vala/0000755000175000017500000000000011327631152014420 5ustar paulliupaulliujana/bindings/vala/libjana-gtk.deps0000644000175000017500000000010011327631152017447 0ustar paulliupaulliuatk gdk-pixbuf-2.0 pango cairo gio-2.0 gdk-2.0 gtk+-2.0 libjana jana/bindings/vala/libjana.metadata0000644000175000017500000000012211327631152017515 0ustar paulliupaulliuJana cheader_filename="libjana/jana.h" jana_duration_copy transfer_ownership="1" jana/bindings/vala/libjana.gi0000644000175000017500000012456611327631152016357 0ustar paulliupaulliu jana/bindings/vala/libjana-gtk.metadata0000644000175000017500000000006211327631152020303 0ustar paulliupaulliuJanaGtk cheader_filename="libjana-gtk/jana-gtk.h" jana/bindings/vala/libjana.namespace0000644000175000017500000000000511327631152017671 0ustar paulliupaulliuJana jana/bindings/vala/Makefile.am0000644000175000017500000000145111327631152016455 0ustar paulliupaulliu STAMP_FILES = libjana.stamp libjana-ecal.stamp libjana-gtk.stamp VAPI_FILES = libjana.vapi libjana-ecal.vapi libjana-gtk.vapi DEPS_FILES = libjana.deps libjana-ecal.deps libjana-gtk.deps %.stamp: $(VAPIGEN) \ --quiet \ --vapidir=. \ --vapidir=@VAPIDIR@ \ --library $* $*.gi \ && echo timestamp > $(@F) libjana.vapi: libjana.stamp libjana.gi libjana.metadata libjana-ecal.vapi: libjana.vapi libjana-ecal.stamp \ libjana-ecal.gi libjana-ecal.metadata libjana-gtk.vapi: libjana.vapi libjana-gtk.stamp \ libjana-gtk.gi libjana-gtk.metadata vapidir = @VAPIDIR@ vapi_DATA = $(VAPI_FILES) $(DEPS_FILES) pkgconfigdir = $(datadir)/pkgconfig pkgconfig_DATA = jana-vala.pc EXTRA_DIST = $(STAMP_FILES) $(VAPI_FILES) $(DEPS_FILES) MAINTAINERCLEANFILES = $(STAMP_FILES) $(VAPI_FILES) Makefile.in jana/bindings/vala/libjana-gtk.gi0000644000175000017500000013500411327631152017127 0ustar paulliupaulliu jana/bindings/vala/libjana-ecal.files0000644000175000017500000000005611327631152017747 0ustar paulliupaulliuinclude/jana/libjana-ecal lib/libjana-ecal.so jana/bindings/vala/libjana-ecal.deps0000644000175000017500000000001011327631152017566 0ustar paulliupaulliulibjana jana/bindings/vala/libjana-ecal.metadata0000644000175000017500000000006511327631152020425 0ustar paulliupaulliuJanaEcal cheader_filename="libjana-ecal/jana-ecal.h" jana/bindings/vala/libjana-ecal.namespace0000644000175000017500000000001111327631152020570 0ustar paulliupaulliuJanaEcal jana/bindings/vala/jana-vala.pc.in0000644000175000017500000000041011327631152017176 0ustar paulliupaulliuprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ datarootdir=@datarootdir@ datadir=@datadir@ vapidir=@VAPIDIR@ Name: Jana-Vala Description: Vala bindings for Jana Version: @VERSION@ Requires: glib-2.0 gobject-2.0 vala-1.0 libjana jana/bindings/vala/libjana-gtk.namespace0000644000175000017500000000001011327631152020450 0ustar paulliupaulliuJanaGtk jana/bindings/vala/libjana-gtk.files0000644000175000017500000000005411327631152017626 0ustar paulliupaulliuinclude/jana/libjana-gtk lib/libjana-gtk.so jana/bindings/vala/libjana.files0000644000175000017500000000004411327631152017042 0ustar paulliupaulliuinclude/jana/libjana lib/libjana.so jana/bindings/vala/libjana-ecal.gi0000644000175000017500000002011211327631152017237 0ustar paulliupaulliu jana/bindings/vala/libjana.deps0000644000175000017500000000000011327631152016663 0ustar paulliupaulliujana/bindings/README0000644000175000017500000000000011327631152014343 0ustar paulliupaulliujana/bindings/AUTHORS0000644000175000017500000000000011327631152014533 0ustar paulliupaulliu