diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 4fd509cdac..799c0b0a3b 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -164,6 +164,7 @@ gtk_public_h_sources = \ gtkcontainer.h \ gtkcssprovider.h \ gtkcsssection.h \ + gtkdatechooserwidget.h \ gtkdebug.h \ gtkdialog.h \ gtkdnd.h \ @@ -424,6 +425,7 @@ gtk_private_h_sources = \ gtkcssvalueprivate.h \ gtkcsswidgetnodeprivate.h \ gtkcustompaperunixdialog.h \ + gtkdatechooserdayprivate.h \ gtkdialogprivate.h \ gtkdndprivate.h \ gtkentryprivate.h \ @@ -668,6 +670,8 @@ gtk_base_c_sources = \ gtkcsstypes.c \ gtkcssvalue.c \ gtkcsswidgetnode.c \ + gtkdatechooserday.c \ + gtkdatechooserwidget.c \ gtkdialog.c \ gtkdrawingarea.c \ gtkeditable.c \ @@ -1080,6 +1084,7 @@ templates = \ ui/gtkcolorchooserdialog.ui \ ui/gtkcoloreditor.ui \ ui/gtkcombobox.ui \ + ui/gtkdatechooserwidget.ui \ ui/gtkdialog.ui \ ui/gtkfilechooserbutton.ui \ ui/gtkfilechooserwidget.ui \ diff --git a/gtk/gtk.h b/gtk/gtk.h index 3cbd13fcd5..0d85e4a4a1 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkdatechooserday.c b/gtk/gtkdatechooserday.c new file mode 100644 index 0000000000..5e7c50033d --- /dev/null +++ b/gtk/gtkdatechooserday.c @@ -0,0 +1,359 @@ +/* GTK - The GIMP Toolkit + * + * Copyright (C) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkdatechooserdayprivate.h" +#include "gtklabel.h" +#include "gtkgesturemultipress.h" +#include "gtkrender.h" +#include "gtkwidgetprivate.h" +#include "gtkselection.h" +#include "gtkdnd.h" + +#include "gtkintl.h" +#include "gtkprivate.h" + +#include +#include + +enum { + SELECTED, + LAST_DAY_SIGNAL +}; + +static guint day_signals[LAST_DAY_SIGNAL] = { 0, }; + +struct _GtkDateChooserDay +{ + GtkBin parent; + GtkWidget *label; + guint day; + guint month; + guint year; + GdkWindow *event_window; + GtkGesture *multipress_gesture; +}; + +struct _GtkDateChooserDayClass +{ + GtkBinClass parent_class; +}; + +G_DEFINE_TYPE (GtkDateChooserDay, gtk_date_chooser_day, GTK_TYPE_BIN) + +static void +day_pressed (GtkGestureMultiPress *gesture, + gint n_press, + gdouble x, + gdouble y, + GtkDateChooserDay *day) +{ + gint button; + + button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)); + + if (button == GDK_BUTTON_PRIMARY) + { + if (n_press == 1) + g_signal_emit (day, day_signals[SELECTED], 0); + } +} + +static gboolean +gtk_date_chooser_day_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + + if (event->keyval == GDK_KEY_space || + event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_ISO_Enter|| + event->keyval == GDK_KEY_KP_Enter || + event->keyval == GDK_KEY_KP_Space) + { + g_signal_emit (day, day_signals[SELECTED], 0); + return TRUE; + } + + if (GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->key_press_event (widget, event)) + return TRUE; + + return FALSE; +} + +static void +gtk_date_chooser_day_init (GtkDateChooserDay *day) +{ + GtkWidget *widget = GTK_WIDGET (day); + + gtk_widget_set_can_focus (widget, TRUE); + gtk_style_context_add_class (gtk_widget_get_style_context (widget), "day"); + + day->label = gtk_label_new (""); + gtk_widget_show (day->label); + gtk_widget_set_hexpand (day->label, TRUE); + gtk_widget_set_vexpand (day->label, TRUE); + gtk_label_set_xalign (GTK_LABEL (day->label), 1.0); + + gtk_container_add (GTK_CONTAINER (day), day->label); + + day->multipress_gesture = gtk_gesture_multi_press_new (widget); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (day->multipress_gesture), 0); + g_signal_connect (day->multipress_gesture, "pressed", + G_CALLBACK (day_pressed), day); +} + +static void +gtk_date_chooser_day_dispose (GObject *object) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (object); + + g_clear_object (&day->multipress_gesture); + + G_OBJECT_CLASS (gtk_date_chooser_day_parent_class)->dispose (object); +} + +static gboolean +gtk_date_chooser_day_draw (GtkWidget *widget, + cairo_t *cr) +{ + GtkStyleContext *context; + GtkStateFlags state; + gint x, y, width, height; + + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + + x = 0; + y = 0; + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + gtk_render_background (context, cr, x, y, width, height); + gtk_render_frame (context, cr, x, y, width, height); + + GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->draw (widget, cr); + + if (gtk_widget_has_visible_focus (widget)) + { + GtkBorder border; + + gtk_style_context_get_border (context, state, &border); + gtk_render_focus (context, cr, border.left, border.top, + gtk_widget_get_allocated_width (widget) - border.left - border.right, + gtk_widget_get_allocated_height (widget) - border.top - border.bottom); + } + + return FALSE; +} + +static void +gtk_date_chooser_day_map (GtkWidget *widget) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + + GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->map (widget); + + gdk_window_show (day->event_window); +} + +static void +gtk_date_chooser_day_unmap (GtkWidget *widget) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + + gdk_window_hide (day->event_window); + + GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->unmap (widget); +} + +static void +gtk_date_chooser_day_realize (GtkWidget *widget) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + GtkAllocation allocation; + GdkWindow *window; + GdkWindowAttr attributes; + gint attributes_mask; + + gtk_widget_get_allocation (widget, &allocation); + gtk_widget_set_realized (widget, TRUE); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = allocation.x; + attributes.y = allocation.y; + attributes.width = allocation.width; + attributes.height = allocation.height; + attributes.wclass = GDK_INPUT_ONLY; + attributes.event_mask = gtk_widget_get_events (widget); + attributes.event_mask |= GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_TOUCH_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + window = gtk_widget_get_parent_window (widget); + gtk_widget_set_window (widget, window); + g_object_ref (window); + + day->event_window = gdk_window_new (window, &attributes, attributes_mask); + gtk_widget_register_window (widget, day->event_window); +} + +static void +gtk_date_chooser_day_unrealize (GtkWidget *widget) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + + if (day->event_window) + { + gtk_widget_unregister_window (widget, day->event_window); + gdk_window_destroy (day->event_window); + day->event_window = NULL; + } + + GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->unrealize (widget); +} + +static void +gtk_date_chooser_day_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + + GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->size_allocate (widget, allocation); + + if (gtk_widget_get_realized (widget)) + gdk_window_move_resize (day->event_window, + allocation->x, + allocation->y, + allocation->width, + allocation->height); +} + +static void +gtk_date_chooser_day_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget); + GDateTime *dt; + gchar *text; + + dt = g_date_time_new_local (day->year, day->month + 1 , day->day, 1, 1, 1); + text = g_date_time_format (dt, "%x"); + gtk_selection_data_set_text (selection_data, text, -1); + g_free (text); + g_date_time_unref (dt); +} + +static void +gtk_date_chooser_day_class_init (GtkDateChooserDayClass *class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = gtk_date_chooser_day_dispose; + + widget_class->draw = gtk_date_chooser_day_draw; + widget_class->realize = gtk_date_chooser_day_realize; + widget_class->unrealize = gtk_date_chooser_day_unrealize; + widget_class->map = gtk_date_chooser_day_map; + widget_class->unmap = gtk_date_chooser_day_unmap; + widget_class->key_press_event = gtk_date_chooser_day_key_press; + widget_class->size_allocate = gtk_date_chooser_day_size_allocate; + widget_class->drag_data_get = gtk_date_chooser_day_drag_data_get; + + day_signals[SELECTED] = g_signal_new (I_("selected"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); +} + +GtkWidget * +gtk_date_chooser_day_new (void) +{ + return GTK_WIDGET (g_object_new (GTK_TYPE_DATE_CHOOSER_DAY, NULL)); +} + +void +gtk_date_chooser_day_set_date (GtkDateChooserDay *day, + guint y, + guint m, + guint d) +{ + gchar *text; + + day->year = y; + day->month = m; + day->day = d; + + text = g_strdup_printf ("%d", day->day); + gtk_label_set_label (GTK_LABEL (day->label), text); + g_free (text); +} + +void +gtk_date_chooser_day_get_date (GtkDateChooserDay *day, + guint *y, + guint *m, + guint *d) +{ + *y = day->year; + *m = day->month; + *d = day->day; +} + +void +gtk_date_chooser_day_set_other_month (GtkDateChooserDay *day, + gboolean other_month) +{ + GtkStyleContext *context; + + context = gtk_widget_get_style_context (GTK_WIDGET (day)); + if (other_month) + { + gtk_style_context_add_class (context, "other-month"); + gtk_drag_source_unset (GTK_WIDGET (day)); + } + else + { + gtk_style_context_remove_class (context, "other-month"); + gtk_drag_source_set (GTK_WIDGET (day), + GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, + NULL, 0, + GDK_ACTION_COPY); + gtk_drag_source_add_text_targets (GTK_WIDGET (day)); + } +} + +void +gtk_date_chooser_day_set_selected (GtkDateChooserDay *day, + gboolean selected) +{ + if (selected) + gtk_widget_set_state_flags (GTK_WIDGET (day), GTK_STATE_FLAG_SELECTED, FALSE); + else + gtk_widget_unset_state_flags (GTK_WIDGET (day), GTK_STATE_FLAG_SELECTED); +} diff --git a/gtk/gtkdatechooserdayprivate.h b/gtk/gtkdatechooserdayprivate.h new file mode 100644 index 0000000000..768dd748b8 --- /dev/null +++ b/gtk/gtkdatechooserdayprivate.h @@ -0,0 +1,53 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_DATE_CHOOSER_DAY_PRIVATE_H__ +#define __GTK_DATE_CHOOSER_DAY_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_DATE_CHOOSER_DAY (gtk_date_chooser_day_get_type ()) +#define GTK_DATE_CHOOSER_DAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDay)) +#define GTK_DATE_CHOOSER_DAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDayClass)) +#define GTK_IS_DATE_CHOOSER_DAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DATE_CHOOSER_DAY)) +#define GTK_IS_DATE_CHOOSER_DAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DATE_CHOOSER_DAY)) +#define GTK_DATE_CHOOSER_DAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDayClass)) + + +typedef struct _GtkDateChooserDay GtkDateChooserDay; +typedef struct _GtkDateChooserDayClass GtkDateChooserDayClass; + +GType gtk_date_chooser_day_get_type (void) G_GNUC_CONST; +GtkWidget * gtk_date_chooser_day_new (void); +void gtk_date_chooser_day_set_date (GtkDateChooserDay *widget, + guint year, + guint month, + guint day); +void gtk_date_chooser_day_get_date (GtkDateChooserDay *widget, + guint *year, + guint *month, + guint *day); +void gtk_date_chooser_day_set_other_month (GtkDateChooserDay *day, + gboolean other_month); +void gtk_date_chooser_day_set_selected (GtkDateChooserDay *day, + gboolean selected); + +G_END_DECLS + +#endif /* __GTK_DATE_CHOOSER_DAY_PRIVATE_H__ */ diff --git a/gtk/gtkdatechooserwidget.c b/gtk/gtkdatechooserwidget.c new file mode 100644 index 0000000000..b834c61584 --- /dev/null +++ b/gtk/gtkdatechooserwidget.c @@ -0,0 +1,1005 @@ +/* GTK - The GIMP Toolkit + * + * Copyright (C) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkdatechooserwidget.h" +#include "gtkdatechooserdayprivate.h" +#include "gtkstack.h" +#include "gtklabel.h" +#include "gtkgrid.h" +#include "gtkselection.h" +#include "gtkdnd.h" + +#include "gtkintl.h" +#include "gtkprivate.h" + +#include +#include + + +enum { + MONTH_CHANGED, + DAY_SELECTED, + LAST_SIGNAL +}; + +static guint calendar_signals[LAST_SIGNAL] = { 0, }; + +enum { + PROP_YEAR = 1, + PROP_MONTH, + PROP_DAY, + PROP_SHOW_HEADING, + PROP_SHOW_DAY_NAMES, + PROP_SHOW_WEEK_NUMBERS, + PROP_NO_MONTH_CHANGE, + NUM_PROPERTIES +}; + +static GParamSpec *calendar_properties[NUM_PROPERTIES] = { NULL, }; + +struct _GtkDateChooserWidget +{ + GtkBin parent; + + GtkWidget *month_down_button; + GtkWidget *month_stack; + GtkWidget *month_up_button; + GtkWidget *year_down_button; + GtkWidget *year_stack; + GtkWidget *odd_year_label; + GtkWidget *even_year_label; + GtkWidget *year_up_button; + GtkWidget *grid; + + guint click_id; + GtkWidget *active_button; + + guint year_id; + GtkWidget *active_year_button; + + GtkWidget *day_grid; + GtkWidget *corner; + GtkWidget *cols[7]; + GtkWidget *rows[6]; + GtkWidget *days[6][7]; + + guint month; + guint year; + guint day; + + gint week_start; + + gboolean show_heading; + gboolean show_day_names; + gboolean show_week_numbers; + gboolean no_month_change; +}; + +struct _GtkDateChooserWidgetClass +{ + GtkBinClass parent_class; +}; + + +G_DEFINE_TYPE (GtkDateChooserWidget, gtk_date_chooser_widget, GTK_TYPE_BIN) + +static const guint month_length[2][13] = +{ + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static gboolean +leap (guint year) +{ + return ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)); +} + +static guint +day_of_week (guint year, guint mm, guint dd) +{ + GDateTime *dt; + guint days; + + dt = g_date_time_new_local (year, mm, dd, 1, 1, 1); + if (dt == NULL) + return 0; + + days = g_date_time_get_day_of_week (dt); + g_date_time_unref (dt); + + return days; +} + +static guint +week_of_year (guint year, guint mm, guint dd) +{ + GDateTime *dt; + guint week; + + dt = g_date_time_new_local (year, mm, dd, 1, 1, 1); + if (dt == NULL) + return 1; + + week = g_date_time_get_week_of_year (dt); + g_date_time_unref (dt); + + return week; +} + +static void +calendar_compute_days (GtkDateChooserWidget *calendar) +{ + guint year, month, day; + gint ndays_in_month; + gint ndays_in_prev_month; + gint first_day; + gint row; + gint col; + GtkDateChooserDay *d; + + year = calendar->year; + month = calendar->month + 1; + + ndays_in_month = month_length[leap (year)][month]; + + first_day = day_of_week (year, month, 1); + first_day = (first_day + 7 - calendar->week_start) % 7; + if (first_day == 0) + first_day = 7; + + /* Compute days of previous month */ + if (month > 1) + ndays_in_prev_month = month_length[leap (year)][month - 1]; + else + ndays_in_prev_month = month_length[leap (year - 1)][12]; + day = ndays_in_prev_month - first_day + 1; + + month = (calendar->month + 11) % 12; + year = calendar->year - (month == 11); + + for (col = 0; col < first_day; col++) + { + d = GTK_DATE_CHOOSER_DAY (calendar->days[0][col]); + gtk_date_chooser_day_set_date (d, year, month, day); + gtk_date_chooser_day_set_other_month (d, TRUE); + day++; + } + + /* Compute days of current month */ + row = first_day / 7; + col = first_day % 7; + + month = calendar->month; + year = calendar->year; + + for (day = 1; day <= ndays_in_month; day++) + { + d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]); + gtk_date_chooser_day_set_date (d, year, month, day); + gtk_date_chooser_day_set_other_month (d, FALSE); + + col++; + if (col == 7) + { + row++; + col = 0; + } + } + + /* Compute days of next month */ + + month = (calendar->month + 1) % 12; + year = calendar->year + (month == 0); + + day = 1; + for (; row < 6; row++) + { + for (; col < 7; col++) + { + d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]); + gtk_date_chooser_day_set_date (d, year, month, day); + gtk_date_chooser_day_set_other_month (d, TRUE); + day++; + } + col = 0; + } + + /* update week numbers */ + for (row = 0; row < 6; row++) + { + gchar *text; + guint week; + + d = GTK_DATE_CHOOSER_DAY (calendar->days[row][6]); + gtk_date_chooser_day_get_date (d, &year, &month, &day); + + week = week_of_year (year, month + 1, day); + text = g_strdup_printf ("%d", week); + gtk_label_set_label (GTK_LABEL (calendar->rows[row]), text); + g_free (text); + } +} + +static const gchar *months[] = { + "jan", "feb", "mar", "apr", + "may", "jun", "jul", "aug", + "sep", "oct", "nov", "dec" +}; + +static void +calendar_update_year_display (GtkDateChooserWidget *calendar) +{ + GtkWidget *label; + gchar *text; + GtkWidget *vis; + + vis = gtk_stack_get_visible_child (GTK_STACK (calendar->year_stack)); + if (vis == calendar->odd_year_label) + label = calendar->even_year_label; + else + label = calendar->odd_year_label; + + text = g_strdup_printf ("%d", calendar->year); + gtk_label_set_label (GTK_LABEL (label), text); + g_free (text); + + gtk_stack_set_visible_child (GTK_STACK (calendar->year_stack), label); +} + +static void +calendar_update_month_display (GtkDateChooserWidget *calendar, + GtkStackTransitionType transition) +{ + gtk_stack_set_visible_child_full (GTK_STACK (calendar->month_stack), + months[calendar->month], + transition); +} + +static gchar * +calendar_get_weekday_name (gint i) +{ + time_t time; + gchar buffer[128]; + + time = (i + 3) * 86400; + strftime (buffer, sizeof (buffer), "%a", gmtime (&time)); + return g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL); +} + +static gchar * +calendar_get_month_name (gint i) +{ + time_t time; + gchar buffer[128]; + + time = i * 2764800; + strftime (buffer, sizeof (buffer), "%B", gmtime (&time)); + return g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL); +} + +static void +calendar_init_weekday_display (GtkDateChooserWidget *calendar) +{ + gint i; + gchar *text; + + for (i = 0; i < 7; i++) + { + text = calendar_get_weekday_name ((i + calendar->week_start) % 7); + gtk_label_set_label (GTK_LABEL (calendar->cols[i]), text); + g_free (text); + } +} + +static void +calendar_init_month_display (GtkDateChooserWidget *calendar) +{ + gint i; + GtkWidget *label; + gchar *text; + + for (i = 0; i < 12; i++) + { + text = calendar_get_month_name (i); + label = gtk_label_new (text); + gtk_widget_show (label); + gtk_stack_add_named (GTK_STACK (calendar->month_stack), label, months[i]); + g_free (text); + } +} + +static void +calendar_update_selected_day_display (GtkDateChooserWidget *calendar) +{ + gint row, col; + GtkDateChooserDay *d; + guint year, month, day; + + for (row = 0; row < 6; row++) + for (col = 0; col < 7; col++) + { + d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]); + gtk_date_chooser_day_get_date (d, &year, &month, &day); + gtk_date_chooser_day_set_selected (d, day == calendar->day && + month == calendar->month && + year == calendar->year); + } +} + +static void +calendar_update_selected_day (GtkDateChooserWidget *calendar) +{ + gint month_len; + + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + if (month_len < calendar->day) + gtk_date_chooser_widget_select_day (calendar, month_len); + else + calendar_update_selected_day_display (calendar); +} + +static void +calendar_set_year_prev (GtkDateChooserWidget *calendar) +{ + if (calendar->no_month_change) + return; + + calendar->year -= 1; + calendar_update_year_display (calendar); + + calendar_compute_days (calendar); + + g_signal_emit (calendar, calendar_signals[MONTH_CHANGED], 0); + + calendar_update_selected_day (calendar); +} + +static void +calendar_set_year_next (GtkDateChooserWidget *calendar) +{ + if (calendar->no_month_change) + return; + + calendar->year += 1; + calendar_update_year_display (calendar); + + calendar_compute_days (calendar); + + g_signal_emit (calendar, calendar_signals[MONTH_CHANGED], 0); + + calendar_update_selected_day (calendar); +} + +static void +calendar_set_month_prev (GtkDateChooserWidget *calendar) +{ + if (calendar->no_month_change) + return; + + calendar->month = (calendar->month + 11) % 12; + calendar_update_month_display (calendar, GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT); + + if (calendar->month == 11) + { + calendar->year -= 1; + calendar_update_year_display (calendar); + } + + calendar_compute_days (calendar); + + g_signal_emit (calendar, calendar_signals[MONTH_CHANGED], 0); + + calendar_update_selected_day (calendar); +} + +static void +calendar_set_month_next (GtkDateChooserWidget *calendar) +{ + if (calendar->no_month_change) + return; + + calendar->month = (calendar->month + 1) % 12; + calendar_update_month_display (calendar, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT); + + if (calendar->month == 0) + { + calendar->year += 1; + calendar_update_year_display (calendar); + } + + calendar_compute_days (calendar); + + g_signal_emit (calendar, calendar_signals[MONTH_CHANGED], 0); + + calendar_update_selected_day (calendar); +} + +static gint +calendar_get_week_start (void) +{ + union { unsigned int word; char *string; } langinfo; + gint week_1stday = 0; + gint first_weekday = 1; + guint week_origin; + + langinfo.string = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); + first_weekday = langinfo.string[0]; + langinfo.string = nl_langinfo (_NL_TIME_WEEK_1STDAY); + week_origin = langinfo.word; + if (week_origin == 19971130) /* Sunday */ + week_1stday = 0; + else if (week_origin == 19971201) /* Monday */ + week_1stday = 1; + else + g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.\n"); + + return (week_1stday + first_weekday - 1) % 7; +} + +static void +day_selected_cb (GtkDateChooserDay *d, + GtkDateChooserWidget *calendar) +{ + guint year, month, day; + + gtk_date_chooser_day_get_date (d, &year, &month, &day); + + if ((month + 1) % 12 == calendar->month) + calendar_set_month_prev (calendar); + else if ((calendar->month + 1) % 12 == month) + calendar_set_month_next (calendar); + + gtk_date_chooser_widget_select_day (calendar, day); +} + +static void +gtk_date_chooser_widget_init (GtkDateChooserWidget *calendar) +{ + gint row, col; + GDateTime *now; + + calendar->show_heading = TRUE; + calendar->show_day_names = TRUE; + calendar->show_week_numbers = TRUE; + calendar->no_month_change = FALSE; + + now = g_date_time_new_now_local (); + calendar->year = g_date_time_get_year (now); + calendar->month = g_date_time_get_month (now) - 1; + calendar->day = g_date_time_get_day_of_month (now); + g_date_time_unref (now); + + calendar->week_start = calendar_get_week_start (); + + gtk_widget_init_template (GTK_WIDGET (calendar)); + + for (col = 0; col < 7; col++) + { + calendar->cols[col] = gtk_label_new (""); + g_object_bind_property (calendar, "show-day-names", + calendar->cols[col], "visible", + G_BINDING_SYNC_CREATE); + gtk_style_context_add_class (gtk_widget_get_style_context (calendar->cols[col]), "weekday"); + gtk_grid_attach (GTK_GRID (calendar->grid), calendar->cols[col], col, -1, 1, 1); + } + + for (row = 0; row < 6; row++) + { + calendar->rows[row] = gtk_label_new (""); + g_object_bind_property (calendar, "show-week-numbers", + calendar->rows[row], "visible", + G_BINDING_SYNC_CREATE); + gtk_label_set_xalign (GTK_LABEL (calendar->rows[row]), 1.0); + gtk_widget_show (calendar->rows[row]); + gtk_style_context_add_class (gtk_widget_get_style_context (calendar->rows[row]), "weeknum"); + gtk_grid_attach (GTK_GRID (calendar->grid), calendar->rows[row], -1, row, 1, 1); + } + + calendar->corner = gtk_label_new (""); + gtk_style_context_add_class (gtk_widget_get_style_context (calendar->corner), "weekday"); + gtk_grid_attach (GTK_GRID (calendar->grid), calendar->corner, -1, -1, 1, 1); + + calendar->day_grid = gtk_grid_new (); + gtk_widget_show (calendar->day_grid); + gtk_widget_set_halign (calendar->day_grid, GTK_ALIGN_FILL); + gtk_widget_set_valign (calendar->day_grid, GTK_ALIGN_FILL); + gtk_grid_attach (GTK_GRID (calendar->grid), calendar->day_grid, 0, 0, 7, 6); + + for (row = 0; row < 6; row++) + for (col = 0; col < 7; col++) + { + calendar->days[row][col] = gtk_date_chooser_day_new (); + g_signal_connect (calendar->days[row][col], "selected", G_CALLBACK (day_selected_cb), calendar); + gtk_widget_show (calendar->days[row][col]); + gtk_grid_attach (GTK_GRID (calendar->day_grid), calendar->days[row][col], col, row, 1, 1); + } + + calendar_init_month_display (calendar); + calendar_init_weekday_display (calendar); + + calendar_compute_days (calendar); + calendar_update_month_display (calendar, GTK_STACK_TRANSITION_TYPE_NONE); + calendar_update_year_display (calendar); + calendar_update_selected_day_display (calendar); + + gtk_drag_dest_set (GTK_WIDGET (calendar), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_text_targets (GTK_WIDGET (calendar)); +} + +static void +calendar_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (obj); + + switch (property_id) + { + case PROP_YEAR: + gtk_date_chooser_widget_set_date (calendar, g_value_get_int (value), calendar->month, calendar->day); + break; + case PROP_MONTH: + gtk_date_chooser_widget_set_date (calendar, calendar->year, g_value_get_int (value), calendar->day); + break; + case PROP_DAY: + gtk_date_chooser_widget_set_date (calendar, calendar->year, calendar->month, g_value_get_int (value)); + break; + case PROP_SHOW_HEADING: + gtk_date_chooser_widget_set_show_heading (calendar, g_value_get_boolean (value)); + break; + case PROP_SHOW_DAY_NAMES: + gtk_date_chooser_widget_set_show_day_names (calendar, g_value_get_boolean (value)); + break; + case PROP_SHOW_WEEK_NUMBERS: + gtk_date_chooser_widget_set_show_week_numbers (calendar, g_value_get_boolean (value)); + break; + case PROP_NO_MONTH_CHANGE: + gtk_date_chooser_widget_set_no_month_change (calendar, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + break; + } +} + +static void +calendar_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (obj); + + switch (property_id) + { + case PROP_YEAR: + g_value_set_int (value, calendar->year); + break; + case PROP_MONTH: + g_value_set_int (value, calendar->month); + break; + case PROP_DAY: + g_value_set_int (value, calendar->day); + break; + case PROP_SHOW_HEADING: + g_value_set_boolean (value, calendar->show_heading); + break; + case PROP_SHOW_DAY_NAMES: + g_value_set_boolean (value, calendar->show_day_names); + break; + case PROP_SHOW_WEEK_NUMBERS: + g_value_set_boolean (value, calendar->show_week_numbers); + break; + case PROP_NO_MONTH_CHANGE: + g_value_set_boolean (value, calendar->no_month_change); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + break; + } +} + +static gboolean +calendar_button_activate (GtkDateChooserWidget *calendar, + GtkWidget *button) +{ + if (button == calendar->month_down_button) + calendar_set_month_prev (calendar); + else if (button == calendar->month_up_button) + calendar_set_month_next (calendar); + else if (button == calendar->year_down_button) + calendar_set_year_prev (calendar); + else if (button == calendar->year_up_button) + calendar_set_year_next (calendar); + else + g_assert_not_reached (); + + return TRUE; +} + +static gboolean +calendar_button_timeout (gpointer user_data) +{ + GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (user_data); + gboolean res; + + if (calendar->click_id == 0) + return G_SOURCE_REMOVE; + + res = calendar_button_activate (calendar, calendar->active_button); + if (!res) + { + g_source_remove (calendar->click_id); + calendar->click_id = 0; + } + + return res; +} + +static gboolean +calendar_button_press_cb (GtkWidget *widget, + GdkEventButton *button, + GtkDateChooserWidget *calendar) +{ + gint double_click_time; + + g_object_get (gtk_widget_get_settings (widget), + "gtk-double-click-time", &double_click_time, + NULL); + + if (calendar->click_id != 0) + g_source_remove (calendar->click_id); + + calendar->active_button = widget; + + calendar->click_id = gdk_threads_add_timeout (double_click_time, + calendar_button_timeout, + calendar); + g_source_set_name_by_id (calendar->click_id, "[gtk+] calendar_button_timeout"); + calendar_button_timeout (calendar); + + return TRUE; +} + +static gboolean +calendar_button_release_cb (GtkWidget *widget, + GdkEventButton *event, + GtkDateChooserWidget *calendar) +{ + if (calendar->click_id != 0) + { + g_source_remove (calendar->click_id); + calendar->click_id = 0; + } + + calendar->active_button = NULL; + + return TRUE; +} + +static void +calendar_clicked_cb (GtkWidget *widget, + GtkDateChooserWidget *calendar) +{ + if (calendar->click_id != 0) + return; + + calendar_button_activate (calendar, widget); +} + +static void +calendar_dispose (GObject *object) +{ + GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (object); + + if (calendar->click_id != 0) + { + g_source_remove (calendar->click_id); + calendar->click_id = 0; + } + + G_OBJECT_CLASS (gtk_date_chooser_widget_parent_class)->dispose (object); +} + +static void +calendar_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (widget); + gchar *text; + GDate *date; + guint year, month, day; + + date = g_date_new (); + text = (gchar *)gtk_selection_data_get_text (selection_data); + if (text) + { + g_date_set_parse (date, text); + g_free (text); + } + if (!g_date_valid (date)) + { + g_date_free (date); + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + year = g_date_get_year (date); + month = g_date_get_month (date) - 1; + day = g_date_get_day (date); + + g_date_free (date); + + gtk_drag_finish (context, TRUE, FALSE, time); + + if (!calendar->show_heading || calendar->no_month_change) + { + year = calendar->year; + month = calendar->month; + } + gtk_date_chooser_widget_set_date (calendar, year, month, day); +} + +static void +gtk_date_chooser_widget_class_init (GtkDateChooserWidgetClass *class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = calendar_dispose; + object_class->set_property = calendar_set_property; + object_class->get_property = calendar_get_property; + + widget_class->drag_data_received = calendar_drag_data_received; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkdatechooserwidget.ui"); + + calendar_properties[PROP_YEAR] = + g_param_spec_int ("year", P_("Year"), P_("The selected year"), + 0, G_MAXINT >> 9, 0, + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + calendar_properties[PROP_MONTH] = + g_param_spec_int ("month", P_("Month"), P_("The selected month (as a number between 0 and 11)"), + 0, 11, 0, + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + calendar_properties[PROP_DAY] = + g_param_spec_int ("day", P_("Day"), P_("The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)"), + 0, 31, 0, + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + calendar_properties[PROP_SHOW_HEADING] = + g_param_spec_boolean ("show-heading", P_("Show Heading"), P_("If TRUE, a heading is displayed"), + TRUE, G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + calendar_properties[PROP_SHOW_DAY_NAMES] = + g_param_spec_boolean ("show-day-names", P_("Show Day Names"), P_("If TRUE, day names are displayed"), + TRUE, G_PARAM_READWRITE); + calendar_properties[PROP_SHOW_WEEK_NUMBERS] = + g_param_spec_boolean ("show-week-numbers", P_("Show Week Numbers"), P_("If TRUE, week numbers are displayed"), + TRUE, G_PARAM_READWRITE); + calendar_properties[PROP_NO_MONTH_CHANGE] = + g_param_spec_boolean ("no-month-change", P_("No Month Change"), P_("If TRUE, the selected month cannot be changed"), + FALSE, G_PARAM_READWRITE); + g_object_class_install_properties (object_class, NUM_PROPERTIES, calendar_properties); + + calendar_signals[MONTH_CHANGED] = g_signal_new (I_("month-changed"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + calendar_signals[DAY_SELECTED] = g_signal_new (I_("day-selected"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, month_down_button); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, month_stack); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, month_up_button); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, year_down_button); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, year_stack); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, odd_year_label); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, even_year_label); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, year_up_button); + gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, grid); + + gtk_widget_class_bind_template_callback (widget_class, calendar_button_press_cb); + gtk_widget_class_bind_template_callback (widget_class, calendar_button_release_cb); + gtk_widget_class_bind_template_callback (widget_class, calendar_clicked_cb); +} + +GtkWidget * +gtk_date_chooser_widget_new (void) +{ + return GTK_WIDGET (g_object_new (GTK_TYPE_DATE_CHOOSER_WIDGET, NULL)); +} + +void +gtk_date_chooser_widget_set_show_heading (GtkDateChooserWidget *calendar, + gboolean setting) +{ + if (calendar->show_heading == setting) + return; + + calendar->show_heading = setting; + + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_SHOW_HEADING]); +} + +gboolean +gtk_date_chooser_widget_get_show_heading (GtkDateChooserWidget *calendar) +{ + return calendar->show_heading; +} + +void +gtk_date_chooser_widget_set_show_day_names (GtkDateChooserWidget *calendar, + gboolean setting) +{ + if (calendar->show_day_names == setting) + return; + + calendar->show_day_names = setting; + + gtk_widget_set_visible (calendar->corner, calendar->show_day_names && calendar->show_week_numbers); + + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_SHOW_DAY_NAMES]); +} + +gboolean +gtk_date_chooser_widget_get_show_day_names (GtkDateChooserWidget *calendar) +{ + return calendar->show_day_names; +} + +void +gtk_date_chooser_widget_set_show_week_numbers (GtkDateChooserWidget *calendar, + gboolean setting) +{ + if (calendar->show_week_numbers == setting) + return; + + calendar->show_week_numbers = setting; + + gtk_widget_set_visible (calendar->corner, calendar->show_day_names && calendar->show_week_numbers); + + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_SHOW_WEEK_NUMBERS]); +} + +gboolean +gtk_date_chooser_widget_get_show_week_numbers (GtkDateChooserWidget *calendar) +{ + return calendar->show_week_numbers; +} + +void +gtk_date_chooser_widget_set_no_month_change (GtkDateChooserWidget *calendar, + gboolean setting) +{ + if (calendar->no_month_change == setting) + return; + + calendar->no_month_change = setting; + + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_NO_MONTH_CHANGE]); +} + +gboolean +gtk_date_chooser_widget_get_no_month_change (GtkDateChooserWidget *calendar) +{ + return calendar->no_month_change; +} + +void +gtk_date_chooser_widget_set_date (GtkDateChooserWidget *calendar, + guint year, + guint month, + guint day) +{ + gboolean month_changed = FALSE; + gboolean day_changed = FALSE; + g_object_freeze_notify (G_OBJECT (calendar)); + + if (calendar->year != year) + { + month_changed = TRUE; + calendar->year = year; + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_YEAR]); + calendar_update_year_display (calendar); + } + + if (calendar->month != month) + { + month_changed = TRUE; + calendar->month = month; + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_MONTH]); + calendar_update_month_display (calendar, GTK_STACK_TRANSITION_TYPE_NONE); + } + + if (calendar->day != day) + { + day_changed = TRUE; + calendar->day = day; + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_DAY]); + } + + if (month_changed) + calendar_compute_days (calendar); + + if (month_changed || day_changed) + { + calendar_update_selected_day (calendar); + g_signal_emit (calendar, calendar_signals[DAY_SELECTED], 0); + } + + g_object_thaw_notify (G_OBJECT (calendar)); +} + +void +gtk_date_chooser_widget_select_month (GtkDateChooserWidget *calendar, + guint year, + guint month) +{ + gtk_date_chooser_widget_set_date (calendar, year, month, calendar->day); +} + +void +gtk_date_chooser_widget_select_day (GtkDateChooserWidget *calendar, + guint day) +{ + if (calendar->day == day) + return; + + calendar->day = day; + + calendar_update_selected_day_display (calendar); + + g_signal_emit (calendar, calendar_signals[DAY_SELECTED], 0); + g_object_notify_by_pspec (G_OBJECT (calendar), + calendar_properties[PROP_DAY]); +} + +void +gtk_date_chooser_widget_get_date (GtkDateChooserWidget *calendar, + guint *year, + guint *month, + guint *day) +{ + *year = calendar->year; + *month = calendar->month; + *day = calendar->day; +} diff --git a/gtk/gtkdatechooserwidget.h b/gtk/gtkdatechooserwidget.h new file mode 100644 index 0000000000..9cd9f8f09b --- /dev/null +++ b/gtk/gtkdatechooserwidget.h @@ -0,0 +1,93 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_DATE_CHOOSER_WIDGET_H__ +#define __GTK_DATE_CHOOSER_WIDGET_H__ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +#ifndef GDK_AVAILABLE_IN_3_20 +#define GDK_AVAILABLE_IN_3_20 _GDK_EXTERN +#endif + +G_BEGIN_DECLS + +#define GTK_TYPE_DATE_CHOOSER_WIDGET (gtk_date_chooser_widget_get_type ()) +#define GTK_DATE_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidget)) +#define GTK_DATE_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidgetClass)) +#define GTK_IS_DATE_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET)) +#define GTK_IS_DATE_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DATE_CHOOSER_WIDGET)) +#define GTK_DATE_CHOOSER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidgetClass)) + +typedef struct _GtkDateChooserWidget GtkDateChooserWidget; +typedef struct _GtkDateChooserWidgetClass GtkDateChooserWidgetClass; + +GDK_AVAILABLE_IN_3_20 +GType gtk_date_chooser_widget_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_3_20 +GtkWidget * gtk_date_chooser_widget_new (void); + + +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_select_month (GtkDateChooserWidget *chooser, + guint year, + guint month); + +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_select_day (GtkDateChooserWidget *chooser, + guint day); + +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_set_date (GtkDateChooserWidget *chooser, + guint year, + guint month, + guint day); +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_get_date (GtkDateChooserWidget *chooser, + guint *year, + guint *month, + guint *day); + + +void gtk_date_chooser_widget_set_no_month_change (GtkDateChooserWidget *chooser, + gboolean setting); + +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_set_show_heading (GtkDateChooserWidget *chooser, + gboolean setting); +GDK_AVAILABLE_IN_3_20 +gboolean gtk_date_chooser_widget_get_show_heading (GtkDateChooserWidget *chooser); +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_set_show_day_names (GtkDateChooserWidget *chooser, + gboolean setting); +GDK_AVAILABLE_IN_3_20 +gboolean gtk_date_chooser_widget_get_show_day_names (GtkDateChooserWidget *chooser); + +GDK_AVAILABLE_IN_3_20 +void gtk_date_chooser_widget_set_show_week_numbers (GtkDateChooserWidget *chooser, + gboolean setting); +GDK_AVAILABLE_IN_3_20 +gboolean gtk_date_chooser_widget_get_show_week_numbers (GtkDateChooserWidget *chooser); + +G_END_DECLS + +#endif /* __GTK_DATE_CHOOSER_WIDGET_H__ */ diff --git a/gtk/ui/gtkdatechooserwidget.ui b/gtk/ui/gtkdatechooserwidget.ui new file mode 100644 index 0000000000..3dc7e9fbce --- /dev/null +++ b/gtk/ui/gtkdatechooserwidget.ui @@ -0,0 +1,153 @@ + + + + + +