]> Dogcows Code - chaz/homebank/blobdiff - src/gtk-dateentry.c
import homebank-5.2.6
[chaz/homebank] / src / gtk-dateentry.c
index ea61280a5e00e8fbe59b956a7c76b5c15bd1701f..f471c66472106f3454363a6a38a5385beb5ff1c9 100644 (file)
@@ -1,5 +1,5 @@
 /*  HomeBank -- Free, easy, personal accounting for everyone.
- *  Copyright (C) 1995-2014 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 <http://www.gnu.org/licenses/>.
  */
 
-#include <stdlib.h>    
-#include <string.h>
-#include <time.h>
+
+//#include <time.h>
+#include <stdlib.h>            /* atoi, atof, atol */
 
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #define DB(x);
 #endif
 
+
 enum {
   CHANGED,
   LAST_SIGNAL
 };
 
+
 enum {
        PROPERTY_DATE = 5,
 };
 
-static void         gtk_dateentry_class_init      (GtkDateEntryClass *klass);
-static void         gtk_dateentry_init            (GtkDateEntry      *dateentry);
-static void         gtk_dateentry_destroy         (GtkObject     *dateentry);
-static void         gtk_dateentry_popup_display   (GtkDateEntry *dateentry);
-static gint        gtk_dateentry_arrow_press     (GtkWidget * widget,
-                                                 GtkDateEntry * dateentry);
-static gint         gtk_dateentry_button_press    (GtkWidget     *widget,
-                                                 GdkEvent      *event,
-                                                  gpointer data);
-
-static void gtk_dateentry_entry_parse(GtkWidget * calendar, gpointer user_data);
-static gint gtk_dateentry_entry_key (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
-static void gtk_dateentry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry);
-static gint gtk_dateentry_calendar_select(GtkWidget * calendar, gpointer user_data);
-static void gtk_dateentry_calendar_year(GtkWidget * calendar, GtkDateEntry * dateentry);
-static void gtk_dateentry_hide_popdown_window(GtkDateEntry *dateentry);
-static gint gtk_dateentry_arrow_press (GtkWidget * widget, GtkDateEntry * dateentry);
-static gint key_press_popup (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
-static gint gtk_dateentry_button_press (GtkWidget * widget, GdkEvent * event, gpointer data);
-
-static void gtk_dateentry_entry_set_text(GtkDateEntry * dateentry);
 
-/*
-static void
-gtk_dateentry_set_property (GObject         *object,
-                        guint            prop_id,
-                        const GValue    *value,
-                        GParamSpec      *pspec);
+static guint dateentry_signals[LAST_SIGNAL] = {0,};
 
-static void
-gtk_dateentry_get_property (GObject         *object,
-                        guint            prop_id,
-                        GValue          *value,
-                        GParamSpec      *pspec);
-*/
 
-static GtkHBoxClass *parent_class = NULL;
-static guint dateentry_signals[LAST_SIGNAL] = {0,};
+G_DEFINE_TYPE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX)
 
 
 // todo:finish this
@@ -103,13 +72,13 @@ typedef struct _GDateParseTokens GDateParseTokens;
 #define NUM_LEN 10
 
 static void
-g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
+hb_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
 {
   gchar num[4][NUM_LEN+1];
   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.
@@ -146,450 +115,23 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
 
 }
 
