aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorDamon Chaplin <damon@helixcode.com>2000-09-11 07:22:51 +0800
committerDamon Chaplin <damon@src.gnome.org>2000-09-11 07:22:51 +0800
commit3ef38d9cc08d0dc1e0e94bfc8b01ca78416bae30 (patch)
treefa70f00a162a910ba8c1e7f67f8f3262d446c3b0 /widgets
parent04b9887c41506d308aac7b89858b3bd5a4bb9ec4 (diff)
downloadgsoc2013-evolution-3ef38d9cc08d0dc1e0e94bfc8b01ca78416bae30.tar.gz
gsoc2013-evolution-3ef38d9cc08d0dc1e0e94bfc8b01ca78416bae30.tar.zst
gsoc2013-evolution-3ef38d9cc08d0dc1e0e94bfc8b01ca78416bae30.zip
added e-dateedit.[hc] and the test-dateedit app.
2000-09-11 Damon Chaplin <damon@helixcode.com> * Makefile.am (libemiscwidgets_a_SOURCES): added e-dateedit.[hc] and the test-dateedit app. * e-dateedit.[hc]: new widget to use instead of GnomeDateEdit. It uses the new ECalendar widget for the calendar and also supports "None", "Today" and "Now" buttons, and goes away with a single click. * test-dateedit.c: app to test the EDateEdit widget. * e-calendar-item.c: updated to support the EDateEdit better, mainly by adding the "move_selection_when_moving" arg so we can turn it off to keep the same day selected when changing the months shown. svn path=/trunk/; revision=5304
Diffstat (limited to 'widgets')
-rw-r--r--widgets/misc/.cvsignore1
-rw-r--r--widgets/misc/ChangeLog15
-rw-r--r--widgets/misc/Makefile.am14
-rw-r--r--widgets/misc/e-calendar-item.c44
-rw-r--r--widgets/misc/e-calendar-item.h11
-rw-r--r--widgets/misc/e-dateedit.c957
-rw-r--r--widgets/misc/e-dateedit.h110
-rw-r--r--widgets/misc/test-dateedit.c114
8 files changed, 1258 insertions, 8 deletions
diff --git a/widgets/misc/.cvsignore b/widgets/misc/.cvsignore
index 411f0fc219..0d7b5ae81b 100644
--- a/widgets/misc/.cvsignore
+++ b/widgets/misc/.cvsignore
@@ -7,3 +7,4 @@ Makefile.in
*.la
test-title-bar
test-calendar
+test-dateedit
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index e3bff75c47..a3619747a6 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,18 @@
+2000-09-11 Damon Chaplin <damon@helixcode.com>
+
+ * Makefile.am (libemiscwidgets_a_SOURCES): added e-dateedit.[hc]
+ and the test-dateedit app.
+
+ * e-dateedit.[hc]: new widget to use instead of GnomeDateEdit. It
+ uses the new ECalendar widget for the calendar and also supports
+ "None", "Today" and "Now" buttons, and goes away with a single click.
+
+ * test-dateedit.c: app to test the EDateEdit widget.
+
+ * e-calendar-item.c: updated to support the EDateEdit better,
+ mainly by adding the "move_selection_when_moving" arg so we can turn
+ it off to keep the same day selected when changing the months shown.
+
2000-09-05 Damon Chaplin <damon@helixcode.com>
* e-calendar-item.c (e_calendar_item_draw_month): make sure we get
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index e2872e7006..1fd1008c9e 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -17,6 +17,8 @@ libemiscwidgets_a_SOURCES = \
e-calendar-item.h \
e-clipped-label.c \
e-clipped-label.h \
+ e-dateedit.c \
+ e-dateedit.h \
e-scroll-frame.c \
e-scroll-frame.h \
e-title-bar.c \
@@ -24,7 +26,8 @@ libemiscwidgets_a_SOURCES = \
noinst_PROGRAMS = \
test-title-bar \
- test-calendar
+ test-calendar \
+ test-dateedit
test_title_bar_SOURCES = \
test-title-bar.c
@@ -40,3 +43,12 @@ test_calendar_LDADD = \
./libemiscwidgets.a \
../../e-util/libeutil.la \
$(EXTRA_GNOME_LIBS)
+
+test_dateedit_SOURCES = \
+ test-dateedit.c
+
+test_dateedit_LDADD = \
+ ./libemiscwidgets.a \
+ ../../e-util/libeutil.la \
+ $(EXTRA_GNOME_LIBS)
+
diff --git a/widgets/misc/e-calendar-item.c b/widgets/misc/e-calendar-item.c
index 53f2608347..4c82f1c5f2 100644
--- a/widgets/misc/e-calendar-item.c
+++ b/widgets/misc/e-calendar-item.c
@@ -241,6 +241,7 @@ enum {
ARG_SHOW_WEEK_NUMBERS,
ARG_MAXIMUM_DAYS_SELECTED,
ARG_DAYS_TO_START_WEEK_SELECTION,
+ ARG_MOVE_SELECTION_WHEN_MOVING,
ARG_ROUND_SELECTION_WHEN_MOVING
};
@@ -328,6 +329,9 @@ e_calendar_item_class_init (ECalendarItemClass *class)
gtk_object_add_arg_type ("ECalendarItem::days_to_start_week_selection",
GTK_TYPE_INT, GTK_ARG_READWRITE,
ARG_DAYS_TO_START_WEEK_SELECTION);
+ gtk_object_add_arg_type ("ECalendarItem::move_selection_when_moving",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE,
+ ARG_MOVE_SELECTION_WHEN_MOVING);
gtk_object_add_arg_type ("ECalendarItem::round_selection_when_moving",
GTK_TYPE_BOOL, GTK_ARG_READWRITE,
ARG_ROUND_SELECTION_WHEN_MOVING);
@@ -395,6 +399,7 @@ e_calendar_item_init (ECalendarItem *calitem)
calitem->expand = TRUE;
calitem->max_days_selected = 42;
calitem->days_to_start_week_selection = 9;
+ calitem->move_selection_when_moving = TRUE;
calitem->round_selection_when_moving = FALSE;
calitem->x1 = 0.0;
@@ -404,7 +409,7 @@ e_calendar_item_init (ECalendarItem *calitem)
calitem->buttons_space = 0.0;
- calitem->selection_start_month_offset = -2;
+ calitem->selection_set = FALSE;
calitem->selection_changed = FALSE;
calitem->date_range_changed = FALSE;
@@ -512,6 +517,9 @@ e_calendar_item_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_DAYS_TO_START_WEEK_SELECTION:
GTK_VALUE_INT (*arg) = calitem->days_to_start_week_selection;
break;
+ case ARG_MOVE_SELECTION_WHEN_MOVING:
+ GTK_VALUE_BOOL (*arg) = calitem->move_selection_when_moving;
+ break;
case ARG_ROUND_SELECTION_WHEN_MOVING:
GTK_VALUE_BOOL (*arg) = calitem->round_selection_when_moving;
break;
@@ -654,6 +662,10 @@ e_calendar_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
ivalue = GTK_VALUE_INT (*arg);
calitem->days_to_start_week_selection = ivalue;
break;
+ case ARG_MOVE_SELECTION_WHEN_MOVING:
+ bvalue = GTK_VALUE_BOOL (*arg);
+ calitem->move_selection_when_moving = bvalue;
+ break;
case ARG_ROUND_SELECTION_WHEN_MOVING:
bvalue = GTK_VALUE_BOOL (*arg);
calitem->round_selection_when_moving = bvalue;
@@ -1258,7 +1270,7 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem,
&& months[mon] == today_month
&& day_num == today_mday;
- selected = calitem->selection_start_month_offset != -2
+ selected = calitem->selection_set
&& (calitem->selection_start_month_offset < month_offset
|| (calitem->selection_start_month_offset == month_offset
&& calitem->selection_start_day <= day_num))
@@ -1631,6 +1643,7 @@ e_calendar_item_button_press (ECalendarItem *calitem,
NULL, event->button.time) != 0)
return FALSE;
+ calitem->selection_set = TRUE;
calitem->selection_start_month_offset = month_offset;
calitem->selection_start_day = day;
calitem->selection_end_month_offset = month_offset;
@@ -2077,9 +2090,10 @@ e_calendar_item_set_first_month(ECalendarItem *calitem,
months_diff = (new_year - calitem->year) * 12
+ new_month - calitem->month;
- if (calitem->selection_start_month_offset != -2) {
- if (calitem->selection_start_month_offset - months_diff >= 0
- && calitem->selection_end_month_offset - months_diff < num_months) {
+ if (calitem->selection_set) {
+ if (!calitem->move_selection_when_moving
+ || (calitem->selection_start_month_offset - months_diff >= 0
+ && calitem->selection_end_month_offset - months_diff < num_months)) {
calitem->selection_start_month_offset -= months_diff;
calitem->selection_end_month_offset -= months_diff;
calitem->selection_real_start_month_offset -= months_diff;
@@ -2441,7 +2455,7 @@ e_calendar_item_get_selection (ECalendarItem *calitem,
g_date_clear (start_date, 1);
g_date_clear (end_date, 1);
- if (calitem->selection_start_month_offset == -2)
+ if (!calitem->selection_set)
return FALSE;
start_year = calitem->year;
@@ -2473,6 +2487,20 @@ e_calendar_item_set_selection (ECalendarItem *calitem,
gboolean need_update;
g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
+
+ /* If start_date is NULL, we clear the selection without changing the
+ month shown. */
+ if (start_date == NULL) {
+ calitem->selection_set = FALSE;
+ calitem->selection_changed = TRUE;
+ e_calendar_item_queue_signal_emission (calitem);
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (calitem));
+ return;
+ }
+
+ if (end_date == NULL)
+ end_date = start_date;
+
g_return_if_fail (g_date_compare (start_date, end_date) <= 0);
start_year = g_date_year (start_date);
@@ -2500,13 +2528,15 @@ e_calendar_item_set_selection (ECalendarItem *calitem,
new_end_day = end_day;
- if (calitem->selection_start_month_offset != new_start_month_offset
+ if (!calitem->selection_set
+ || calitem->selection_start_month_offset != new_start_month_offset
|| calitem->selection_start_day != new_start_day
|| calitem->selection_end_month_offset != new_end_month_offset
|| calitem->selection_end_day != new_end_day) {
need_update = TRUE;
calitem->selection_changed = TRUE;
e_calendar_item_queue_signal_emission (calitem);
+ calitem->selection_set = TRUE;
calitem->selection_start_month_offset = new_start_month_offset;
calitem->selection_start_day = new_start_day;
calitem->selection_end_month_offset = new_end_month_offset;
diff --git a/widgets/misc/e-calendar-item.h b/widgets/misc/e-calendar-item.h
index 3091e47bb4..3820b84131 100644
--- a/widgets/misc/e-calendar-item.h
+++ b/widgets/misc/e-calendar-item.h
@@ -126,6 +126,11 @@ struct _ECalendarItem
weeks, or -1 if we never switch. Defaults to -1. */
gint days_to_start_week_selection;
+ /* Whether the selection is moved when we move back/forward one month.
+ Used for things like the EDateEdit which only want the selection to
+ be changed when the user explicitly selects a day. */
+ gboolean move_selection_when_moving;
+
/* Whether the selection is rounded down to the nearest week when we
move back/forward one month. Used for the week view. */
gboolean round_selection_when_moving;
@@ -165,6 +170,7 @@ struct _ECalendarItem
gboolean selecting;
gboolean selection_dragging_end;
gboolean selection_from_full_week;
+ gboolean selection_set;
gint selection_start_month_offset;
gint selection_start_day;
gint selection_end_month_offset;
@@ -236,9 +242,14 @@ void e_calendar_item_get_date_range (ECalendarItem *calitem,
gint *end_month,
gint *end_day);
+/* Returns the selected date range. It returns FALSE if no days are currently
+ selected. */
gboolean e_calendar_item_get_selection (ECalendarItem *calitem,
GDate *start_date,
GDate *end_date);
+/* Sets the selected date range, and changes the date range shown so at least
+ the start of the selection is shown. If start_date is NULL it clears the
+ selection. */
void e_calendar_item_set_selection (ECalendarItem *calitem,
GDate *start_date,
GDate *end_date);
diff --git a/widgets/misc/e-dateedit.c b/widgets/misc/e-dateedit.c
new file mode 100644
index 0000000000..dac3cce0c6
--- /dev/null
+++ b/widgets/misc/e-dateedit.c
@@ -0,0 +1,957 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@helixcode.com>
+ *
+ * Copyright 2000, Helix Code, Inc.
+ *
+ * Based on the GnomeDateEdit, part of the Gnome Library.
+ * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EDateEdit - a widget based on GnomeDateEdit to provide a date & optional
+ * time field with popups for entering a date.
+ */
+
+/* We need this for strptime. */
+#define _XOPEN_SOURCE
+
+#include <config.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <gtk/gtkmain.h>
+#include "e-dateedit.h"
+#include "e-calendar.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkarrow.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkwindow.h>
+
+struct _EDateEditPrivate {
+ GtkWidget *date_entry;
+ GtkWidget *date_button;
+
+ GtkWidget *space;
+
+ GtkWidget *time_combo;
+
+ GtkWidget *cal_popup;
+ GtkWidget *calendar;
+ GtkWidget *now_button;
+ GtkWidget *today_button;
+ GtkWidget *none_button;
+
+ gboolean show_time;
+ gboolean use_24_hour_format;
+
+ gint lower_hour;
+ gint upper_hour;
+};
+
+enum {
+ DATE_CHANGED,
+ TIME_CHANGED,
+ LAST_SIGNAL
+};
+
+
+static gint date_edit_signals [LAST_SIGNAL] = { 0 };
+
+
+static void e_date_edit_class_init (EDateEditClass *class);
+static void e_date_edit_init (EDateEdit *dedit);
+static void create_children (EDateEdit *dedit);
+static void e_date_edit_destroy (GtkObject *object);
+static void e_date_edit_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void on_date_button_clicked (GtkWidget *widget,
+ EDateEdit *dedit);
+static void position_date_popup (EDateEdit *dedit);
+static void on_date_popup_none_button_clicked (GtkWidget *button,
+ EDateEdit *dedit);
+static void on_date_popup_today_button_clicked (GtkWidget *button,
+ EDateEdit *dedit);
+static void on_date_popup_now_button_clicked (GtkWidget *button,
+ EDateEdit *dedit);
+static gint on_date_popup_delete_event (GtkWidget *widget,
+ gpointer data);
+static gint on_date_popup_key_press (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data);
+static gint on_date_popup_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data);
+static void on_date_popup_date_selected (ECalendarItem *calitem,
+ EDateEdit *dedit);
+static void hide_date_popup (EDateEdit *dedit);
+static void rebuild_time_popup (EDateEdit *dedit);
+static void enable_time_combo (EDateEdit *dedit);
+static void disable_time_combo (EDateEdit *dedit);
+static gboolean date_is_none (char *date_text);
+
+
+static GtkHBoxClass *parent_class;
+
+/**
+ * e_date_edit_get_type:
+ *
+ * Returns the GtkType for the EDateEdit widget
+ */
+guint
+e_date_edit_get_type (void)
+{
+ static guint date_edit_type = 0;
+
+ if (!date_edit_type){
+ GtkTypeInfo date_edit_info = {
+ "EDateEdit",
+ sizeof (EDateEdit),
+ sizeof (EDateEditClass),
+ (GtkClassInitFunc) e_date_edit_class_init,
+ (GtkObjectInitFunc) e_date_edit_init,
+ NULL,
+ NULL,
+ };
+
+ date_edit_type = gtk_type_unique (gtk_hbox_get_type (), &date_edit_info);
+ }
+
+ return date_edit_type;
+}
+
+
+static void
+e_date_edit_class_init (EDateEditClass *class)
+{
+ GtkObjectClass *object_class = (GtkObjectClass *) class;
+ GtkContainerClass *container_class = (GtkContainerClass *) class;
+
+ object_class = (GtkObjectClass*) class;
+
+ parent_class = gtk_type_class (gtk_hbox_get_type ());
+
+ date_edit_signals [TIME_CHANGED] =
+ gtk_signal_new ("time_changed",
+ GTK_RUN_FIRST, object_class->type,
+ GTK_SIGNAL_OFFSET (EDateEditClass,
+ time_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ date_edit_signals [DATE_CHANGED] =
+ gtk_signal_new ("date_changed",
+ GTK_RUN_FIRST, object_class->type,
+ GTK_SIGNAL_OFFSET (EDateEditClass,
+ date_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, date_edit_signals,
+ LAST_SIGNAL);
+
+ container_class->forall = e_date_edit_forall;
+
+ object_class->destroy = e_date_edit_destroy;
+
+ class->date_changed = NULL;
+ class->time_changed = NULL;
+}
+
+
+static void
+e_date_edit_init (EDateEdit *dedit)
+{
+ EDateEditPrivate *priv;
+
+ dedit->_priv = priv = g_new0 (EDateEditPrivate, 1);
+
+ priv->show_time = TRUE;
+ priv->use_24_hour_format = TRUE;
+
+ priv->lower_hour = 0;
+ priv->upper_hour = 24;
+}
+
+
+/**
+ * e_date_edit_new:
+ *
+ * Description: Creates a new #EDateEdit widget which can be used
+ * to provide an easy to use way for entering dates and times.
+ *
+ * Returns: a new #EDateEdit widget.
+ */
+GtkWidget *
+e_date_edit_new (void)
+{
+ EDateEdit *dedit;
+
+ dedit = gtk_type_new (e_date_edit_get_type ());
+
+ create_children (dedit);
+ e_date_edit_set_time (dedit, 0);
+
+ return GTK_WIDGET (dedit);
+}
+
+
+static void
+create_children (EDateEdit *dedit)
+{
+ EDateEditPrivate *priv;
+ ECalendar *calendar;
+ GtkWidget *frame, *arrow;
+ GtkWidget *vbox, *bbox;
+
+ priv = dedit->_priv;
+
+ priv->date_entry = gtk_entry_new ();
+ gtk_widget_set_usize (priv->date_entry, 90, 0);
+ gtk_box_pack_start (GTK_BOX (dedit), priv->date_entry, FALSE, TRUE, 0);
+ gtk_widget_show (priv->date_entry);
+
+ priv->date_button = gtk_button_new ();
+ gtk_signal_connect (GTK_OBJECT (priv->date_button), "clicked",
+ GTK_SIGNAL_FUNC (on_date_button_clicked), dedit);
+ gtk_box_pack_start (GTK_BOX (dedit), priv->date_button,
+ FALSE, FALSE, 0);
+
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (priv->date_button), arrow);
+ gtk_widget_show (arrow);
+
+ gtk_widget_show (priv->date_button);
+
+ /* This is just to create a space between the date & time parts. */
+ priv->space = gtk_drawing_area_new ();
+ gtk_box_pack_start (GTK_BOX (dedit), priv->space, FALSE, FALSE, 2);
+
+
+ priv->time_combo = gtk_combo_new ();
+ gtk_widget_set_usize (GTK_COMBO (priv->time_combo)->entry, 90, 0);
+ gtk_box_pack_start (GTK_BOX (dedit), priv->time_combo, FALSE, TRUE, 0);
+ rebuild_time_popup (dedit);
+
+ if (priv->show_time) {
+ gtk_widget_show (priv->space);
+ gtk_widget_show (priv->time_combo);
+ }
+
+ priv->cal_popup = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_widget_set_events (priv->cal_popup,
+ gtk_widget_get_events (priv->cal_popup)
+ | GDK_KEY_PRESS_MASK);
+ gtk_signal_connect (GTK_OBJECT (priv->cal_popup), "delete_event",
+ (GtkSignalFunc) on_date_popup_delete_event,
+ dedit);
+ gtk_signal_connect (GTK_OBJECT (priv->cal_popup), "key_press_event",
+ (GtkSignalFunc) on_date_popup_key_press,
+ dedit);
+ gtk_signal_connect (GTK_OBJECT (priv->cal_popup), "button_press_event",
+ (GtkSignalFunc) on_date_popup_button_press,
+ dedit);
+ gtk_window_set_policy (GTK_WINDOW (priv->cal_popup),
+ FALSE, FALSE, TRUE);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (priv->cal_popup), frame);
+ gtk_widget_show (frame);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_widget_show (vbox);
+
+ priv->calendar = e_calendar_new ();
+ calendar = E_CALENDAR (priv->calendar);
+ /*e_calendar_set_buttons (calendar, TRUE, TRUE);*/
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (calendar->calitem),
+ "maximum_days_selected", 1,
+ "move_selection_when_moving", FALSE,
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT (calendar->calitem),
+ "selection_changed",
+ GTK_SIGNAL_FUNC (on_date_popup_date_selected), dedit);
+
+ gtk_box_pack_start (GTK_BOX (vbox), priv->calendar, FALSE, FALSE, 0);
+ gtk_widget_show (priv->calendar);
+
+ bbox = gtk_hbutton_box_new ();
+ gtk_container_set_border_width (GTK_CONTAINER (bbox), 4);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 2);
+ gtk_button_box_set_child_ipadding (GTK_BUTTON_BOX (bbox), 2, 0);
+ gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
+ gtk_widget_show (bbox);
+
+ priv->now_button = gtk_button_new_with_label (_("Now"));
+ gtk_container_add (GTK_CONTAINER (bbox), priv->now_button);
+ gtk_widget_show (priv->now_button);
+ gtk_signal_connect (GTK_OBJECT (priv->now_button), "clicked",
+ GTK_SIGNAL_FUNC (on_date_popup_now_button_clicked), dedit);
+
+ priv->today_button = gtk_button_new_with_label (_("Today"));
+ gtk_container_add (GTK_CONTAINER (bbox), priv->today_button);
+ gtk_widget_show (priv->today_button);
+ gtk_signal_connect (GTK_OBJECT (priv->today_button), "clicked",
+ GTK_SIGNAL_FUNC (on_date_popup_today_button_clicked), dedit);
+
+ priv->none_button = gtk_button_new_with_label (_("None"));
+ gtk_container_add (GTK_CONTAINER (bbox), priv->none_button);
+ gtk_signal_connect (GTK_OBJECT (priv->none_button), "clicked",
+ GTK_SIGNAL_FUNC (on_date_popup_none_button_clicked), dedit);
+}
+
+
+static void
+e_date_edit_destroy (GtkObject *object)
+{
+ EDateEdit *dedit;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (E_IS_DATE_EDIT (object));
+
+ dedit = E_DATE_EDIT (object);
+
+ gtk_widget_destroy (dedit->_priv->cal_popup);
+ gtk_widget_unref (dedit->_priv->cal_popup);
+
+ g_free(dedit->_priv);
+ dedit->_priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+static void
+e_date_edit_forall (GtkContainer *container, gboolean include_internals,
+ GtkCallback callback, gpointer callback_data)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_DATE_EDIT (container));
+ g_return_if_fail (callback != NULL);
+
+ /* Let GtkBox handle things only if the internal widgets need to be
+ * poked.
+ */
+ if (include_internals)
+ if (GTK_CONTAINER_CLASS (parent_class)->forall)
+ (* GTK_CONTAINER_CLASS (parent_class)->forall)
+ (container,
+ include_internals,
+ callback,
+ callback_data);
+}
+
+
+/* The arrow button beside the date field has been clicked, so we show the
+ popup with the ECalendar in. */
+static void
+on_date_button_clicked (GtkWidget *widget, EDateEdit *dedit)
+{
+ EDateEditPrivate *priv;
+ ECalendar *calendar;
+ struct tm mtm;
+ gchar *date_text, *status;
+ GDate selected_day;
+ gboolean clear_selection = FALSE;
+
+ priv = dedit->_priv;
+ calendar = E_CALENDAR (priv->calendar);
+
+ date_text = gtk_entry_get_text (GTK_ENTRY (dedit->_priv->date_entry));
+ if (date_is_none (date_text)) {
+ clear_selection = TRUE;
+ } else {
+ status = strptime (date_text, "%x", &mtm);
+ if (!status || !status[0])
+ clear_selection = TRUE;
+ }
+
+ if (clear_selection) {
+ e_calendar_item_set_selection (calendar->calitem, NULL, NULL);
+ } else {
+ g_date_clear (&selected_day, 1);
+ g_date_set_dmy (&selected_day, mtm.tm_mday, mtm.tm_mon + 1,
+ mtm.tm_year + 1900);
+ e_calendar_item_set_selection (calendar->calitem,
+ &selected_day, NULL);
+ }
+
+ /* FIXME: Hack. Change ECalendarItem so it doesn't queue signal
+ emissions. */
+ calendar->calitem->selection_changed = FALSE;
+
+ position_date_popup (dedit);
+
+ gtk_widget_realize (dedit->_priv->cal_popup);
+ gtk_widget_show (dedit->_priv->cal_popup);
+
+ gtk_widget_grab_focus (dedit->_priv->cal_popup);
+
+ gtk_grab_add (dedit->_priv->cal_popup);
+
+ gdk_pointer_grab (dedit->_priv->cal_popup->window, TRUE,
+ (GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_POINTER_MOTION_MASK),
+ NULL, NULL, GDK_CURRENT_TIME);
+}
+
+
+/* This positions the date popup below and to the left of the arrow button,
+ just before it is shown. */
+static void
+position_date_popup (EDateEdit *dedit)
+{
+ gint x, y;
+ gint bwidth, bheight;
+ GtkRequisition req;
+ gint screen_width, screen_height;
+
+ gtk_widget_size_request (dedit->_priv->cal_popup, &req);
+
+ gdk_window_get_origin (dedit->_priv->date_button->window, &x, &y);
+ gdk_window_get_size (dedit->_priv->date_button->window,
+ &bwidth, &bheight);
+
+ screen_width = gdk_screen_width ();
+ screen_height = gdk_screen_height ();
+
+ x += bwidth - req.width;
+ y += bheight;
+
+ x = CLAMP (x, 0, MAX (0, screen_width - req.width));
+ y = CLAMP (y, 0, MAX (0, screen_height - req.height));
+
+ gtk_widget_set_uposition (dedit->_priv->cal_popup, x, y);
+}
+
+
+/* A date has been selected in the date popup, so we set the date field
+ and hide the popup. */
+static void
+on_date_popup_date_selected (ECalendarItem *calitem, EDateEdit *dedit)
+{
+ GDate start_date, end_date;
+ struct tm tmp_tm;
+ char buffer [40];
+
+ if (!e_calendar_item_get_selection (calitem, &start_date, &end_date))
+ return;
+
+ g_date_to_struct_tm (&start_date, &tmp_tm);
+
+ strftime (buffer, sizeof (buffer), "%x", &tmp_tm);
+ gtk_entry_set_text (GTK_ENTRY (dedit->_priv->date_entry), buffer);
+
+ enable_time_combo (dedit);
+
+ gtk_signal_emit (GTK_OBJECT (dedit), date_edit_signals [DATE_CHANGED]);
+ hide_date_popup (dedit);
+}
+
+
+static void
+on_date_popup_now_button_clicked (GtkWidget *button,
+ EDateEdit *dedit)
+{
+ e_date_edit_set_time (dedit, time (NULL));
+ gtk_signal_emit (GTK_OBJECT (dedit), date_edit_signals [DATE_CHANGED]);
+ hide_date_popup (dedit);
+}
+
+
+static void
+on_date_popup_today_button_clicked (GtkWidget *button,
+ EDateEdit *dedit)
+{
+ struct tm *tmp_tm;
+ time_t t;
+ char buffer [40];
+
+ t = time (NULL);
+ tmp_tm = localtime (&t);
+ strftime (buffer, sizeof (buffer), "%x", tmp_tm);
+ gtk_entry_set_text (GTK_ENTRY (dedit->_priv->date_entry), buffer);
+
+ enable_time_combo (dedit);
+
+ gtk_signal_emit (GTK_OBJECT (dedit), date_edit_signals [DATE_CHANGED]);
+ hide_date_popup (dedit);
+}
+
+
+static void
+on_date_popup_none_button_clicked (GtkWidget *button,
+ EDateEdit *dedit)
+{
+ e_date_edit_set_time (dedit, -1);
+ gtk_signal_emit (GTK_OBJECT (dedit), date_edit_signals [DATE_CHANGED]);
+ hide_date_popup (dedit);
+}
+
+
+/* A key has been pressed while the date popup is showing. If it is the Escape
+ key we hide the popup. */
+static gint
+on_date_popup_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ EDateEdit *dedit;
+
+ if (event->keyval != GDK_Escape)
+ return FALSE;
+
+ dedit = data;
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+ hide_date_popup (dedit);
+
+ return TRUE;
+}
+
+
+/* A mouse button has been pressed while the date popup is showing.
+ Any button press events used to select days etc. in the popup will have
+ have been handled elsewhere, so here we just hide the popup.
+ (This function is yanked from gtkcombo.c) */
+static gint
+on_date_popup_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ EDateEdit *dedit;
+ GtkWidget *child;
+
+ dedit = data;
+
+ child = gtk_get_event_widget ((GdkEvent *) 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 = child->parent;
+ }
+ }
+
+ hide_date_popup (dedit);
+
+ return TRUE;
+}
+
+
+/* A delete event has been received for the date popup, so we hide it and
+ return TRUE so it doesn't get destroyed. */
+static gint
+on_date_popup_delete_event (GtkWidget *widget, gpointer data)
+{
+ EDateEdit *dedit;
+
+ dedit = data;
+ hide_date_popup (dedit);
+
+ return TRUE;
+}
+
+
+/* Hides the date popup, removing any grabs. */
+static void
+hide_date_popup (EDateEdit *dedit)
+{
+ gtk_widget_hide (dedit->_priv->cal_popup);
+ gtk_grab_remove (dedit->_priv->cal_popup);
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+}
+
+
+/**
+ * e_date_edit_get_time:
+ * @dedit: The EDateEdit widget
+ *
+ * Returns the time entered in the EDateEdit widget
+ */
+time_t
+e_date_edit_get_time (EDateEdit *dedit)
+{
+ EDateEditPrivate *priv;
+ struct tm date_tm = { 0 }, time_tm = { 0 };
+ char *date_text, *time_text, *format;
+
+ g_return_val_if_fail (dedit != NULL, -1);
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), -1);
+
+ priv = dedit->_priv;
+
+ date_text = gtk_entry_get_text (GTK_ENTRY (priv->date_entry));
+ if (date_is_none (date_text))
+ return -1;
+
+ strptime (date_text, "%x", &date_tm);
+
+ if (dedit->_priv->show_time) {
+ time_text = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (priv->time_combo)->entry));
+
+ if (priv->use_24_hour_format)
+ format = "%H:%M";
+ else
+ format = "%I:%M %p";
+
+ strptime (time_text, format, &time_tm);
+
+ date_tm.tm_hour = time_tm.tm_hour;
+ date_tm.tm_min = time_tm.tm_min;
+ }
+
+ date_tm.tm_isdst = -1;
+
+ return mktime (&date_tm);
+}
+
+
+/**
+ * e_date_edit_set_time:
+ * @dedit: the EDateEdit widget
+ * @the_time: The time and date that should be set on the widget
+ *
+ * Description: Changes the displayed date and time in the EDateEdit
+ * widget to be the one represented by @the_time. If @the_time is 0
+ * then current time is used.
+ */
+void
+e_date_edit_set_time (EDateEdit *dedit, time_t the_time)
+{
+ EDateEditPrivate *priv;
+ struct tm *mytm;
+ char buffer[40], *format;
+
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ priv = dedit->_priv;
+
+ if (the_time == -1) {
+ gtk_entry_set_text (GTK_ENTRY (priv->date_entry), _("None"));
+ disable_time_combo (dedit);
+ return;
+ }
+
+ enable_time_combo (dedit);
+
+ if (the_time == 0)
+ the_time = time (NULL);
+
+ mytm = localtime (&the_time);
+
+ /* Set the date */
+ strftime (buffer, sizeof (buffer), "%x", mytm);
+ gtk_entry_set_text (GTK_ENTRY (priv->date_entry), buffer);
+
+ /* Set the time */
+ if (priv->use_24_hour_format)
+ format = "%H:%M";
+ else
+ format = "%I:%M %p";
+
+ strftime (buffer, sizeof (buffer), format, mytm);
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (priv->time_combo)->entry),
+ buffer);
+}
+
+
+/* Whether we show the time field. */
+gboolean
+e_date_edit_get_show_time (EDateEdit *dedit)
+{
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE);
+
+ return dedit->_priv->show_time;
+}
+
+
+void
+e_date_edit_set_show_time (EDateEdit *dedit,
+ gboolean show_time)
+{
+ EDateEditPrivate *priv;
+
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ priv = dedit->_priv;
+
+ if (priv->show_time == show_time)
+ return;
+
+ priv->show_time = show_time;
+
+ if (show_time) {
+ gtk_widget_show (priv->space);
+ gtk_widget_show (priv->time_combo);
+ } else {
+ gtk_widget_hide (priv->space);
+ gtk_widget_hide (priv->time_combo);
+ gtk_widget_hide (priv->now_button);
+ }
+}
+
+
+/* The week start day, used in the date popup. 0 (Sun) to 6 (Sat). */
+gint
+e_date_edit_get_week_start_day (EDateEdit *dedit)
+{
+ gint week_start_day;
+
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), 1);
+
+ gtk_object_get (GTK_OBJECT (E_CALENDAR (dedit->_priv->calendar)->calitem),
+ "week_start_day", &week_start_day,
+ NULL);
+
+ return week_start_day;
+}
+
+
+void
+e_date_edit_set_week_start_day (EDateEdit *dedit,
+ gint week_start_day)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (dedit->_priv->calendar)->calitem),
+ "week_start_day", week_start_day,
+ NULL);
+}
+
+
+/* Whether we show week numbers in the date popup. */
+gboolean
+e_date_edit_get_show_week_numbers (EDateEdit *dedit)
+{
+ gboolean show_week_numbers;
+
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE);
+
+ gtk_object_get (GTK_OBJECT (E_CALENDAR (dedit->_priv->calendar)->calitem),
+ "show_week_numbers", &show_week_numbers,
+ NULL);
+
+ return show_week_numbers;
+}
+
+
+void
+e_date_edit_set_show_week_numbers (EDateEdit *dedit,
+ gboolean show_week_numbers)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (dedit->_priv->calendar)->calitem),
+ "show_week_numbers", show_week_numbers,
+ NULL);
+}
+
+
+/* Whether we use 24 hour format in the time field & popup. */
+gboolean
+e_date_edit_get_use_24_hour_format (EDateEdit *dedit)
+{
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE);
+
+ return dedit->_priv->use_24_hour_format;
+}
+
+
+void
+e_date_edit_set_use_24_hour_format (EDateEdit *dedit,
+ gboolean use_24_hour_format)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ if (dedit->_priv->use_24_hour_format == use_24_hour_format)
+ return;
+
+ dedit->_priv->use_24_hour_format = use_24_hour_format;
+
+ rebuild_time_popup (dedit);
+}
+
+
+/* Whether we allow the date to be set to 'None'. e_date_edit_get_time() will
+ return (time_t) -1 in this case. */
+gboolean
+e_date_edit_get_allow_no_date_set (EDateEdit *dedit)
+{
+ g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE);
+
+ return GTK_WIDGET_VISIBLE (dedit->_priv->none_button);
+}
+
+
+void
+e_date_edit_set_allow_no_date_set (EDateEdit *dedit,
+ gboolean allow_no_date_set)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ if (allow_no_date_set) {
+ gtk_widget_show (dedit->_priv->none_button);
+ } else {
+ gtk_widget_hide (dedit->_priv->none_button);
+
+ /* If currently set to 'None' set to the current time. */
+ if (e_date_edit_get_time (dedit) == -1)
+ e_date_edit_set_time (dedit, time (NULL));
+ }
+}
+
+
+/* The range of time to show in the time combo popup. */
+void
+e_date_edit_get_time_popup_range (EDateEdit *dedit,
+ gint *lower_hour,
+ gint *upper_hour)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ *lower_hour = dedit->_priv->lower_hour;
+ *upper_hour = dedit->_priv->upper_hour;
+}
+
+
+void
+e_date_edit_set_time_popup_range (EDateEdit *dedit,
+ gint lower_hour,
+ gint upper_hour)
+{
+ g_return_if_fail (E_IS_DATE_EDIT (dedit));
+
+ if (dedit->_priv->lower_hour == lower_hour
+ && dedit->_priv->upper_hour == upper_hour)
+ return;
+
+ dedit->_priv->lower_hour = lower_hour;
+ dedit->_priv->upper_hour = upper_hour;
+
+ rebuild_time_popup (dedit);
+}
+
+
+static void
+rebuild_time_popup (EDateEdit *dedit)
+{
+ EDateEditPrivate *priv;
+ GtkList *list;
+ GtkWidget *listitem;
+ char buffer[40], *format;
+ struct tm tmp_tm;
+ gint hour, min;
+
+ priv = dedit->_priv;
+
+ list = GTK_LIST (GTK_COMBO (priv->time_combo)->list);
+
+ gtk_list_clear_items (list, 0, -1);
+
+ /* Fill the struct tm with some sane values. */
+ tmp_tm.tm_year = 2000;
+ tmp_tm.tm_mon = 0;
+ tmp_tm.tm_mday = 1;
+ tmp_tm.tm_sec = 0;
+ tmp_tm.tm_isdst = 0;
+
+ for (hour = priv->lower_hour; hour <= priv->upper_hour; hour++) {
+
+ /* We don't want to display midnight at the end, since that is
+ really in the next day. */
+ if (hour == 24)
+ break;
+
+ /* We want to finish on upper_hour, with min == 0. */
+ for (min = 0;
+ min == 0 || (min < 60 && hour != priv->upper_hour);
+ min += 30) {
+ tmp_tm.tm_hour = hour;
+ tmp_tm.tm_min = min;
+
+ if (priv->use_24_hour_format)
+ format = "%H:%M";
+ else
+ format = "%I:%M %p";
+
+ strftime (buffer, sizeof (buffer), format, &tmp_tm);
+
+ listitem = gtk_list_item_new_with_label (buffer);
+ gtk_widget_show (listitem);
+ gtk_container_add (GTK_CONTAINER (list), listitem);
+ }
+ }
+}
+
+
+static void
+enable_time_combo (EDateEdit *dedit)
+{
+ gtk_widget_set_sensitive (dedit->_priv->time_combo, TRUE);
+}
+
+
+static void
+disable_time_combo (EDateEdit *dedit)
+{
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (dedit->_priv->time_combo)->entry), "");
+ gtk_widget_set_sensitive (dedit->_priv->time_combo, FALSE);
+}
+
+
+static gboolean
+date_is_none (char *date_text)
+{
+ char *pos, *none_string;
+
+ pos = date_text;
+ while (isspace (*pos))
+ pos++;
+
+ none_string = _("None");
+
+ if (*pos == '\0' || !strncmp (pos, none_string, strlen (none_string)))
+ return TRUE;
+ return FALSE;
+}
+
diff --git a/widgets/misc/e-dateedit.h b/widgets/misc/e-dateedit.h
new file mode 100644
index 0000000000..a2783c1814
--- /dev/null
+++ b/widgets/misc/e-dateedit.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@helixcode.com>
+ *
+ * Copyright 2000, Helix Code, Inc.
+ *
+ * Based on the GnomeDateEdit, part of the Gnome Library.
+ * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EDateEdit - a widget based on GnomeDateEdit to provide a date & optional
+ * time field with popups for entering a date.
+ */
+
+#ifndef __E_DATE_EDIT_H_
+#define __E_DATE_EDIT_H_
+
+#include <gtk/gtkhbox.h>
+#include <libgnome/gnome-defs.h>
+
+BEGIN_GNOME_DECLS
+
+
+#define E_TYPE_DATE_EDIT (e_date_edit_get_type ())
+#define E_DATE_EDIT(obj) (GTK_CHECK_CAST ((obj), E_TYPE_DATE_EDIT, EDateEdit))
+#define E_DATE_EDIT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_DATE_EDIT, EDateEditClass))
+#define E_IS_DATE_EDIT(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_DATE_EDIT))
+#define E_IS_DATE_EDIT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_DATE_EDIT))
+
+
+typedef struct _EDateEdit EDateEdit;
+typedef struct _EDateEditPrivate EDateEditPrivate;
+typedef struct _EDateEditClass EDateEditClass;
+
+struct _EDateEdit {
+ GtkHBox hbox;
+
+ /*< private >*/
+ EDateEditPrivate *_priv;
+};
+
+struct _EDateEditClass {
+ GtkHBoxClass parent_class;
+
+ void (*date_changed) (EDateEdit *dedit);
+ void (*time_changed) (EDateEdit *dedit);
+};
+
+guint e_date_edit_get_type (void);
+GtkWidget* e_date_edit_new (void);
+
+time_t e_date_edit_get_time (EDateEdit *dedit);
+void e_date_edit_set_time (EDateEdit *dedit,
+ time_t the_time);
+
+/* Whether we show the time field. */
+gboolean e_date_edit_get_show_time (EDateEdit *dedit);
+void e_date_edit_set_show_time (EDateEdit *dedit,
+ gboolean show_time);
+
+/* The week start day, used in the date popup. 0 (Mon) to 6 (Sun). */
+gint e_date_edit_get_week_start_day (EDateEdit *dedit);
+void e_date_edit_set_week_start_day (EDateEdit *dedit,
+ gint week_start_day);
+
+/* Whether we show week numbers in the date popup. */
+gboolean e_date_edit_get_show_week_numbers (EDateEdit *dedit);
+void e_date_edit_set_show_week_numbers (EDateEdit *dedit,
+ gboolean show_week_numbers);
+
+/* Whether we use 24 hour format in the time field & popup. */
+gboolean e_date_edit_get_use_24_hour_format (EDateEdit *dedit);
+void e_date_edit_set_use_24_hour_format (EDateEdit *dedit,
+ gboolean use_24_hour_format);
+
+/* Whether we allow the date to be set to 'None'. e_date_edit_get_time() will
+ return (time_t) -1 in this case. */
+gboolean e_date_edit_get_allow_no_date_set (EDateEdit *dedit);
+void e_date_edit_set_allow_no_date_set (EDateEdit *dedit,
+ gboolean allow_no_date_set);
+
+/* The range of time to show in the time combo popup. */
+void e_date_edit_get_time_popup_range (EDateEdit *dedit,
+ gint *lower_hour,
+ gint *upper_hour);
+void e_date_edit_set_time_popup_range (EDateEdit *dedit,
+ gint lower_hour,
+ gint upper_hour);
+
+END_GNOME_DECLS
+
+#endif
diff --git a/widgets/misc/test-dateedit.c b/widgets/misc/test-dateedit.c
new file mode 100644
index 0000000000..12fb93ac88
--- /dev/null
+++ b/widgets/misc/test-dateedit.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@helixcode.com>
+ *
+ * Copyright 2000, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * test-dateedit - tests the EDateEdit widget.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gnome.h>
+
+#include "e-dateedit.h"
+
+static void delete_event_cb (GtkWidget *widget,
+ GdkEventAny *event,
+ gpointer data);
+static void on_get_date_clicked (GtkWidget *button,
+ EDateEdit *dedit);
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *app;
+ EDateEdit *dedit;
+ GtkWidget *vbox, *button;
+
+ gnome_init ("test-dateedit", "0.0", argc, argv);
+
+ app = gnome_app_new ("Test", "Test");
+ gtk_window_set_default_size (GTK_WINDOW (app), 400, 200);
+ gtk_window_set_policy (GTK_WINDOW (app), FALSE, TRUE, TRUE);
+ gtk_container_set_border_width (GTK_CONTAINER (app), 8);
+
+ gtk_signal_connect (GTK_OBJECT (app), "delete_event",
+ GTK_SIGNAL_FUNC (delete_event_cb), NULL);
+
+ dedit = E_DATE_EDIT (e_date_edit_new ());
+ gtk_widget_show ((GtkWidget*) (dedit));
+
+ e_date_edit_set_week_start_day (dedit, 1);
+ e_date_edit_set_show_week_numbers (dedit, TRUE);
+ e_date_edit_set_use_24_hour_format (dedit, FALSE);
+ e_date_edit_set_time_popup_range (dedit, 8, 18);
+#if 0
+ e_date_edit_set_show_time (dedit, FALSE);
+#endif
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), (GtkWidget*) dedit,
+ FALSE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ button = gtk_button_new_with_label ("Get Date");
+ gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (on_get_date_clicked), dedit);
+
+
+ gnome_app_set_contents (GNOME_APP (app), vbox);
+ gtk_widget_show (app);
+
+ gtk_main ();
+
+ return 0;
+}
+
+
+static void
+delete_event_cb (GtkWidget *widget,
+ GdkEventAny *event,
+ gpointer data)
+{
+ gtk_main_quit ();
+}
+
+
+static void
+on_get_date_clicked (GtkWidget *button,
+ EDateEdit *dedit)
+{
+ time_t t;
+
+ t = e_date_edit_get_time (dedit);
+
+ if (t == -1)
+ g_print ("Time: None\n");
+ else
+ g_print ("Time: %s", ctime (&t));
+}
+