X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fgtk-dateentry.c;h=f471c66472106f3454363a6a38a5385beb5ff1c9;hb=160a363125e5d06f47eb22b333788097e4f01362;hp=6e55a394f9cd615105babae7ae275b4f97481886;hpb=2ef3e601408ebaeeaf5f40d6967664b012a49979;p=chaz%2Fhomebank
diff --git a/src/gtk-dateentry.c b/src/gtk-dateentry.c
index 6e55a39..f471c66 100644
--- a/src/gtk-dateentry.c
+++ b/src/gtk-dateentry.c
@@ -1,5 +1,5 @@
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
@@ -17,9 +17,9 @@
* along with this program. If not, see .
*/
-#include
-#include
-#include
+
+//#include
+#include /* atoi, atof, atol */
#include
#include
@@ -34,40 +34,22 @@
#define DB(x);
#endif
+
enum {
CHANGED,
LAST_SIGNAL
};
+
enum {
PROPERTY_DATE = 5,
};
-static void gtk_date_entry_dispose (GObject *gobject);
-static void gtk_date_entry_finalize (GObject *gobject);
-static void gtk_date_entry_destroy (GtkWidget *dateentry);
-
-static void gtk_date_entry_entry_activate(GtkWidget * calendar, gpointer user_data);
-static gint gtk_date_entry_entry_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
-static void gtk_date_entry_button_clicked (GtkWidget * widget, GtkDateEntry * dateentry);
-
-static void
-gtk_date_entry_popup(GtkDateEntry * dateentry, GdkEvent *event);
-
-static gint gtk_date_entry_popup_key_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
-static gint gtk_date_entry_popup_button_press (GtkWidget * widget, GdkEvent * event, gpointer data);
-
-static void gtk_date_entry_calendar_year(GtkWidget * calendar, GtkDateEntry * dateentry);
-static void gtk_date_entry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry);
-static gint gtk_date_entry_calendar_select(GtkWidget * calendar, gpointer user_data);
-
-
-static void gtk_date_entry_entry_set_text(GtkDateEntry * dateentry);
-static void gtk_date_entry_popdown(GtkDateEntry *dateentry);
+static guint dateentry_signals[LAST_SIGNAL] = {0,};
-static guint dateentry_signals[LAST_SIGNAL] = {0,};
+G_DEFINE_TYPE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX)
// todo:finish this
@@ -96,7 +78,7 @@ hb_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
gint i;
const guchar *s;
- DB( g_print("\n[dateentry] fill parse token\n") );
+ //DB( g_print("\n[dateentry] fill parse token\n") );
/* We count 4, but store 3; so we can give an error
* if there are 4.
@@ -134,69 +116,22 @@ hb_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
}
-/*
-static void hb_date_determine_dmy(void)
-{
-GDate d;
-gchar buf[128];
-GDateParseTokens testpt;
-gint i;
-
- DB( g_print("\n[dateentry] determine dmy\n") );
-
- g_date_clear (&d, 1); // clear for scratch use
-
- // had to pick a random day - don't change this, some strftimes
- // are broken on some days, and this one is good so far.
- g_date_set_dmy (&d, 4, 7, 1976);
- g_date_strftime (buf, 127, "%x", &d);
-
- hb_date_fill_parse_tokens (buf, &testpt);
-
- i = 0;
- while (i < testpt.num_ints)
- {
- switch (testpt.n[i])
- {
- case 7:
- dmy_order[i] = G_DATE_MONTH;
- break;
- case 4:
- dmy_order[i] = G_DATE_DAY;
- break;
- case 1976:
- dmy_order[2] = G_DATE_YEAR;
- break;
- }
- ++i;
- }
-
- DB( g_print(" dmy legend: 0=day, 1=month, 2=year\n") );
- DB( g_print(" dmy is: %d %d %d\n", dmy_order[0], dmy_order[1], dmy_order[2]) );
-}*/
-
-
-static void hb_date_parse_tokens(GtkWidget *gtkentry, gpointer user_data)
+static void hb_date_parse_tokens(GDate *date, const gchar *str)
{
-GtkDateEntry *dateentry = user_data;
-GtkDateEntryPrivate *priv = dateentry->priv;
-const gchar *str;
GDateParseTokens pt;
- str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
-
hb_date_fill_parse_tokens(str, &pt);
- DB( g_print(" -> parsetoken return is %d values :%d %d %d\n", pt.num_ints, pt.n[0], pt.n[1], pt.n[2]) );
+ DB( g_print(" -> parsetoken return %d values: %d %d %d\n", pt.num_ints, pt.n[0], pt.n[1], pt.n[2]) );
// initialize with today's date
- g_date_set_time_t(priv->date, time(NULL));
+ g_date_set_time_t(date, time(NULL));
switch( pt.num_ints )
{
case 1:
DB( g_print(" -> seizured 1 number\n") );
if(g_date_valid_day(pt.n[0]))
- g_date_set_day(priv->date, pt.n[0]);
+ g_date_set_day(date, pt.n[0]);
break;
case 2:
DB( g_print(" -> seizured 2 numbers\n") );
@@ -205,189 +140,239 @@ GDateParseTokens pt;
if( dmy_order[0] == G_DATE_DAY )
{
if(g_date_valid_day(pt.n[0]))
- g_date_set_day(priv->date, pt.n[0]);
+ g_date_set_day(date, pt.n[0]);
if(g_date_valid_month(pt.n[1]))
- g_date_set_month(priv->date, pt.n[1]);
+ g_date_set_month(date, pt.n[1]);
}
else
{
if(g_date_valid_day(pt.n[1]))
- g_date_set_day(priv->date, pt.n[1]);
+ g_date_set_day(date, pt.n[1]);
if(g_date_valid_month(pt.n[0]))
- g_date_set_month(priv->date, pt.n[0]);
+ g_date_set_month(date, pt.n[0]);
}
}
break;
- }
-
-
-
+ }
}
+static void
+update_text(GtkDateEntry *self)
+{
+GtkDateEntryPrivate *priv = self->priv;
+gchar label[256];
+ DB( g_print("\n[dateentry] update text\n") );
-
-//end
-
-
-G_DEFINE_TYPE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX)
-
+ //%x : The preferred date representation for the current locale without the time.
+ g_date_strftime (label, 256 - 1, "%x", priv->date);
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), label);
+ DB( g_print(" = %s\n", label) );
+}
static void
-gtk_date_entry_class_init (GtkDateEntryClass *class)
+eval_date(GtkDateEntry *self)
{
-GObjectClass *object_class;
-GtkWidgetClass *widget_class;
-
- object_class = G_OBJECT_CLASS (class);
- widget_class = GTK_WIDGET_CLASS (class);
-
- DB( g_print("\n[dateentry] class_init\n") );
-
- //object_class->constructor = gtk_date_entry_constructor;
- //object_class->set_property = gtk_date_entry_set_property;
- //object_class->get_property = gtk_date_entry_get_property;
- object_class->dispose = gtk_date_entry_dispose;
- object_class->finalize = gtk_date_entry_finalize;
+GtkDateEntryPrivate *priv = self->priv;
- widget_class->destroy = gtk_date_entry_destroy;
+ g_date_clamp(priv->date, &priv->mindate, &priv->maxdate);
- dateentry_signals[CHANGED] =
- g_signal_new ("changed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkDateEntryClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (object_class, sizeof (GtkDateEntryPrivate));
+ update_text(self);
+ if(priv->lastdate != g_date_get_julian(priv->date))
+ {
+ DB( g_print(" **emit 'changed' signal**\n") );
+ g_signal_emit_by_name (self, "changed", NULL, NULL);
+ }
+
+ priv->lastdate = g_date_get_julian(priv->date);
}
-static gboolean
-gtk_date_entry_entry_focus_out(GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
+static void
+parse_date(GtkDateEntry *self)
{
-GtkDateEntry *dateentry = user_data;
+GtkDateEntryPrivate *priv = self->priv;
+const gchar *str;
+
+ DB( g_print("\n[dateentry] parse date\n") );
- DB( g_print("\n[dateentry] entry focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry))) );
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
- gtk_date_entry_entry_activate(GTK_WIDGET(dateentry), dateentry);
+ //1) we parse the string according to the locale
+ g_date_set_parse (priv->date, str);
+ if(!g_date_valid(priv->date) || g_date_get_julian (priv->date) <= HB_MINDATE)
+ {
+ //2) give a try to tokens: day, day/month, month/day
+ hb_date_parse_tokens(priv->date, str);
+ }
- return FALSE;
+ //3) at last if date still invalid, put today's dateentry_signals
+ // we should consider just warn the user here
+ if(!g_date_valid(priv->date))
+ {
+ g_date_set_time_t(priv->date, time(NULL));
+ }
+ eval_date(self);
}
+
static void
-gtk_date_entry_init (GtkDateEntry *dateentry)
+gtk_date_entry_cb_calendar_day_selected(GtkWidget * calendar, GtkDateEntry * dateentry)
{
-GtkDateEntryPrivate *priv;
+GtkDateEntryPrivate *priv = dateentry->priv;
+guint year, month, day;
- DB( g_print("\n[dateentry] init\n") );
+ DB( g_print("\n[dateentry] calendar_day_selected\n") );
- /* yes, also priv, need to keep the code readable */
- dateentry->priv = G_TYPE_INSTANCE_GET_PRIVATE (dateentry,
- GTK_TYPE_DATE_ENTRY,
- GtkDateEntryPrivate);
- priv = dateentry->priv;
+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
+ g_date_set_dmy (priv->date, day, month + 1, year);
+ eval_date(dateentry);
+}
-
- /* initialize datas */
- priv->date = g_date_new();
- priv->device = NULL;
- priv->popup_in_progress = FALSE;
- priv->has_grab = FALSE;
- g_date_set_time_t(priv->date, time(NULL));
+static gint
+gtk_date_entry_cb_calendar_day_select_double_click(GtkWidget * calendar, gpointer user_data)
+{
+GtkDateEntry *dateentry = user_data;
+GtkDateEntryPrivate *priv = dateentry->priv;
- g_date_set_dmy(&priv->mindate, 1, 1, 1900);
- g_date_set_dmy(&priv->maxdate, 31, 12, 2200);
+ DB( g_print("\n[dateentry] calendar_day_select_double_click\n") );
+ gtk_widget_hide (priv->popover);
- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry)), GTK_STYLE_CLASS_LINKED);
+ return FALSE;
+}
- //widget=GTK_WIDGET(dateentry);
-
- priv->entry = gtk_entry_new ();
-
- //gtk_entry_set_width_chars(GTK_ENTRY(priv->entry), 10);
- //gtk_entry_set_max_width_chars(GTK_ENTRY(priv->entry), 4);
-
-
- gtk_box_pack_start (GTK_BOX (dateentry), priv->entry, TRUE, TRUE, 0);
- g_signal_connect (priv->entry, "key-press-event",
- G_CALLBACK (gtk_date_entry_entry_key_pressed), dateentry);
+static void
+gtk_date_entry_cb_calendar_monthyear(GtkWidget *calendar, GtkDateEntry *dateentry)
+{
+GtkDateEntryPrivate *priv = dateentry->priv;
+guint year, month, day;
- g_signal_connect_after (priv->entry, "focus-out-event",
- G_CALLBACK (gtk_date_entry_entry_focus_out), dateentry);
+ DB( g_print("\n[dateentry] cb_calendar_monthyear\n") );
- g_signal_connect (priv->entry, "activate",
- G_CALLBACK (gtk_date_entry_entry_activate), dateentry);
+ gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
+ if( year < 1900)
+ g_object_set(calendar, "year", 1900, NULL);
+ if( year > 2200)
+ g_object_set(calendar, "year", 2200, NULL);
- priv->button = gtk_button_new ();
- priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
- gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
- gtk_box_pack_end (GTK_BOX (dateentry), priv->button, FALSE, FALSE, 0);
- gtk_widget_show_all (priv->button);
+}
- g_signal_connect (priv->button, "clicked",
- G_CALLBACK (gtk_date_entry_button_clicked), dateentry);
+static gint
+gtk_date_entry_cb_entry_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+GtkDateEntry *dateentry = user_data;
+GtkDateEntryPrivate *priv = dateentry->priv;
- priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_type_hint (
- GTK_WINDOW (priv->popup_window), GDK_WINDOW_TYPE_HINT_COMBO);
- gtk_widget_set_events (priv->popup_window,
- gtk_widget_get_events(priv->popup_window) | GDK_KEY_PRESS_MASK);
+ DB( g_print("\n[dateentry] entry key pressed: state=%04x, keyval=%04x\n", event->state, event->keyval) );
- priv->frame = gtk_frame_new (NULL);
- gtk_container_add (GTK_CONTAINER (priv->popup_window), priv->frame);
- gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_ETCHED_IN);
- gtk_widget_show (priv->frame);
+ if( event->keyval == GDK_KEY_Up )
+ {
+ if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
+ {
+ g_date_add_days (priv->date, 1);
+ eval_date(dateentry);
+ }
+ else
+ if( event->state & GDK_SHIFT_MASK )
+ {
+ g_date_add_months (priv->date, 1);
+ eval_date(dateentry);
+ }
+ else
+ if( event->state & GDK_CONTROL_MASK )
+ {
+ g_date_add_years (priv->date, 1);
+ eval_date(dateentry);
+ }
+ return TRUE;
+ }
+ else
+ if( event->keyval == GDK_KEY_Down )
+ {
+ if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
+ {
+ g_date_subtract_days (priv->date, 1);
+ eval_date(dateentry);
+ }
+ else
+ if( event->state & GDK_SHIFT_MASK )
+ {
+ g_date_subtract_months (priv->date, 1);
+ eval_date(dateentry);
+ }
+ else
+ if( event->state & GDK_CONTROL_MASK )
+ {
+ g_date_subtract_years (priv->date, 1);
+ eval_date(dateentry);
+ }
+ return TRUE;
+ }
- g_signal_connect (priv->popup_window, "key-press-event",
- G_CALLBACK (gtk_date_entry_popup_key_event), dateentry);
+ return FALSE;
+}
- g_signal_connect (priv->popup_window, "button-press-event",
- G_CALLBACK (gtk_date_entry_popup_button_press), dateentry);
-
- priv->calendar = gtk_calendar_new ();
- gtk_container_add (GTK_CONTAINER (priv->frame), priv->calendar);
- gtk_widget_show (priv->calendar);
+static void
+gtk_date_entry_cb_entry_activate(GtkWidget *gtkentry, gpointer user_data)
+{
+GtkDateEntry *dateentry = user_data;
- g_signal_connect (priv->calendar, "prev-year",
- G_CALLBACK (gtk_date_entry_calendar_year), dateentry);
- g_signal_connect (priv->calendar, "next-year",
- G_CALLBACK (gtk_date_entry_calendar_year), dateentry);
- g_signal_connect (priv->calendar, "prev-month",
- G_CALLBACK (gtk_date_entry_calendar_year), dateentry);
- g_signal_connect (priv->calendar, "next-month",
- G_CALLBACK (gtk_date_entry_calendar_year), dateentry);
+ DB( g_print("\n[dateentry] entry_activate\n") );
+
+ parse_date(dateentry);
+ eval_date(dateentry);
+}
- g_signal_connect (priv->calendar, "day-selected",
- G_CALLBACK (gtk_date_entry_calendar_getfrom), dateentry);
- g_signal_connect (priv->calendar, "day-selected-double-click",
- G_CALLBACK (gtk_date_entry_calendar_select), dateentry);
+static gboolean
+gtk_date_entry_cb_entry_focus_out(GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
+{
+GtkDateEntry *dateentry = user_data;
+
+ DB( g_print("\n[dateentry] entry focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry))) );
+ parse_date(dateentry);
+ eval_date(dateentry);
+ return FALSE;
}
-GtkWidget *
-gtk_date_entry_new ()
+static void
+gtk_date_entry_cb_button_clicked (GtkWidget * widget, GtkDateEntry * dateentry)
{
-GtkDateEntry *dateentry;
-
- DB( g_print("\n[dateentry] new\n") );
+GtkDateEntryPrivate *priv = dateentry->priv;
+//GdkRectangle rect;
+int month;
- dateentry = g_object_new (GTK_TYPE_DATE_ENTRY, NULL);
+ DB( g_print("\n[dateentry] button_clicked\n") );
- return GTK_WIDGET(dateentry);
+ /* GtkCalendar expects month to be in 0-11 range (inclusive) */
+ month = g_date_get_month (priv->date) - 1;
+
+ g_signal_handler_block(priv->calendar, priv->hid_dayselect);
+
+ gtk_calendar_select_month (GTK_CALENDAR (priv->calendar),
+ CLAMP (month, 0, 11),
+ g_date_get_year (priv->date));
+ gtk_calendar_select_day (GTK_CALENDAR (priv->calendar),
+ g_date_get_day (priv->date));
+
+ g_signal_handler_unblock(priv->calendar, priv->hid_dayselect);
+
+ gtk_popover_set_relative_to (GTK_POPOVER (priv->popover), GTK_WIDGET (priv->entry));
+ //gtk_widget_get_clip(priv->arrow, &rect);
+ //gtk_popover_set_pointing_to (GTK_POPOVER (priv->popover), &rect);
+
+ gtk_widget_show_all (priv->popover);
}
@@ -400,18 +385,13 @@ GtkDateEntryPrivate *priv = dateentry->priv;
g_return_if_fail(object != NULL);
g_return_if_fail(GTK_IS_DATE_ENTRY(object));
- DB( g_print(" \n[dateentry] destroy\n") );
+ DB( g_print("\n[dateentry] destroy\n") );
DB( g_print(" free gtkentry: %p\n", priv->entry) );
DB( g_print(" free arrow: %p\n", priv->button) );
- DB( g_print(" free popup_window: %p\n", priv->popup_window) );
DB( g_print(" free dateentry: %p\n", dateentry) );
- if(priv->popup_window)
- gtk_widget_destroy (priv->popup_window);
- priv->popup_window = NULL;
-
if(priv->date)
g_date_free(priv->date);
priv->date = NULL;
@@ -426,7 +406,7 @@ gtk_date_entry_dispose (GObject *gobject)
{
//GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
- DB( g_print(" \n[dateentry] dispose\n") );
+ DB( g_print("\n[dateentry] dispose\n") );
//g_clear_object (&self->priv->an_object);
@@ -442,7 +422,7 @@ gtk_date_entry_finalize (GObject *gobject)
{
//GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
- DB( g_print(" \n[dateentry] finalize\n") );
+ DB( g_print("\n[dateentry] finalize\n") );
//g_date_free(self->date);
@@ -455,478 +435,204 @@ gtk_date_entry_finalize (GObject *gobject)
}
-/*
-**
-*/
-void gtk_date_entry_set_date(GtkDateEntry *dateentry, guint32 julian_days)
+
+static void
+gtk_date_entry_class_init (GtkDateEntryClass *class)
{
-GtkDateEntryPrivate *priv = dateentry->priv;
+GObjectClass *object_class;
+GtkWidgetClass *widget_class;
- DB( g_print(" \n[dateentry] set date\n") );
+ object_class = G_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
- g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
+ DB( g_print("\n[dateentry] class_init\n") );
- if(g_date_valid_julian(julian_days))
- {
- g_date_set_julian (priv->date, julian_days);
- }
- else
- {
- g_date_set_time_t(priv->date, time(NULL));
- }
- gtk_date_entry_entry_set_text(dateentry);
-}
+ //object_class->constructor = gtk_date_entry_constructor;
+ //object_class->set_property = gtk_date_entry_set_property;
+ //object_class->get_property = gtk_date_entry_get_property;
+ object_class->dispose = gtk_date_entry_dispose;
+ object_class->finalize = gtk_date_entry_finalize;
-/*
-**
-*/
-void gtk_date_entry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days)
-{
-GtkDateEntryPrivate *priv = dateentry->priv;
+ widget_class->destroy = gtk_date_entry_destroy;
- DB( g_print(" \n[dateentry] set mindate\n") );
-
- g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
-
- if(g_date_valid_julian(julian_days))
- {
- g_date_set_julian (&priv->mindate, julian_days);
- }
-}
-
+ dateentry_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkDateEntryClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
-/*
-**
-*/
-void gtk_date_entry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days)
-{
-GtkDateEntryPrivate *priv = dateentry->priv;
+ g_type_class_add_private (object_class, sizeof (GtkDateEntryPrivate));
- DB( g_print(" \n[dateentry] set maxdate\n") );
-
- g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
-
- if(g_date_valid_julian(julian_days))
- {
- g_date_set_julian (&priv->maxdate, julian_days);
- }
}
-
-guint32 gtk_date_entry_get_date(GtkDateEntry * dateentry)
+static void
+gtk_date_entry_init (GtkDateEntry *dateentry)
{
-GtkDateEntryPrivate *priv = dateentry->priv;
-
- DB( g_print(" \n[dateentry] get date\n") );
+GtkDateEntryPrivate *priv;
- g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
+ DB( g_print("\n[dateentry] init\n") );
- return(g_date_get_julian(priv->date));
-}
+ /* yes, also priv, need to keep the code readable */
+ dateentry->priv = G_TYPE_INSTANCE_GET_PRIVATE (dateentry,
+ GTK_TYPE_DATE_ENTRY,
+ GtkDateEntryPrivate);
+ priv = dateentry->priv;
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry)), GTK_STYLE_CLASS_LINKED);
-static void
-gtk_date_entry_entry_set_text(GtkDateEntry * dateentry)
-{
-GtkDateEntryPrivate *priv = dateentry->priv;
-gchar buffer[256];
+ priv->entry = gtk_entry_new ();
+ //todo: see if really useful
+ gtk_entry_set_width_chars(GTK_ENTRY(priv->entry), 16);
+ gtk_entry_set_max_width_chars(GTK_ENTRY(priv->entry), 16);
+ gtk_box_pack_start (GTK_BOX (dateentry), priv->entry, TRUE, TRUE, 0);
- DB( g_print("\n[dateentry] entry set text\n") );
+ priv->button = gtk_button_new ();
+ priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
+ gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
+ gtk_box_pack_end (GTK_BOX (dateentry), priv->button, FALSE, FALSE, 0);
- g_date_clamp(priv->date, &priv->mindate, &priv->maxdate);
+ priv->popover = gtk_popover_new (priv->button);
+ gtk_popover_set_position(GTK_POPOVER(priv->popover), GTK_POS_BOTTOM);
+ priv->calendar = gtk_calendar_new ();
+ gtk_container_add (GTK_CONTAINER (priv->popover), priv->calendar);
+ gtk_widget_set_margin_start (priv->calendar, 10);
+ gtk_widget_set_margin_end (priv->calendar, 10);
+ gtk_widget_set_margin_top (priv->calendar, 10);
+ gtk_widget_set_margin_bottom (priv->calendar, 10);
- if(g_date_valid(priv->date) == TRUE)
- {
- g_date_strftime (buffer, 256 - 1, "%x", priv->date);
- gtk_entry_set_text (GTK_ENTRY (priv->entry), buffer);
-
- DB( g_print(" = %s\n", buffer) );
- }
- else
- gtk_entry_set_text (GTK_ENTRY (priv->entry), "??");
+ gtk_widget_show_all (GTK_WIDGET(dateentry));
+ /* initialize datas */
+ priv->date = g_date_new();
+ g_date_set_time_t(priv->date, time(NULL));
+ g_date_set_dmy(&priv->mindate, 1, 1, 1900); //693596
+ g_date_set_dmy(&priv->maxdate, 31, 12, 2200); //803533
+ update_text(dateentry);
- /* emit the signal */
- if(priv->lastdate != g_date_get_julian(priv->date))
- {
- DB( g_print(" **emit 'changed' signal**\n") );
-
- g_signal_emit_by_name (dateentry, "changed", NULL, NULL);
- }
- priv->lastdate = g_date_get_julian(priv->date);
+ g_signal_connect (priv->entry, "key-press-event",
+ G_CALLBACK (gtk_date_entry_cb_entry_key_pressed), dateentry);
-}
+ g_signal_connect_after (priv->entry, "focus-out-event",
+ G_CALLBACK (gtk_date_entry_cb_entry_focus_out), dateentry);
+ g_signal_connect (priv->entry, "activate",
+ G_CALLBACK (gtk_date_entry_cb_entry_activate), dateentry);
-static void
-gtk_date_entry_entry_activate(GtkWidget *gtkentry, gpointer user_data)
-{
-GtkDateEntry *dateentry = user_data;
-GtkDateEntryPrivate *priv = dateentry->priv;
-const gchar *str;
- DB( g_print("\n[dateentry] entry_activate\n") );
+ g_signal_connect (priv->button, "clicked",
+ G_CALLBACK (gtk_date_entry_cb_button_clicked), dateentry);
- str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
- //1) we parse the string according to the locale
- g_date_set_parse (priv->date, str);
- if(g_date_valid(priv->date) == FALSE)
- {
- //2) give a try to tokens: day, day/month, month/day
- hb_date_parse_tokens(gtkentry, user_data);
- }
+ g_signal_connect (priv->calendar, "prev-year",
+ G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
+ g_signal_connect (priv->calendar, "next-year",
+ G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
+ g_signal_connect (priv->calendar, "prev-month",
+ G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
+ g_signal_connect (priv->calendar, "next-month",
+ G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
- //3) at last if date still invalid, put today's dateentry_signals
- // we should consider just warn the user here
- if(g_date_valid(priv->date) == FALSE)
- {
- /* today's date */
- g_date_set_time_t(priv->date, time(NULL));
- }
+ priv->hid_dayselect = g_signal_connect (priv->calendar, "day-selected",
+ G_CALLBACK (gtk_date_entry_cb_calendar_day_selected), dateentry);
- gtk_date_entry_entry_set_text(dateentry);
+ g_signal_connect (priv->calendar, "day-selected-double-click",
+ G_CALLBACK (gtk_date_entry_cb_calendar_day_select_double_click), dateentry);
}
-static void
-gtk_date_entry_calendar_year(GtkWidget *calendar, GtkDateEntry *dateentry)
+GtkWidget *
+gtk_date_entry_new ()
{
-GtkDateEntryPrivate *priv = dateentry->priv;
-guint year, month, day;
+GtkDateEntry *dateentry;
- DB( g_print(" (dateentry) year changed\n") );
+ DB( g_print("\n[dateentry] new\n") );
- gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
- if( year < 1900)
- g_object_set(calendar, "year", 1900, NULL);
+ dateentry = g_object_new (GTK_TYPE_DATE_ENTRY, NULL);
- if( year > 2200)
- g_object_set(calendar, "year", 2200, NULL);
-
+ return GTK_WIDGET(dateentry);
}
-static void
-gtk_date_entry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry)
+/*
+**
+*/
+void
+gtk_date_entry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days)
{
GtkDateEntryPrivate *priv = dateentry->priv;
-guint year, month, day;
-
- DB( g_print(" (dateentry) calendar_getfrom\n") );
-
- gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
- g_date_set_dmy (priv->date, day, month + 1, year);
- gtk_date_entry_entry_set_text(dateentry);
-}
-
-
-static gint
-gtk_date_entry_calendar_select(GtkWidget * calendar, gpointer user_data)
-{
-GtkDateEntry *dateentry = user_data;
-
- DB( g_print(" (dateentry) calendar_select\n") );
-
- gtk_date_entry_calendar_getfrom(NULL, dateentry);
- gtk_date_entry_popdown(dateentry);
- return FALSE;
-}
-
+ DB( g_print("\n[dateentry] set mindate\n") );
-static gint
-gtk_date_entry_entry_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
-{
-GtkDateEntry *dateentry = user_data;
-GtkDateEntryPrivate *priv = dateentry->priv;
-
- DB( g_print("\n[dateentry] entry key pressed: state=%04x, keyval=%04x\n", event->state, event->keyval) );
+ g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
- if( event->keyval == GDK_KEY_Up )
- {
- if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
- {
- g_date_add_days (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- else
- if( event->state & GDK_SHIFT_MASK )
- {
- g_date_add_months (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- else
- if( event->state & GDK_CONTROL_MASK )
- {
- g_date_add_years (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- return TRUE;
- }
- else
- if( event->keyval == GDK_KEY_Down )
+ if(g_date_valid_julian(julian_days))
{
- if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
- {
- g_date_subtract_days (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- else
- if( event->state & GDK_SHIFT_MASK )
- {
- g_date_subtract_months (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- else
- if( event->state & GDK_CONTROL_MASK )
- {
- g_date_subtract_years (priv->date, 1);
- gtk_date_entry_entry_set_text(dateentry);
- }
- return TRUE;
+ g_date_set_julian (&priv->mindate, julian_days);
}
-
- return FALSE;
}
-static void
-gtk_date_entry_popup_position (GtkDateEntry * dateentry)
+/*
+**
+*/
+void
+gtk_date_entry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days)
{
GtkDateEntryPrivate *priv = dateentry->priv;
-gint x, y;
-gint bwidth, bheight;
-GtkRequisition req;
-GdkWindow *gdkwindow;
-GtkAllocation allocation;
-
- DB( g_print("\n[dateentry] position popup\n") );
-
- gtk_widget_get_preferred_size (priv->popup_window, NULL, &req);
-
- gdkwindow = gtk_widget_get_window(priv->button);
- gdk_window_get_origin (gdkwindow, &x, &y);
-
- gtk_widget_get_allocation(priv->button, &allocation);
- x += allocation.x;
- y += allocation.y;
- bwidth = allocation.width;
- bheight = allocation.height;
-
- x += bwidth - req.width;
- y += bheight;
-
- if (x < 0)
- x = 0;
-
- if (y < 0)
- y = 0;
-
- gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);
-}
-
-
-static void
-gtk_date_entry_button_clicked (GtkWidget * widget, GtkDateEntry * dateentry)
-{
-GdkEvent *event;
-
- DB( g_print("\n[dateentry] button_clicked\n") );
-
-/* Obtain the GdkEvent that triggered
- * the date button's "clicked" signal. */
- event = gtk_get_current_event ();
- gtk_date_entry_popup(dateentry, event);
-
-}
-
-
-static void
-gtk_date_entry_popup(GtkDateEntry * dateentry, GdkEvent *event)
-{
-GtkDateEntryPrivate *priv = dateentry->priv;
-const char *str;
-int month;
-GdkDevice *event_device;
-GdkDevice *assoc_device;
-GdkDevice *keyboard_device;
-GdkDevice *pointer_device;
-GdkWindow *window;
-GdkGrabStatus grab_status;
-guint event_time;
-
+ DB( g_print("\n[dateentry] set maxdate\n") );
- DB( g_print("\n[dateentry] popup_display\n****\n\n") );
-
-/* update */
- str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
- g_date_set_parse (priv->date, str);
+ g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
- if(g_date_valid(priv->date) == TRUE)
+ if(g_date_valid_julian(julian_days))
{
- /* GtkCalendar expects month to be in 0-11 range (inclusive) */
- month = g_date_get_month (priv->date) - 1;
- gtk_calendar_select_month (GTK_CALENDAR (priv->calendar),
- CLAMP (month, 0, 11),
- g_date_get_year (priv->date));
- gtk_calendar_select_day (GTK_CALENDAR (priv->calendar),
- g_date_get_day (priv->date));
- }
-
-
- /* popup */
- gtk_date_entry_popup_position(dateentry);
- gtk_widget_show (priv->popup_window);
- gtk_widget_grab_focus (priv->popup_window);
- gtk_grab_add (priv->popup_window);
-
- window = gtk_widget_get_window (priv->popup_window);
-
- g_return_if_fail (priv->grab_keyboard == NULL);
- g_return_if_fail (priv->grab_pointer == NULL);
-
- event_device = gdk_event_get_device (event);
- assoc_device = gdk_device_get_associated_device (event_device);
-
- event_time = gdk_event_get_time (event);
-
- if (gdk_device_get_source (event_device) == GDK_SOURCE_KEYBOARD) {
- keyboard_device = event_device;
- pointer_device = assoc_device;
- } else {
- keyboard_device = assoc_device;
- pointer_device = event_device;
- }
-
- if (keyboard_device != NULL) {
- grab_status = gdk_device_grab (
- keyboard_device,
- window,
- GDK_OWNERSHIP_WINDOW,
- TRUE,
- GDK_KEY_PRESS_MASK |
- GDK_KEY_RELEASE_MASK,
- NULL,
- event_time);
- if (grab_status == GDK_GRAB_SUCCESS) {
- priv->grab_keyboard =
- g_object_ref (keyboard_device);
- }
- }
-
- if (pointer_device != NULL) {
- grab_status = gdk_device_grab (
- pointer_device,
- window,
- GDK_OWNERSHIP_WINDOW,
- TRUE,
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK,
- NULL,
- event_time);
- if (grab_status == GDK_GRAB_SUCCESS) {
- priv->grab_pointer =
- g_object_ref (pointer_device);
- } else if (priv->grab_keyboard != NULL) {
- gdk_device_ungrab (
- priv->grab_keyboard,
- event_time);
- g_object_unref (priv->grab_keyboard);
- priv->grab_keyboard = NULL;
- }
+ g_date_set_julian (&priv->maxdate, julian_days);
}
-
- gdk_window_focus (window, event_time);
-
}
-static void
-gtk_date_entry_popdown(GtkDateEntry *dateentry)
+/*
+**
+*/
+void
+gtk_date_entry_set_date(GtkDateEntry *dateentry, guint32 julian_days)
{
GtkDateEntryPrivate *priv = dateentry->priv;
- DB( g_print("\n[dateentry] popdown\n") );
+ DB( g_print("\n[dateentry] set date\n") );
- gtk_widget_hide (priv->popup_window);
- gtk_grab_remove (priv->popup_window);
+ g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
- if (priv->grab_keyboard != NULL) {
- gdk_device_ungrab (
- priv->grab_keyboard,
- GDK_CURRENT_TIME);
- g_object_unref (priv->grab_keyboard);
- priv->grab_keyboard = NULL;
+ if(g_date_valid_julian(julian_days))
+ {
+ g_date_set_julian (priv->date, julian_days);
}
-
- if (priv->grab_pointer != NULL) {
- gdk_device_ungrab (
- priv->grab_pointer,
- GDK_CURRENT_TIME);
- g_object_unref (priv->grab_pointer);
- priv->grab_pointer = NULL;
+ else
+ {
+ g_date_set_time_t(priv->date, time(NULL));
}
-
+ eval_date(dateentry);
}
-
-
-
-static gint
-gtk_date_entry_popup_key_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
-{
-GtkDateEntry *dateentry = user_data;
-
- DB( g_print("\n[dateentry] popup_key_event%d\n", event->keyval) );
-
- DB( g_print(" -> key=%d\n", event->keyval) );
-
- if (event->keyval != GDK_KEY_Escape && event->keyval != GDK_KEY_Return)
- return FALSE;
-
- g_signal_stop_emission_by_name (widget, "key-press-event");
-
- gtk_date_entry_popdown(dateentry);
-
- return TRUE;
-}
-
-
-static gint
-gtk_date_entry_popup_button_press (GtkWidget * widget, GdkEvent * event, gpointer user_data)
+/*
+**
+*/
+guint32
+gtk_date_entry_get_date(GtkDateEntry *dateentry)
{
-GtkDateEntry *dateentry = user_data;
-//GtkDateEntryPrivate *priv = dateentry->priv;
-GtkWidget *child;
-
- DB( g_print("\n[dateentry] popup_button_press\n") );
-
- child = gtk_get_event_widget (event);
-
- /* We don't ask for button press events on the grab widget, so
- * if an event is reported directly to the grab widget, it must
- * be on a window outside the application (and thus we remove
- * the popup window). Otherwise, we check if the widget is a child
- * of the grab widget, and only remove the popup window if it
- * is not.
- */
- if (child != widget) {
- while (child) {
- if (child == widget)
- return FALSE;
- child = gtk_widget_get_parent (child);
- }
- }
+GtkDateEntryPrivate *priv = dateentry->priv;
+
+ DB( g_print("\n[dateentry] get date\n") );
- gtk_date_entry_popdown(dateentry);
+ g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
- return TRUE;
+ return(g_date_get_julian(priv->date));
}