-static void g_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);
-      
-      g_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 76:
-              //using_twodigit_years = TRUE; /* FALL THRU */
-            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]) );   
-}        
-        
-
-//end 
-
-
-GType
-gtk_dateentry_get_type ()
-{
-static GType dateentry_type = 0;
-
-       //DB( g_print("\n[dateentry] get_type\n") );
-
-       if (!dateentry_type)
-    {
-               static const GTypeInfo dateentry_info =
-               {
-               sizeof (GtkDateEntryClass),
-               NULL,           /* base_init */
-               NULL,           /* base_finalize */
-               (GClassInitFunc) gtk_dateentry_class_init,
-               NULL,           /* class_finalize */
-               NULL,           /* class_data */
-               sizeof (GtkDateEntry),
-               0,              /* n_preallocs */
-               (GInstanceInitFunc) gtk_dateentry_init,
-               NULL
-               };
-
-               //dateentry_type = gtk_type_unique (gtk_hbox_get_type (), &dateentry_info);
-
-               dateentry_type = g_type_register_static (GTK_TYPE_HBOX, "GtkDateEntry",
-                                                        &dateentry_info, 0);
-
-
-       }
-       return dateentry_type;
-}
-
-static void
-gtk_dateentry_class_init (GtkDateEntryClass * klass)
-{
-  //GObjectClass *gobject_class;
-  GtkObjectClass *object_class;
-  //GtkWidgetClass *widget_class;
-
-  //gobject_class = (GObjectClass*) klass;
-  object_class = (GtkObjectClass*) klass;
-  //widget_class = (GtkWidgetClass*) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-       DB( g_print("\n[dateentry] class_init\n") );
-
-
-       object_class->destroy = gtk_dateentry_destroy;
-
-  dateentry_signals[CHANGED] =
-    g_signal_new ("changed",
-                  G_OBJECT_CLASS_TYPE (klass),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkDateEntryClass, changed),
-                  NULL, NULL,
-                  g_cclosure_marshal_VOID__VOID,
-                  G_TYPE_NONE, 0);
-
-       g_date_determine_dmy();
-
- /*
-       gobject_class->set_property = gtk_dateentry_set_property;
-       gobject_class->get_property = gtk_dateentry_get_property;
-
-       g_object_class_install_property (gobject_class,
-                       PROPERTY_DATE,
-                       g_param_spec_uint(      "date",
-                                                               "Date",
-                                                           "The date currently selected",
-                                                           0, G_MAXUINT,
-                                                           0,
-                                                           (G_PARAM_READABLE | G_PARAM_WRITABLE)
-                                                          )
-                       );
-       */
-}
-
-static gboolean gtk_dateentry_focus(GtkWidget     *widget,
-                                                        GdkEventFocus *event,
-                                                        gpointer       user_data)
-{
-GtkDateEntry *dateentry = user_data;
-
-       DB( g_print("\n[dateentry] focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry))) );
-
-       gtk_dateentry_entry_parse(GTK_WIDGET(dateentry), dateentry);
-
-       return FALSE;
-}
-
-static void
-gtk_dateentry_init (GtkDateEntry *dateentry)
-{
-GtkWidget *widget;
-GtkWidget *arrow;
-
-       DB( g_print("\n[dateentry] init\n") );
-
-       /* initialize datas */
-       dateentry->date = g_date_new();
-
-       g_date_set_time_t(dateentry->date, time(NULL));
-
-       g_date_set_dmy(&dateentry->mindate, 1, 1, 1900);
-       g_date_set_dmy(&dateentry->maxdate, 31, 12, 2200);
-
-
-       widget=GTK_WIDGET(dateentry);
-       gtk_box_set_homogeneous(GTK_BOX(widget), FALSE);
-       
-       dateentry->entry = gtk_entry_new ();
-       gtk_widget_set_size_request(dateentry->entry, 90, -1);
-       gtk_box_pack_start (GTK_BOX (dateentry), dateentry->entry, TRUE, TRUE, 0);
-
-       dateentry->arrow = gtk_toggle_button_new ();
-       arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
-       gtk_container_add (GTK_CONTAINER (dateentry->arrow), arrow);
-       gtk_box_pack_end (GTK_BOX (dateentry), dateentry->arrow, FALSE, FALSE, 0);
-
-       gtk_widget_show (dateentry->entry);
-       gtk_widget_show (dateentry->arrow);
-
-
-    /* our popup window */
-       dateentry->popwin = gtk_window_new (GTK_WINDOW_POPUP);
-       gtk_widget_set_events (dateentry->popwin,
-                               gtk_widget_get_events(dateentry->popwin) | GDK_KEY_PRESS_MASK);
-
-       dateentry->frame = gtk_frame_new (NULL);
-       gtk_container_add (GTK_CONTAINER (dateentry->popwin), dateentry->frame);
-       gtk_frame_set_shadow_type (GTK_FRAME (dateentry->frame), GTK_SHADOW_OUT);
-       gtk_widget_show (dateentry->frame);
-
-       dateentry->calendar = gtk_calendar_new ();
-       gtk_container_add (GTK_CONTAINER (dateentry->frame), dateentry->calendar);
-       gtk_widget_show (dateentry->calendar);
-
-       // dateentry signals
-       g_signal_connect (GTK_OBJECT (dateentry->entry), "activate",
-                               G_CALLBACK (gtk_dateentry_entry_parse), dateentry);
-
-       g_signal_connect (GTK_OBJECT (dateentry->entry), "focus-out-event",
-                               G_CALLBACK (gtk_dateentry_focus), dateentry);
-
-
-       g_signal_connect (GTK_OBJECT (dateentry->entry), "key_press_event",
-                               G_CALLBACK (gtk_dateentry_entry_key), dateentry);
-
-       // arrow/popwin signals
-       g_signal_connect (GTK_OBJECT (dateentry->arrow), "toggled",
-                               G_CALLBACK (gtk_dateentry_arrow_press), dateentry);
-
-       g_signal_connect (GTK_OBJECT (dateentry->popwin), "key_press_event",
-                               G_CALLBACK (key_press_popup), dateentry);
-
-       g_signal_connect (GTK_OBJECT (dateentry->popwin), "button_press_event",
-                               G_CALLBACK (gtk_dateentry_button_press), dateentry);
-
-       // calendar signals
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "prev-year",
-                               G_CALLBACK (gtk_dateentry_calendar_year), dateentry);
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "next-year",
-                               G_CALLBACK (gtk_dateentry_calendar_year), dateentry);
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "prev-month",
-                               G_CALLBACK (gtk_dateentry_calendar_year), dateentry);
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "next-month",
-                               G_CALLBACK (gtk_dateentry_calendar_year), dateentry);
-
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "day-selected",
-                               G_CALLBACK (gtk_dateentry_calendar_getfrom), dateentry);
-
-       g_signal_connect (GTK_OBJECT (dateentry->calendar), "day-selected-double-click",
-                               G_CALLBACK (gtk_dateentry_calendar_select), dateentry);
-
-       //gtk_dateentry_calendar_getfrom(NULL, dateentry);
-}
-
-
-GtkWidget *gtk_dateentry_new ()
-{
-GtkDateEntry *dateentry;
-
-       DB( g_print("\n[dateentry] new\n") );
-
-       dateentry = g_object_new (GTK_TYPE_DATE_ENTRY, NULL);
-
-       return GTK_WIDGET(dateentry);
-}
-
-
-static void gtk_dateentry_destroy (GtkObject * object)
-{
-GtkDateEntry *dateentry;
-
-       DB( g_print(" \n[dateentry] destroy\n") );
-
-       g_return_if_fail (GTK_IS_DATE_ENTRY (object));
-
-       dateentry = GTK_DATE_ENTRY (object);
-
-       DB( g_print(" free gtkentry: %p\n", dateentry->entry) );
-       DB( g_print(" free arrow: %p\n", dateentry->arrow) );
-       DB( g_print(" free popwin: %p\n", dateentry->popwin) );
-
-       DB( g_print(" free dateentry: %p\n", dateentry) );
-
-       if(dateentry->popwin)
-               gtk_widget_destroy (dateentry->popwin);
-       dateentry->popwin = NULL;
-
-       if(dateentry->date)
-               g_date_free(dateentry->date);
-       dateentry->date = NULL;
-
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-/*
-**
-*/
-void gtk_dateentry_set_date(GtkDateEntry *dateentry, guint32 julian_days)
-{
-       DB( g_print(" \n[dateentry] set date\n") );
-
-       g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
-
-       if(g_date_valid_julian(julian_days))
-       {
-               g_date_set_julian (dateentry->date, julian_days);
-       }
-       else
-       {
-               g_date_set_time_t(dateentry->date, time(NULL));
-       }
-       gtk_dateentry_entry_set_text(dateentry);
-}
-
-/*
-**
-*/
-void gtk_dateentry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days)
-{
-       DB( g_print(" \n[dateentry] set date\n") );
-
-       g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
-
-       if(g_date_valid_julian(julian_days))
-       {
-               g_date_set_julian (&dateentry->mindate, julian_days);
-       }
-}
-
-
-/*
-**
-*/
-void gtk_dateentry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days)
-{
-       DB( g_print(" \n[dateentry] set date\n") );
-
-       g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
-
-       if(g_date_valid_julian(julian_days))
-       {
-               g_date_set_julian (&dateentry->maxdate, julian_days);
-       }
-}
-
-
-/*
-**
-*/
-guint32 gtk_dateentry_get_date(GtkDateEntry * dateentry)
-{
-       DB( g_print(" \n[dateentry] get date\n") );
-
-       g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
-
-       return(g_date_get_julian(dateentry->date));
-}
-
-
-/*
-static void
-gtk_dateentry_set_property (GObject         *object,
-                        guint            prop_id,
-                        const GValue    *value,
-                        GParamSpec      *pspec)
-{
-GtkDateEntry *dateentry = GTK_DATE_ENTRY (object);
-
-       DB( g_print("\n[dateentry] set %d\n", prop_id) );
-
-
-  switch (prop_id)
-    {
-       case PROPERTY_DATE:
-          DB( g_print(" -> date to %d\n", g_value_get_uint (value)) );
-
-               g_date_set_julian (dateentry->date, g_value_get_uint (value));
-               gtk_dateentry_entry_set_text(dateentry);
-       break;
-
-
-    default:
-      //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-gtk_dateentry_get_property (GObject         *object,
-                        guint            prop_id,
-                        GValue          *value,
-                        GParamSpec      *pspec)
-{
-GtkDateEntry *dateentry = GTK_DATE_ENTRY (object);
-
-       DB( g_print("\n[dateentry] get\n") );
-
-  switch (prop_id)
-    {
-       case PROPERTY_DATE:
-          DB( g_print(" -> date is %d\n", 0) );
-               g_value_set_uint (value, g_date_get_julian(dateentry->date));
-               break;
-
-    default:
-      //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-*/
-
-
-/*
-** fill in our gtkentry from our GDate
-*/
-static void gtk_dateentry_entry_set_text(GtkDateEntry * dateentry)
-{
-gchar buffer[256];
-
-       DB( g_print("\n[dateentry] date2entry\n") );
-
-       g_date_clamp(dateentry->date, &dateentry->mindate, &dateentry->maxdate);
-
-       
-       if(g_date_valid(dateentry->date) == TRUE)
-       {
-               g_date_strftime (buffer, 256 - 1, "%x", dateentry->date);
-               gtk_entry_set_text (GTK_ENTRY (dateentry->entry), buffer);
-               
-               DB( g_print(" = %s\n", buffer) );
-       }
-       else
-               gtk_entry_set_text (GTK_ENTRY (dateentry->entry), "??");
-
-
-       /* emit the signal */
-       if(dateentry->lastdate != g_date_get_julian(dateentry->date))
-       {
-               DB( g_print(" **emit 'changed' signal**\n") );
-
-               g_signal_emit_by_name (dateentry, "changed", NULL, NULL);
-       }
-
-       dateentry->lastdate = g_date_get_julian(dateentry->date);
-
-}
-
 
