X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fhomebank;a=blobdiff_plain;f=src%2Fgtk-dateentry.c;fp=src%2Fgtk-dateentry.c;h=519793decf93fa1c2679791154bfaa8ea0d7fa01;hp=ea61280a5e00e8fbe59b956a7c76b5c15bd1701f;hb=59c5e08a64798d4303ae7eb3a2713bc93d98fa7b;hpb=8988b3bef0760b4cab8144715cc3d8f55688861c diff --git a/src/gtk-dateentry.c b/src/gtk-dateentry.c index ea61280..519793d 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-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@ -43,43 +43,30 @@ 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_date_entry_dispose (GObject *gobject); +static void gtk_date_entry_finalize (GObject *gobject); +static void gtk_date_entry_destroy (GtkWidget *dateentry); -/* -static void -gtk_dateentry_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); +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_dateentry_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -*/ +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 GtkHBoxClass *parent_class = NULL; static guint dateentry_signals[LAST_SIGNAL] = {0,}; @@ -103,7 +90,7 @@ 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; @@ -146,236 +133,253 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt) } -static void g_date_determine_dmy(void) + +/* +static void hb_date_determine_dmy(void) { GDate d; gchar buf[128]; GDateParseTokens testpt; gint i; - DB( g_print("\n[dateentry] determine dmy\n") ); + 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_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; - } + hb_date_fill_parse_tokens (buf, &testpt); - 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]) ); -} - + 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; + } -//end + 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]) ); +}*/ -GType -gtk_dateentry_get_type () +static void hb_date_parse_tokens(GtkWidget *gtkentry, gpointer user_data) { -static GType dateentry_type = 0; - - //DB( g_print("\n[dateentry] get_type\n") ); +GtkDateEntry *dateentry = user_data; +GtkDateEntryPrivate *priv = dateentry->priv; +const gchar *str; +GDateParseTokens pt; - 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 - }; + str = gtk_entry_get_text (GTK_ENTRY (priv->entry)); - //dateentry_type = gtk_type_unique (gtk_hbox_get_type (), &dateentry_info); + 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]) ); - dateentry_type = g_type_register_static (GTK_TYPE_HBOX, "GtkDateEntry", - &dateentry_info, 0); + // initialize with today's date + g_date_set_time_t(priv->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]); + break; + case 2: + DB( g_print(" -> seizured 2 numbers\n") ); + if( dmy_order[0] != G_DATE_YEAR ) + { + if( dmy_order[0] == G_DATE_DAY ) + { + if(g_date_valid_day(pt.n[0])) + g_date_set_day(priv->date, pt.n[0]); + if(g_date_valid_month(pt.n[1])) + g_date_set_month(priv->date, pt.n[1]); + } + else + { + if(g_date_valid_day(pt.n[1])) + g_date_set_day(priv->date, pt.n[1]); + if(g_date_valid_month(pt.n[0])) + g_date_set_month(priv->date, pt.n[0]); + } + } + break; + } - } - return dateentry_type; + } + + + + +//end + + +G_DEFINE_TYPE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX) + + + static void -gtk_dateentry_class_init (GtkDateEntryClass * klass) +gtk_date_entry_class_init (GtkDateEntryClass *class) { - //GObjectClass *gobject_class; - GtkObjectClass *object_class; - //GtkWidgetClass *widget_class; - - //gobject_class = (GObjectClass*) klass; - object_class = (GtkObjectClass*) klass; - //widget_class = (GtkWidgetClass*) klass; +GObjectClass *object_class; +GtkWidgetClass *widget_class; - parent_class = g_type_class_peek_parent (klass); + 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; - object_class->destroy = gtk_dateentry_destroy; - - dateentry_signals[CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (klass), + 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); - 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) - ) - ); - */ + g_type_class_add_private (object_class, sizeof (GtkDateEntryPrivate)); + } -static gboolean gtk_dateentry_focus(GtkWidget *widget, - GdkEventFocus *event, - gpointer user_data) + +static gboolean +gtk_date_entry_entry_focus_out(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))) ); + DB( g_print("\n[dateentry] entry focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry))) ); - gtk_dateentry_entry_parse(GTK_WIDGET(dateentry), dateentry); + gtk_date_entry_entry_activate(GTK_WIDGET(dateentry), dateentry); return FALSE; } static void -gtk_dateentry_init (GtkDateEntry *dateentry) +gtk_date_entry_init (GtkDateEntry *dateentry) { -GtkWidget *widget; -GtkWidget *arrow; +GtkDateEntryPrivate *priv; DB( g_print("\n[dateentry] init\n") ); - /* initialize datas */ - dateentry->date = g_date_new(); + /* 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; - g_date_set_time_t(dateentry->date, time(NULL)); + + /* initialize datas */ + priv->date = g_date_new(); + priv->device = NULL; + priv->popup_in_progress = FALSE; + priv->has_grab = FALSE; - g_date_set_dmy(&dateentry->mindate, 1, 1, 1900); - g_date_set_dmy(&dateentry->maxdate, 31, 12, 2200); + g_date_set_time_t(priv->date, time(NULL)); + g_date_set_dmy(&priv->mindate, 1, 1, 1900); + g_date_set_dmy(&priv->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_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry)), GTK_STYLE_CLASS_LINKED); - gtk_widget_show (dateentry->entry); - gtk_widget_show (dateentry->arrow); + //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); - /* 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); + g_signal_connect_after (priv->entry, "focus-out-event", + G_CALLBACK (gtk_date_entry_entry_focus_out), dateentry); - 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); + g_signal_connect (priv->entry, "activate", + G_CALLBACK (gtk_date_entry_entry_activate), dateentry); - dateentry->calendar = gtk_calendar_new (); - gtk_container_add (GTK_CONTAINER (dateentry->frame), dateentry->calendar); - gtk_widget_show (dateentry->calendar); + + 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); - // dateentry signals - g_signal_connect (GTK_OBJECT (dateentry->entry), "activate", - G_CALLBACK (gtk_dateentry_entry_parse), dateentry); + g_signal_connect (priv->button, "clicked", + G_CALLBACK (gtk_date_entry_button_clicked), dateentry); - g_signal_connect (GTK_OBJECT (dateentry->entry), "focus-out-event", - G_CALLBACK (gtk_dateentry_focus), dateentry); + 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); - g_signal_connect (GTK_OBJECT (dateentry->entry), "key_press_event", - G_CALLBACK (gtk_dateentry_entry_key), dateentry); + 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); - // arrow/popwin signals - g_signal_connect (GTK_OBJECT (dateentry->arrow), "toggled", - G_CALLBACK (gtk_dateentry_arrow_press), dateentry); + g_signal_connect (priv->popup_window, "key-press-event", + G_CALLBACK (gtk_date_entry_popup_key_event), dateentry); - g_signal_connect (GTK_OBJECT (dateentry->popwin), "key_press_event", - G_CALLBACK (key_press_popup), dateentry); + g_signal_connect (priv->popup_window, "button-press-event", + G_CALLBACK (gtk_date_entry_popup_button_press), dateentry); - g_signal_connect (GTK_OBJECT (dateentry->popwin), "button_press_event", - G_CALLBACK (gtk_dateentry_button_press), dateentry); + + priv->calendar = gtk_calendar_new (); + gtk_container_add (GTK_CONTAINER (priv->frame), priv->calendar); + gtk_widget_show (priv->calendar); - // 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 (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); - g_signal_connect (GTK_OBJECT (dateentry->calendar), "day-selected", - G_CALLBACK (gtk_dateentry_calendar_getfrom), dateentry); + g_signal_connect (priv->calendar, "day-selected", + G_CALLBACK (gtk_date_entry_calendar_getfrom), dateentry); - g_signal_connect (GTK_OBJECT (dateentry->calendar), "day-selected-double-click", - G_CALLBACK (gtk_dateentry_calendar_select), dateentry); + g_signal_connect (priv->calendar, "day-selected-double-click", + G_CALLBACK (gtk_date_entry_calendar_select), dateentry); - //gtk_dateentry_calendar_getfrom(NULL, dateentry); } -GtkWidget *gtk_dateentry_new () +GtkWidget * +gtk_date_entry_new () { GtkDateEntry *dateentry; @@ -387,65 +391,106 @@ GtkDateEntry *dateentry; } -static void gtk_dateentry_destroy (GtkObject * object) +static void +gtk_date_entry_destroy (GtkWidget *object) { -GtkDateEntry *dateentry; +GtkDateEntry *dateentry = GTK_DATE_ENTRY (object); +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") ); - g_return_if_fail (GTK_IS_DATE_ENTRY (object)); + 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) ); - dateentry = GTK_DATE_ENTRY (object); + if(priv->popup_window) + gtk_widget_destroy (priv->popup_window); + priv->popup_window = NULL; - 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) ); + if(priv->date) + g_date_free(priv->date); + priv->date = NULL; + + GTK_WIDGET_CLASS (gtk_date_entry_parent_class)->destroy (object); +} - 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; +static void +gtk_date_entry_dispose (GObject *gobject) +{ +//GtkDateEntry *self = GTK_DATE_ENTRY (gobject); - GTK_OBJECT_CLASS (parent_class)->destroy (object); + DB( g_print(" \n[dateentry] dispose\n") ); + + + //g_clear_object (&self->priv->an_object); + + G_OBJECT_CLASS (gtk_date_entry_parent_class)->dispose (gobject); } + + + +static void +gtk_date_entry_finalize (GObject *gobject) +{ +//GtkDateEntry *self = GTK_DATE_ENTRY (gobject); + + DB( g_print(" \n[dateentry] finalize\n") ); + + + //g_date_free(self->date); + //g_free (self->priv->a_string); + + /* 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); +} + + /* ** */ -void gtk_dateentry_set_date(GtkDateEntry *dateentry, guint32 julian_days) +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)) { - g_date_set_julian (dateentry->date, julian_days); + g_date_set_julian (priv->date, julian_days); } else { - g_date_set_time_t(dateentry->date, time(NULL)); + g_date_set_time_t(priv->date, time(NULL)); } - gtk_dateentry_entry_set_text(dateentry); + gtk_date_entry_entry_set_text(dateentry); } /* ** */ -void gtk_dateentry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days) +void gtk_date_entry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days) { - DB( g_print(" \n[dateentry] set date\n") ); +GtkDateEntryPrivate *priv = dateentry->priv; + + 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 (&dateentry->mindate, julian_days); + g_date_set_julian (&priv->mindate, julian_days); } } @@ -453,213 +498,109 @@ void gtk_dateentry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days) /* ** */ -void gtk_dateentry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days) +void gtk_date_entry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days) { - DB( g_print(" \n[dateentry] set date\n") ); +GtkDateEntryPrivate *priv = dateentry->priv; + + 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 (&dateentry->maxdate, julian_days); + g_date_set_julian (&priv->maxdate, julian_days); } } -/* -** -*/ -guint32 gtk_dateentry_get_date(GtkDateEntry * dateentry) +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(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; - } + return(g_date_get_julian(priv->date)); } - -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) +static void +gtk_date_entry_entry_set_text(GtkDateEntry * dateentry) { +GtkDateEntryPrivate *priv = dateentry->priv; gchar buffer[256]; - DB( g_print("\n[dateentry] date2entry\n") ); + DB( g_print("\n[dateentry] entry set text\n") ); - g_date_clamp(dateentry->date, &dateentry->mindate, &dateentry->maxdate); + g_date_clamp(priv->date, &priv->mindate, &priv->maxdate); - if(g_date_valid(dateentry->date) == TRUE) + if(g_date_valid(priv->date) == TRUE) { - g_date_strftime (buffer, 256 - 1, "%x", dateentry->date); - gtk_entry_set_text (GTK_ENTRY (dateentry->entry), buffer); + 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 (dateentry->entry), "??"); + gtk_entry_set_text (GTK_ENTRY (priv->entry), "??"); /* emit the signal */ - if(dateentry->lastdate != g_date_get_julian(dateentry->date)) + 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); } - dateentry->lastdate = g_date_get_julian(dateentry->date); - -} - - -static void gtk_dateentry_tokens(GtkWidget *gtkentry, gpointer user_data) -{ -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]) ); - - // initialize with today's date - g_date_set_time_t(dateentry->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]); - break; - case 2: - DB( g_print(" -> seizured 2 numbers\n") ); - if( dmy_order[0] != G_DATE_YEAR ) - { - if( dmy_order[0] == G_DATE_DAY ) - { - if(g_date_valid_day(pt.n[0])) - g_date_set_day(dateentry->date, pt.n[0]); - if(g_date_valid_month(pt.n[1])) - g_date_set_month(dateentry->date, pt.n[1]); - } - else - { - if(g_date_valid_day(pt.n[1])) - g_date_set_day(dateentry->date, pt.n[1]); - if(g_date_valid_month(pt.n[0])) - g_date_set_month(dateentry->date, pt.n[0]); - } - } - break; - } - + 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 +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_parse\n") ); + DB( g_print("\n[dateentry] entry_activate\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) == FALSE) { //2) give a try to tokens: day, day/month, month/day - gtk_dateentry_tokens(gtkentry, user_data); + hb_date_parse_tokens(gtkentry, user_data); } //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) == FALSE) { /* 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); + gtk_date_entry_entry_set_text(dateentry); } -static void gtk_dateentry_calendar_year(GtkWidget *calendar, GtkDateEntry *dateentry) + +static void +gtk_date_entry_calendar_year(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); + gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day); if( year < 1900) g_object_set(calendar, "year", 1900, NULL); @@ -668,37 +609,40 @@ guint year, month, day; } -/* -** store the calendar date to GDate, update our gtkentry -*/ -static void gtk_dateentry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry) + +static void +gtk_date_entry_calendar_getfrom(GtkWidget * calendar, GtkDateEntry * dateentry) { +GtkDateEntryPrivate *priv = dateentry->priv; guint year, month, day; - DB( g_print(" (dateentry) get from calendar\n") ); + DB( g_print(" (dateentry) calendar_getfrom\n") ); - 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); + 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_dateentry_calendar_select(GtkWidget * calendar, gpointer user_data) +static gint +gtk_date_entry_calendar_select(GtkWidget * calendar, gpointer user_data) { GtkDateEntry *dateentry = user_data; DB( g_print(" (dateentry) calendar_select\n") ); - gtk_dateentry_hide_popdown_window(dateentry); - gtk_dateentry_calendar_getfrom(NULL, dateentry); + gtk_date_entry_calendar_getfrom(NULL, dateentry); + + gtk_date_entry_popdown(dateentry); return FALSE; } static gint -gtk_dateentry_entry_key (GtkWidget *widget, GdkEventKey *event, gpointer user_data) +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) ); @@ -706,20 +650,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); + gtk_date_entry_entry_set_text(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); + gtk_date_entry_entry_set_text(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); + gtk_date_entry_entry_set_text(dateentry); } return TRUE; } @@ -728,20 +672,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); + gtk_date_entry_entry_set_text(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); + gtk_date_entry_entry_set_text(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); + gtk_date_entry_entry_set_text(dateentry); } return TRUE; } @@ -751,8 +695,9 @@ GtkDateEntry *dateentry = user_data; static void -position_popup (GtkDateEntry * dateentry) +gtk_date_entry_popup_position (GtkDateEntry * dateentry) { +GtkDateEntryPrivate *priv = dateentry->priv; gint x, y; gint bwidth, bheight; GtkRequisition req; @@ -761,12 +706,12 @@ GtkAllocation allocation; DB( g_print("\n[dateentry] position popup\n") ); - gtk_widget_size_request (dateentry->popwin, &req); + gtk_widget_get_preferred_size (priv->popup_window, NULL, &req); - gdkwindow = gtk_widget_get_window(dateentry->arrow); + gdkwindow = gtk_widget_get_window(priv->button); gdk_window_get_origin (gdkwindow, &x, &y); - gtk_widget_get_allocation(dateentry->arrow, &allocation); + gtk_widget_get_allocation(priv->button, &allocation); x += allocation.x; y += allocation.y; bwidth = allocation.width; @@ -781,136 +726,206 @@ GtkAllocation allocation; if (y < 0) y = 0; - gtk_window_move (GTK_WINDOW (dateentry->popwin), x, y); + 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_dateentry_popup_display (GtkDateEntry * dateentry) +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; - //gint height, width, x, y; - //gint old_width, old_height; DB( g_print("\n[dateentry] popup_display\n****\n\n") ); - //old_width = dateentry->popwin->allocation.width; - //old_height = dateentry->popwin->allocation.height; - - /* update */ - str = gtk_entry_get_text (GTK_ENTRY (dateentry->entry)); - g_date_set_parse (dateentry->date, str); + str = gtk_entry_get_text (GTK_ENTRY (priv->entry)); + g_date_set_parse (priv->date, str); - if(g_date_valid(dateentry->date) == TRUE) + if(g_date_valid(priv->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), + month = g_date_get_month (priv->date) - 1; + gtk_calendar_select_month (GTK_CALENDAR (priv->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)); + g_date_get_year (priv->date)); + gtk_calendar_select_day (GTK_CALENDAR (priv->calendar), + g_date_get_day (priv->date)); } - position_popup(dateentry); - gtk_widget_show (dateentry->popwin); + /* 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); - gtk_grab_add (dateentry->popwin); + window = gtk_widget_get_window (priv->popup_window); - // this close the popup */ - GdkWindow *gdkwindow; - gdkwindow = gtk_widget_get_window(dateentry->popwin); + g_return_if_fail (priv->grab_keyboard == NULL); + g_return_if_fail (priv->grab_pointer == NULL); - gdk_pointer_grab (gdkwindow, TRUE, - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK, - NULL, NULL, GDK_CURRENT_TIME); + event_device = gdk_event_get_device (event); + assoc_device = gdk_device_get_associated_device (event_device); -} + event_time = gdk_event_get_time (event); -static void -gtk_dateentry_hide_popdown_window(GtkDateEntry *dateentry) -{ - DB( g_print("\n[dateentry] hide_popdown_window\n") ); + 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; + } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dateentry->arrow), FALSE); + 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; + } + } + + gdk_window_focus (window, event_time); - gtk_grab_remove(dateentry->popwin); - gdk_pointer_ungrab(GDK_CURRENT_TIME); - gtk_widget_hide(dateentry->popwin); } -static gint -gtk_dateentry_arrow_press (GtkWidget * widget, GtkDateEntry * dateentry) + +static void +gtk_date_entry_popdown(GtkDateEntry *dateentry) { - GtkToggleButton *button; +GtkDateEntryPrivate *priv = dateentry->priv; - DB( g_print("\n[dateentry] arrow_press\n") ); + DB( g_print("\n[dateentry] popdown\n") ); - button = GTK_TOGGLE_BUTTON(widget); + gtk_widget_hide (priv->popup_window); + gtk_grab_remove (priv->popup_window); - if(!gtk_toggle_button_get_active(button)){ - gtk_widget_hide (dateentry->popwin); - gtk_grab_remove (dateentry->popwin); - gdk_pointer_ungrab (GDK_CURRENT_TIME); + if (priv->grab_keyboard != NULL) { + gdk_device_ungrab ( + priv->grab_keyboard, + GDK_CURRENT_TIME); + g_object_unref (priv->grab_keyboard); + priv->grab_keyboard = NULL; + } - gtk_dateentry_calendar_getfrom(NULL, dateentry); - return TRUE; - } + if (priv->grab_pointer != NULL) { + gdk_device_ungrab ( + priv->grab_pointer, + GDK_CURRENT_TIME); + g_object_unref (priv->grab_pointer); + priv->grab_pointer = NULL; + } - gtk_dateentry_popup_display(dateentry); - return TRUE; } + + + + static gint -key_press_popup (GtkWidget *widget, GdkEventKey *event, gpointer user_data) +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("\n[dateentry] key pressed%d\n", event->keyval) ); + DB( g_print(" -> key=%d\n", event->keyval) ); - if (event->keyval != GDK_KEY_Escape) + if (event->keyval != GDK_KEY_Escape && event->keyval != GDK_KEY_Return) return FALSE; - g_signal_stop_emission_by_name (widget, "key_press_event"); - - gtk_dateentry_hide_popdown_window(dateentry); + g_signal_stop_emission_by_name (widget, "key-press-event"); + gtk_date_entry_popdown(dateentry); return TRUE; } static gint -gtk_dateentry_button_press (GtkWidget * widget, GdkEvent * event, gpointer user_data) +gtk_date_entry_popup_button_press (GtkWidget * widget, GdkEvent * event, gpointer user_data) { +GtkDateEntry *dateentry = user_data; +//GtkDateEntryPrivate *priv = dateentry->priv; GtkWidget *child; -DB( g_print("\n[dateentry] button_press\n") ); + DB( g_print("\n[dateentry] popup_button_press\n") ); child = gtk_get_event_widget (event); - if (child != widget) - { - while (child) - { + /* 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); + child = gtk_widget_get_parent (child); } } - 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); + gtk_date_entry_popdown(dateentry); return TRUE; }