[gnome-calendar] Added GcalDateEntry widget.
- From: Erick PÃrez Castellanos <erickpc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] Added GcalDateEntry widget.
- Date: Sat, 1 Dec 2012 20:32:19 +0000 (UTC)
commit 8594de0f28e34d22b3728c6ce9c33103401d454c
Author: Erick PÃrez Castellanos <erick red gmail com>
Date: Tue Oct 16 14:25:10 2012 -0400
Added GcalDateEntry widget.
Initial approach. I really don't like the implementation, is kinda week.
And it needs a lot of testing, localization kind of testing.
src/Makefile.am | 2 +
src/gcal-date-entry.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++++
src/gcal-date-entry.h | 69 +++++++++
3 files changed, 475 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 459e836..356b732 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ gnome_calendar_SOURCES = \
gcal-edit-dialog.h \
gcal-time-entry.c \
gcal-time-entry.h \
+ gcal-date-entry.c \
+ gcal-date-entry.h \
gcal-manager.c \
gcal-manager.h \
gcal-utils.c \
diff --git a/src/gcal-date-entry.c b/src/gcal-date-entry.c
new file mode 100644
index 0000000..56835d5
--- /dev/null
+++ b/src/gcal-date-entry.c
@@ -0,0 +1,404 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * gcal-date-entry.c
+ * Copyright (C) 2012 Erick PÃrez Castellanos <erickpc gnome org>
+ *
+ * gnome-calendar is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gnome-calendar 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gcal-date-entry.h"
+
+#include <locale.h>
+#include <langinfo.h>
+#include <glib/gi18n.h>
+
+struct _GcalDateEntryPrivate
+{
+ gboolean internal_skip;
+
+ guint day; /* 1 - 28 || 29 || 30 || 31 */
+ guint month; /* 1 - 12 */
+ guint year;
+
+ gchar *mask;
+ guint day_pos;
+ guint month_pos;
+ guint year_pos;
+ gboolean have_long_year;
+};
+
+static void gtk_editable_iface_init (GtkEditableInterface *iface);
+
+static void gcal_date_entry_constructed (GObject *object);
+
+static void gcal_date_entry_icon_press (GtkEntry *entry,
+ GtkEntryIconPosition icon_pos,
+ GdkEvent *event,
+ gpointer user_data);
+
+static void gcal_date_entry_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position);
+
+static void gcal_date_entry_delete_text (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos);
+
+static void gcal_date_entry_validate_and_insert (GcalDateEntry *entry);
+
+G_DEFINE_TYPE_WITH_CODE (GcalDateEntry,
+ gcal_date_entry,
+ GTK_TYPE_ENTRY,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
+ gtk_editable_iface_init));
+
+static void
+gcal_date_entry_class_init (GcalDateEntryClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gcal_date_entry_constructed;
+
+ g_type_class_add_private ((gpointer)klass, sizeof(GcalDateEntryPrivate));
+}
+
+static void
+gcal_date_entry_init (GcalDateEntry *self)
+{
+ GcalDateEntryPrivate *priv;
+ gchar *have_y;
+
+ gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ GCAL_TYPE_DATE_ENTRY,
+ GcalDateEntryPrivate);
+ priv = self->priv;
+
+ priv->internal_skip = FALSE;
+ priv->day = 1;
+ priv->month = 1;
+ priv->year = 1970;
+
+ setlocale (LC_ALL,"");
+ priv->mask = nl_langinfo (D_FMT);
+
+ priv->day_pos = - (priv->mask - g_strstr_len (priv->mask, -1, "%d"));
+ priv->month_pos = - (priv->mask - g_strstr_len (priv->mask, -1, "%m"));
+ if ((have_y = g_strstr_len (priv->mask, - 1, "%y")) != NULL)
+ {
+ priv->have_long_year = FALSE;
+ priv->year_pos = - (priv->mask - have_y);
+ }
+ else
+ {
+ priv->have_long_year = TRUE;
+ priv->year_pos = - (priv->mask - g_strstr_len (priv->mask, -1, "%Y"));
+ if (priv->year_pos < priv->day_pos)
+ priv->day_pos += 2;
+ if (priv->year_pos < priv->month_pos)
+ priv->month_pos += 2;
+ }
+}
+
+static void
+gtk_editable_iface_init (GtkEditableInterface *iface)
+{
+ iface->insert_text = gcal_date_entry_insert_text;
+ iface->delete_text = gcal_date_entry_delete_text;
+}
+
+static void
+gcal_date_entry_constructed (GObject *object)
+{
+ GcalDateEntryPrivate *priv;
+
+ priv = GCAL_DATE_ENTRY (object)->priv;
+
+ /* chaining up */
+ G_OBJECT_CLASS (gcal_date_entry_parent_class)->constructed (object);
+
+ gtk_entry_set_width_chars (
+ GTK_ENTRY (object),
+ strlen (priv->mask) + (priv->have_long_year ? 4 : 2));
+ gtk_entry_set_alignment (GTK_ENTRY (object), 0.5);
+
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (object),
+ GTK_ENTRY_ICON_SECONDARY,
+ "x-office-calendar-symbolic");
+ gtk_entry_set_icon_tooltip_text (GTK_ENTRY (object),
+ GTK_ENTRY_ICON_SECONDARY,
+ _("Change the date"));
+
+ /* default text */
+ gcal_date_entry_validate_and_insert (GCAL_DATE_ENTRY (object));
+
+ /* setting signals */
+ g_signal_connect (object,
+ "icon-press",
+ G_CALLBACK (gcal_date_entry_icon_press),
+ object);
+}
+
+static void
+gcal_date_entry_icon_press (GtkEntry *entry,
+ GtkEntryIconPosition icon_pos,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ g_debug ("Icon pressed");
+}
+
+static void
+gcal_date_entry_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position)
+{
+ GcalDateEntryPrivate *priv;
+ GtkEditableInterface *parent_editable_iface;
+ gboolean new_string_set;
+ gchar new_string [16];
+ gint i;
+
+ priv = GCAL_DATE_ENTRY (editable)->priv;
+ parent_editable_iface = g_type_interface_peek (gcal_date_entry_parent_class,
+ GTK_TYPE_EDITABLE);
+
+ if (priv->internal_skip)
+ {
+ parent_editable_iface->insert_text (editable,
+ new_text,
+ new_text_length,
+ position);
+ *position = 0;
+ return;
+ }
+
+ new_string_set = FALSE;
+ memset (new_string, 0, 16);
+ /* Is it day */
+ if (*position >= priv->day_pos &&
+ *position < priv->day_pos + 2)
+ {
+ //trim string, decide what to remove
+ for (i = 0; i < priv->day_pos + 2 - *position; i++)
+ {
+ if (g_ascii_isdigit (new_text[i]))
+ {
+ new_string_set = TRUE;
+ new_string[i] = new_text[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /* Is it month */
+ if (*position >= priv->month_pos &&
+ *position < priv->month_pos + 2)
+ {
+ //trim string, decide what to remove
+ for (i = 0; i < priv->month_pos + 2 - *position; i++)
+ {
+ if (g_ascii_isdigit (new_text[i]))
+ {
+ new_string_set = TRUE;
+ new_string[i] = new_text[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /* Is it year */
+ if (*position >= priv->year_pos &&
+ *position < priv->year_pos + (priv->have_long_year ? 4 : 2))
+ {
+ //trim string, decide what to remove
+ for (i = 0;
+ i < priv->year_pos + (priv->have_long_year ? 4 : 2) - *position;
+ i++)
+ {
+ if (g_ascii_isdigit (new_text[i]))
+ {
+ new_string_set = TRUE;
+ new_string[i] = new_text[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if (new_string_set)
+ {
+ gchar* unit_string;
+ const gchar* text;
+
+ /* making space for new_string */
+ priv->internal_skip = TRUE;
+ gtk_editable_delete_text (editable,
+ *position,
+ *position + strlen (new_string));
+ priv->internal_skip = FALSE;
+
+ parent_editable_iface->insert_text (editable,
+ new_string,
+ strlen (new_string),
+ position);
+
+ /* Updating internal data and validating */
+ text = gtk_entry_get_text (GTK_ENTRY (editable));
+ unit_string = g_strndup (text + priv->day_pos, 2);
+ priv->day = (guint) g_ascii_strtoull (unit_string, NULL, 10);
+ g_free (unit_string);
+
+ unit_string = g_strndup (text + priv->month_pos, 2);
+ priv->month = (guint) g_ascii_strtoull (unit_string, NULL, 10);
+ g_free (unit_string);
+
+ unit_string = g_strndup (text + priv->year_pos, (priv->have_long_year ? 4 : 2));
+ priv->year = (guint) g_ascii_strtoull (unit_string, NULL, 10);
+ g_free (unit_string);
+
+ gcal_date_entry_validate_and_insert (GCAL_DATE_ENTRY (editable));
+ }
+}
+
+static void
+gcal_date_entry_delete_text (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos)
+{
+ /* do nothing, unless we mark it */
+ GcalDateEntryPrivate *priv;
+ GtkEditableInterface *parent_editable_iface;
+
+ priv = GCAL_DATE_ENTRY (editable)->priv;
+ parent_editable_iface = g_type_interface_peek (gcal_date_entry_parent_class,
+ GTK_TYPE_EDITABLE);
+
+ if (priv->internal_skip)
+ {
+ parent_editable_iface->delete_text (editable,
+ start_pos,
+ end_pos);
+ }
+}
+
+static void
+gcal_date_entry_validate_and_insert (GcalDateEntry *entry)
+{
+ GcalDateEntryPrivate *priv;
+ gchar *tmp;
+ gchar *tmp1;
+ gchar **tokens;
+ gchar *unit;
+
+ priv = entry->priv;
+
+ if (priv->month > 12)
+ priv->month = 12;
+ if (priv->day > g_date_days_in_month (priv->month, priv->year))
+ priv->day = g_date_days_in_month (priv->month, priv->year);
+
+ tokens = g_strsplit (priv->mask, "%d", -1);
+ unit = g_strdup_printf ("%.2d", priv->day);
+ tmp = g_strjoinv (unit, tokens);
+ g_free (unit);
+ g_strfreev (tokens);
+
+ tokens = g_strsplit (tmp, "%m", -1);
+ unit = g_strdup_printf ("%.2d", priv->month);
+ tmp1 = g_strjoinv (unit, tokens);
+ g_free (unit);
+ g_strfreev (tokens);
+
+ g_free (tmp);
+ if (priv->have_long_year)
+ {
+ tokens = g_strsplit (tmp1, "%Y", -1);
+ unit = g_strdup_printf ("%.4d", priv->year);
+ tmp = g_strjoinv (unit, tokens);
+ }
+ else
+ {
+ tokens = g_strsplit (tmp1, "%y", -1);
+ unit = g_strdup_printf ("%.2d", priv->year);
+ tmp = g_strjoinv (unit, tokens);
+ }
+
+ g_free (unit);
+ g_strfreev (tokens);
+
+ priv->internal_skip = TRUE;
+ gtk_entry_set_text (GTK_ENTRY (entry), tmp);
+ priv->internal_skip = FALSE;
+
+ g_free (tmp);
+ g_free (tmp1);
+}
+
+/* Public API */
+GtkWidget*
+gcal_date_entry_new (void)
+{
+ return g_object_new (GCAL_TYPE_DATE_ENTRY, NULL);
+}
+
+void
+gcal_date_entry_set_date (GcalDateEntry *entry,
+ guint day,
+ guint month,
+ guint year)
+{
+ GcalDateEntryPrivate *priv;
+
+ g_return_if_fail (GCAL_IS_DATE_ENTRY (entry));
+ priv = entry->priv;
+
+ priv->day = day;
+ priv->month = month;
+ priv->year = year;
+
+ gcal_date_entry_validate_and_insert (entry);
+}
+
+void
+gcal_date_entry_get_date (GcalDateEntry *entry,
+ guint *day,
+ guint *month,
+ guint *year)
+{
+ GcalDateEntryPrivate *priv;
+
+ g_return_if_fail (GCAL_IS_DATE_ENTRY (entry));
+ priv = entry->priv;
+
+ if (day != NULL)
+ *day = priv->day;
+ if (month != NULL)
+ *month = priv->month;
+ if (year != NULL)
+ *year = priv->year;
+}
diff --git a/src/gcal-date-entry.h b/src/gcal-date-entry.h
new file mode 100644
index 0000000..38ba706
--- /dev/null
+++ b/src/gcal-date-entry.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * gcal-date-entry.h
+ * Copyright (C) 2012 Erick PÃrez Castellanos <erickpc gnome org>
+ *
+ * gnome-calendar is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gnome-calendar 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GCAL_DATE_ENTRY_H__
+#define __GCAL_DATE_ENTRY_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_DATE_ENTRY (gcal_date_entry_get_type ())
+#define GCAL_DATE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GCAL_TYPE_DATE_ENTRY, GcalDateEntry))
+#define GCAL_DATE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GCAL_TYPE_DATE_ENTRY, GcalDateEntryClass))
+#define GCAL_IS_DATE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GCAL_TYPE_DATE_ENTRY))
+#define GCAL_IS_DATE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GCAL_TYPE_DATE_ENTRY))
+#define GCAL_DATE_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GCAL_TYPE_DATE_ENTRY, GcalDateEntryClass))
+
+typedef struct _GcalTime GcalTime;
+
+typedef struct _GcalDateEntry GcalDateEntry;
+typedef struct _GcalDateEntryClass GcalDateEntryClass;
+typedef struct _GcalDateEntryPrivate GcalDateEntryPrivate;
+
+struct _GcalDateEntry
+{
+ GtkEntry parent;
+ /* add your public declarations here */
+
+ GcalDateEntryPrivate *priv;
+};
+
+struct _GcalDateEntryClass
+{
+ GtkEntryClass parent_class;
+};
+
+GType gcal_date_entry_get_type (void);
+
+GtkWidget* gcal_date_entry_new (void);
+
+void gcal_date_entry_set_date (GcalDateEntry *entry,
+ guint day,
+ guint month,
+ guint year);
+
+void gcal_date_entry_get_date (GcalDateEntry *entry,
+ guint *day,
+ guint *month,
+ guint *year);
+
+G_END_DECLS
+
+#endif /* __GCAL_DATE_ENTRY_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]