-static void gtk_dateentry_tokens(GtkWidget *gtkentry, gpointer user_data)
+static void hb_date_parse_tokens(GDate *date, const gchar *str)
 {
-GtkDateEntry *dateentry = user_data;
-const gchar *str;
 GDateParseTokens pt;
 
-       str = gtk_entry_get_text (GTK_ENTRY (dateentry->entry));
-
-       g_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]) );
+       hb_date_fill_parse_tokens(str, &pt);
+       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(dateentry->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(dateentry->date, pt.n[0]);
+                               g_date_set_day(date, pt.n[0]);
                        break;
                case 2:
                        DB( g_print(" -> seizured 2 numbers\n") );
@@ -598,107 +140,136 @@ GDateParseTokens pt;
                                if( dmy_order[0] == G_DATE_DAY )
                                {
                                        if(g_date_valid_day(pt.n[0]))
-                                           g_date_set_day(dateentry->date, pt.n[0]);
+                                           g_date_set_day(date, pt.n[0]);
                                        if(g_date_valid_month(pt.n[1]))
-                                               g_date_set_month(dateentry->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(dateentry->date, pt.n[1]);
+                                           g_date_set_day(date, pt.n[1]);
                                        if(g_date_valid_month(pt.n[0]))
-                                               g_date_set_month(dateentry->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") );
+
+       //%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
+eval_date(GtkDateEntry *self)
+{
+GtkDateEntryPrivate *priv = self->priv;
+
+       g_date_clamp(priv->date, &priv->mindate, &priv->maxdate);
+       
+       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);
+}
 
 
-/*
-** parse the gtkentry and store the GDate
-*/
-static void gtk_dateentry_entry_parse(GtkWidget *gtkentry, 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_parse\n") );
-
-       str = gtk_entry_get_text (GTK_ENTRY (dateentry->entry));
+       str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
 
        //1) we parse the string according to the locale
-       g_date_set_parse (dateentry->date, str);
-       if(g_date_valid(dateentry->date) == FALSE)
+       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
-               gtk_dateentry_tokens(gtkentry, user_data);
+               hb_date_parse_tokens(priv->date, str);
        }
 
        //3) at last if date still invalid, put today's dateentry_signals
        // we should consider just warn the user here
-       if(g_date_valid(dateentry->date) == FALSE)
+       if(!g_date_valid(priv->date))
        {
-               /* today's date */
-               g_date_set_time_t(dateentry->date, time(NULL));
+               g_date_set_time_t(priv->date, time(NULL));
        }
-
-       gtk_dateentry_entry_set_text(dateentry);
-
+       eval_date(self);
 }
 
-static void gtk_dateentry_calendar_year(GtkWidget *calendar, GtkDateEntry *dateentry)
+
+static void
+gtk_date_entry_cb_calendar_day_selected(GtkWidget * calendar, GtkDateEntry * dateentry)
 {
+GtkDateEntryPrivate *priv = dateentry->priv;
 guint year, month, day;
 
-       DB( g_print(" (dateentry) year changed\n") );
-
-       gtk_calendar_get_date (GTK_CALENDAR (dateentry->calendar), &year, &month, &day);
-       if( year < 1900)
-               g_object_set(calendar, "year", 1900, NULL);
+       DB( g_print("\n[dateentry] calendar_day_selected\n") );
 
-       if( year > 2200)
-               g_object_set(calendar, "year", 2200, NULL);
-       
+       gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
+       g_date_set_dmy (priv->date, day, month + 1, year);
+       eval_date(dateentry);   
 }
 
-/*
-** store the calendar date to GDate, update our gtkentry
-*/
-static void gtk_dateentry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry)
+
+static gint
+gtk_date_entry_cb_calendar_day_select_double_click(GtkWidget * calendar, gpointer user_data)
 {
-guint year, month, day;
+GtkDateEntry *dateentry = user_data;
+GtkDateEntryPrivate *priv = dateentry->priv;
+
+       DB( g_print("\n[dateentry] calendar_day_select_double_click\n") );
 
-       DB( g_print(" (dateentry) get from calendar\n") );
+       gtk_widget_hide (priv->popover);        
 
-       gtk_calendar_get_date (GTK_CALENDAR (dateentry->calendar), &year, &month, &day);
-       g_date_set_dmy (dateentry->date, day, month + 1, year);
-       gtk_dateentry_entry_set_text(dateentry);
+       return FALSE;
 }
 
 
-static gint gtk_dateentry_calendar_select(GtkWidget * calendar, gpointer user_data)
+static void 
+gtk_date_entry_cb_calendar_monthyear(GtkWidget *calendar, GtkDateEntry *dateentry)
 {
-GtkDateEntry *dateentry = user_data;
+GtkDateEntryPrivate *priv = dateentry->priv;
+guint year, month, day;
 
-       DB( g_print(" (dateentry) calendar_select\n") );
+       DB( g_print("\n[dateentry] cb_calendar_monthyear\n") );
 
-       gtk_dateentry_hide_popdown_window(dateentry);
-       gtk_dateentry_calendar_getfrom(NULL, dateentry);
-       return FALSE;
+       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);
+       
 }
 
 
 static gint
-gtk_dateentry_entry_key (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+gtk_date_entry_cb_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) );
 
@@ -706,20 +277,20 @@ GtkDateEntry *dateentry = user_data;
        {
                if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
                {
-                       g_date_add_days (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_add_days (priv->date, 1);
+                       eval_date(dateentry);
                }
                else
                if( event->state & GDK_SHIFT_MASK )
                {
-                       g_date_add_months (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_add_months (priv->date, 1);
+                       eval_date(dateentry);
                }
                else
                if( event->state & GDK_CONTROL_MASK )
                {
-                       g_date_add_years (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_add_years (priv->date, 1);
+                       eval_date(dateentry);
                }
                return TRUE;
        }
@@ -728,20 +299,20 @@ GtkDateEntry *dateentry = user_data;
        {
                if( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) )
                {
-                       g_date_subtract_days (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_subtract_days (priv->date, 1);
+                       eval_date(dateentry);
                }
                else
                if( event->state & GDK_SHIFT_MASK )
                {
-                       g_date_subtract_months (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_subtract_months (priv->date, 1);
+                       eval_date(dateentry);
                }
                else
                if( event->state & GDK_CONTROL_MASK )
                {
-                       g_date_subtract_years (dateentry->date, 1);
-                       gtk_dateentry_entry_set_text(dateentry);
+                       g_date_subtract_years (priv->date, 1);
+                       eval_date(dateentry);
                }
                return TRUE;
        }
@@ -751,167 +322,317 @@ GtkDateEntry *dateentry = user_data;
 
 
 static void
-position_popup (GtkDateEntry * dateentry)
+gtk_date_entry_cb_entry_activate(GtkWidget *gtkentry, gpointer user_data)
 {
-gint x, y;
-gint bwidth, bheight;
-GtkRequisition req;
-GdkWindow *gdkwindow;
-GtkAllocation allocation;
+GtkDateEntry *dateentry = user_data;
+
+       DB( g_print("\n[dateentry] entry_activate\n") );
+
+       parse_date(dateentry);
+       eval_date(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;
+}
+
+
+static void
+gtk_date_entry_cb_button_clicked (GtkWidget * widget, GtkDateEntry * dateentry)
+{
+GtkDateEntryPrivate *priv = dateentry->priv;
+//GdkRectangle rect;
+int month;
 
-       DB( g_print("\n[dateentry] position popup\n") );
+       DB( g_print("\n[dateentry] button_clicked\n") );
 
-       gtk_widget_size_request (dateentry->popwin, &req);
+       /* 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);
+}
+
+
+static void 
+gtk_date_entry_destroy (GtkWidget *object)
+{
+GtkDateEntry *dateentry = GTK_DATE_ENTRY (object);
+GtkDateEntryPrivate *priv = dateentry->priv;
 
-       gdkwindow = gtk_widget_get_window(dateentry->arrow);
-       gdk_window_get_origin (gdkwindow, &x, &y);
+       g_return_if_fail(object != NULL);
+       g_return_if_fail(GTK_IS_DATE_ENTRY(object));
 
-       gtk_widget_get_allocation(dateentry->arrow, &allocation);
-       x += allocation.x;
-       y += allocation.y;
-       bwidth = allocation.width;
-       bheight = allocation.height;
+       DB( g_print("\n[dateentry] destroy\n") );
 
-       x += bwidth - req.width;
-       y += bheight;
+       DB( g_print(" free gtkentry: %p\n", priv->entry) );
+       DB( g_print(" free arrow: %p\n", priv->button) );
 
-       if (x < 0)
-               x = 0;
+       DB( g_print(" free dateentry: %p\n", dateentry) );
 
-       if (y < 0)
-               y = 0;
+       if(priv->date)
+               g_date_free(priv->date);
+       priv->date = NULL;
 
-       gtk_window_move (GTK_WINDOW (dateentry->popwin), x, y);
+       GTK_WIDGET_CLASS (gtk_date_entry_parent_class)->destroy (object);
 }
 
 
 
 static void
-gtk_dateentry_popup_display (GtkDateEntry * dateentry)
+gtk_date_entry_dispose (GObject *gobject)
 {
-const char *str;
-int month;
+//GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
 
-  //gint height, width, x, y;
-  //gint old_width, old_height;
+       DB( g_print("\n[dateentry] dispose\n") );
 
-       DB( g_print("\n[dateentry] popup_display\n****\n\n") );
+       
+  //g_clear_object (&self->priv->an_object);
 
-  //old_width = dateentry->popwin->allocation.width;
-  //old_height  = dateentry->popwin->allocation.height;
+  G_OBJECT_CLASS (gtk_date_entry_parent_class)->dispose (gobject);
+}
 
 
-/* update */
-       str = gtk_entry_get_text (GTK_ENTRY (dateentry->entry));
-       g_date_set_parse (dateentry->date, str);
 
-       if(g_date_valid(dateentry->date) == TRUE)
-       {
-               /* GtkCalendar expects month to be in 0-11 range (inclusive) */
-               month = g_date_get_month (dateentry->date) - 1;
-               gtk_calendar_select_month (GTK_CALENDAR (dateentry->calendar),
-                                  CLAMP (month, 0, 11),
-                                  g_date_get_year (dateentry->date));
-        gtk_calendar_select_day (GTK_CALENDAR (dateentry->calendar),
-                                g_date_get_day (dateentry->date));
-       }
 
-       position_popup(dateentry);
+static void
+gtk_date_entry_finalize (GObject *gobject)
+{
+//GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
 
-       gtk_widget_show (dateentry->popwin);
+       DB( g_print("\n[dateentry] finalize\n") );
 
-  gtk_grab_add (dateentry->popwin);
+       
+       //g_date_free(self->date);
+  //g_free (self->priv->a_string);
 
-  // this close the popup */
-       GdkWindow *gdkwindow;
-       gdkwindow = gtk_widget_get_window(dateentry->popwin);
+  /* Always chain up to the parent class; as with dispose(), finalize()
+   * is guaranteed to exist on the parent's class virtual function table
+   */
+  G_OBJECT_CLASS(gtk_date_entry_parent_class)->finalize (gobject);
+}
 
-  gdk_pointer_grab (gdkwindow, TRUE,
-                   GDK_BUTTON_PRESS_MASK |
-                   GDK_BUTTON_RELEASE_MASK |
-                   GDK_POINTER_MOTION_MASK,
-                   NULL, NULL, GDK_CURRENT_TIME);
 
-}
 
 static void
-gtk_dateentry_hide_popdown_window(GtkDateEntry *dateentry)
+gtk_date_entry_class_init (GtkDateEntryClass *class)
 {
-       DB( g_print("\n[dateentry] hide_popdown_window\n") );
+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;
 
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dateentry->arrow), FALSE);
+       widget_class->destroy  = gtk_date_entry_destroy;
+       
+       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);
 
-  gtk_grab_remove(dateentry->popwin);
-  gdk_pointer_ungrab(GDK_CURRENT_TIME);
-  gtk_widget_hide(dateentry->popwin);
+       g_type_class_add_private (object_class, sizeof (GtkDateEntryPrivate));
+       
 }
 
-static gint
-gtk_dateentry_arrow_press (GtkWidget * widget, GtkDateEntry * dateentry)
+static void
+gtk_date_entry_init (GtkDateEntry *dateentry)
 {
-  GtkToggleButton *button;
+GtkDateEntryPrivate *priv;
+
+       DB( g_print("\n[dateentry] init\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_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry)), GTK_STYLE_CLASS_LINKED);
+
+       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);
+
+       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);
+
+       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);
+       
+       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);
+
+
+       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);
 
-       DB( g_print("\n[dateentry] arrow_press\n") );
 
-  button = GTK_TOGGLE_BUTTON(widget);
+       g_signal_connect (priv->button, "clicked",
+                               G_CALLBACK (gtk_date_entry_cb_button_clicked), dateentry);
 
-  if(!gtk_toggle_button_get_active(button)){
-     gtk_widget_hide (dateentry->popwin);
-     gtk_grab_remove (dateentry->popwin);
-     gdk_pointer_ungrab (GDK_CURRENT_TIME);
 
-       gtk_dateentry_calendar_getfrom(NULL, dateentry);
-     return TRUE;
-  }
+       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);
+
+       priv->hid_dayselect = g_signal_connect (priv->calendar, "day-selected",
+                               G_CALLBACK (gtk_date_entry_cb_calendar_day_selected), dateentry);
+
+       g_signal_connect (priv->calendar, "day-selected-double-click",
+                               G_CALLBACK (gtk_date_entry_cb_calendar_day_select_double_click), dateentry);
 
-  gtk_dateentry_popup_display(dateentry);
-  return TRUE;
 }
 
-static gint
-key_press_popup (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+
+GtkWidget *
+gtk_date_entry_new ()
 {
-GtkDateEntry *dateentry = user_data;
+GtkDateEntry *dateentry;
 
+       DB( g_print("\n[dateentry] new\n") );
 
-       DB( g_print("\n[dateentry] key pressed%d\n", event->keyval) );
+       dateentry = g_object_new (GTK_TYPE_DATE_ENTRY, NULL);
 
-       if (event->keyval != GDK_KEY_Escape)
-               return FALSE;
+       return GTK_WIDGET(dateentry);
+}
 
-       g_signal_stop_emission_by_name (widget, "key_press_event");
 
-       gtk_dateentry_hide_popdown_window(dateentry);
+/*
+**
+*/
+void 
+gtk_date_entry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days)
+{
+GtkDateEntryPrivate *priv = dateentry->priv;
+       
+       DB( g_print("\n[dateentry] set mindate\n") );
 
+       g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
 
-       return TRUE;
+       if(g_date_valid_julian(julian_days))
+       {
+               g_date_set_julian (&priv->mindate, julian_days);
+       }
 }
 
 
-static gint
-gtk_dateentry_button_press (GtkWidget * widget, GdkEvent * event, gpointer user_data)
+/*
+**
+*/
+void 
+gtk_date_entry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days)
 {
-GtkWidget *child;
+GtkDateEntryPrivate *priv = dateentry->priv;
+       
+       DB( g_print("\n[dateentry] set maxdate\n") );
 
-DB( g_print("\n[dateentry] button_press\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);
+       }
+}
 
-       child = gtk_get_event_widget (event);
 
-       if (child != widget)
+/*
+**
+*/
+void
+gtk_date_entry_set_date(GtkDateEntry *dateentry, guint32 julian_days)
+{
+GtkDateEntryPrivate *priv = dateentry->priv;
+
+       DB( g_print("\n[dateentry] set date\n") );
+
+       g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
+
+       if(g_date_valid_julian(julian_days))
        {
-               while (child)
-               {
-                       if (child == widget)
-                               return FALSE;
-                       child = gtk_widget_get_parent(child);
-               }
+               g_date_set_julian (priv->date, julian_days);
        }
+       else
+       {
+               g_date_set_time_t(priv->date, time(NULL));
+       }
+       eval_date(dateentry);
+}
 
-       gtk_widget_hide (widget);
-       gtk_grab_remove (widget);
-       gdk_pointer_ungrab (GDK_CURRENT_TIME);
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(GTK_DATE_ENTRY(user_data)->arrow), FALSE);
 
-       return TRUE;
+/*
+**
+*/
+guint32
+gtk_date_entry_get_date(GtkDateEntry *dateentry)
+{
+GtkDateEntryPrivate *priv = dateentry->priv;
+       
+       DB( g_print("\n[dateentry] get date\n") );
+
+       g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
+
+       return(g_date_get_julian(priv->date));
 }
 
This page took 0.048464 seconds and 4 git commands to generate.