date-selector: move to use the new date chooser

After adding the new GcalDateChooser widget, change the
current date selector to use it as the internal widget
of the popover.

The next logical step is turning GcalDateSelector into
an entry.
This commit is contained in:
Georges Basile Stavracas Neto
2016-07-23 17:47:11 -03:00
parent c2dca8a3dc
commit 4ef9f75dfb
2 changed files with 25 additions and 426 deletions
+5 -117
View File
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<template class="GcalDateSelector" parent="GtkMenuButton">
@@ -13,124 +12,13 @@
</template>
<object class="GtkPopover" id="date_selector_popover">
<property name="position">bottom</property>
<property name="border_width">12</property>
<child>
<object class="GtkGrid" id="grid">
<object class="GcalDateChooser" id="date_chooser">
<property name="visible">True</property>
<property name="border_width">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkCalendar" id="calendar">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_week_numbers">True</property>
<signal name="day-selected" handler="calendar_day_selected" object="GcalDateSelector" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="max_width_chars">4</property>
<property name="xalign">0.5</property>
<property name="input_purpose">number</property>
<signal name="insert-text" handler="text_inserted" object="GcalDateSelector" swapped="no"/>
<signal name="focus-out-event" handler="date_entry_focus_out" object="GcalDateSelector" swapped="no"/>
<signal name="activate" handler="entry_activated" object="GcalDateSelector" swapped="no"/>
</object>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="max_width_chars">4</property>
<property name="xalign">0.5</property>
<property name="input_purpose">number</property>
<signal name="insert-text" handler="text_inserted" object="GcalDateSelector" swapped="no"/>
<signal name="focus-out-event" handler="date_entry_focus_out" object="GcalDateSelector" swapped="no"/>
<signal name="activate" handler="entry_activated" object="GcalDateSelector" swapped="no"/>
<style>
<class name="middle-entry"/>
</style>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">4</property>
<property name="width_chars">4</property>
<property name="max_width_chars">4</property>
<property name="xalign">0.5</property>
<property name="input_purpose">number</property>
<signal name="insert-text" handler="text_inserted" object="GcalDateSelector" swapped="no"/>
<signal name="focus-out-event" handler="date_entry_focus_out" object="GcalDateSelector" swapped="no"/>
<signal name="activate" handler="entry_activated" object="GcalDateSelector" swapped="no"/>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">3</property>
</packing>
</child>
<property name="can_focus">True</property>
<property name="show_week_numbers">True</property>
<signal name="day-selected" handler="calendar_day_selected" object="GcalDateSelector" swapped="yes"/>
</object>
</child>
</object>
+20 -309
View File
@@ -17,6 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gcal-date-chooser.h"
#include "gcal-date-selector.h"
#include <locale.h>
@@ -24,35 +25,13 @@
#include <stdlib.h>
#include <glib/gi18n.h>
enum
{
DAY,
MONTH,
YEAR,
NUM_ENTRIES
};
struct _GcalDateSelector
{
GtkMenuButton parent;
/* widgets */
GtkWidget *date_chooser;
GtkWidget *date_label;
GtkWidget *calendar;
GtkWidget *grid;
GtkWidget *entries[NUM_ENTRIES];
/* date */
GDateTime *date;
/* misc */
const gchar *mask;
/* index in the mask starting by 0 */
guint day_pos;
guint month_pos;
guint year_pos;
};
enum
@@ -62,136 +41,29 @@ enum
LAST_PROP
};
static void calendar_day_selected (GtkCalendar *calendar,
GcalDateSelector *selector);
static gboolean date_entry_focus_out (GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
static void entry_activated (GtkEntry *entry,
gpointer user_data);
static void parse_entries (GcalDateSelector *selector);
static void text_inserted (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position,
gpointer user_data);
static void gcal_date_selector_constructed (GObject *object);
G_DEFINE_TYPE (GcalDateSelector, gcal_date_selector, GTK_TYPE_MENU_BUTTON);
static void
calendar_day_selected (GtkCalendar *calendar,
GcalDateSelector *selector)
update_label (GcalDateSelector *self)
{
GDateTime *new_date;
guint day, month, year;
GDateTime *date;
gchar *label;
gtk_calendar_get_date (calendar, &year, &month, &day);
date = gcal_date_chooser_get_date (GCAL_DATE_CHOOSER (self->date_chooser));
new_date = g_date_time_new_local (year, month + 1, day, 0, 0, 0);
/* rebuild the date label */
label = g_date_time_format (date, "%x");
/**
* Block signal handler to avoid an infinite
* recursion, exploding the proccess stack.
*/
g_signal_handlers_block_by_func (selector->calendar, calendar_day_selected, selector);
gcal_date_selector_set_date (selector, new_date);
g_signal_handlers_unblock_by_func (selector->calendar, calendar_day_selected, selector);
g_clear_pointer (&new_date, g_date_time_unref);
}
static gboolean
date_entry_focus_out (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
parse_entries (GCAL_DATE_SELECTOR (user_data));
return FALSE;
gtk_label_set_label (GTK_LABEL (self->date_label), label);
g_free (label);
}
static void
entry_activated (GtkEntry *entry,
gpointer user_data)
calendar_day_selected (GcalDateSelector *self)
{
parse_entries (GCAL_DATE_SELECTOR (user_data));
}
update_label (self);
static void
parse_entries (GcalDateSelector *selector)
{
GDateTime *new_date;
gint day, month, year;
day = atoi (gtk_entry_get_text (GTK_ENTRY (selector->entries[DAY])));
month = atoi (gtk_entry_get_text (GTK_ENTRY (selector->entries[MONTH])));
year = atoi (gtk_entry_get_text (GTK_ENTRY (selector->entries[YEAR])));
new_date = g_date_time_new_local (year, month, day, 0, 0, 0);
/* select the date */
g_signal_handlers_block_by_func (selector->calendar, calendar_day_selected, selector);
gcal_date_selector_set_date (selector, new_date);
g_signal_handlers_unblock_by_func (selector->calendar, calendar_day_selected, selector);
g_clear_pointer (&new_date, g_date_time_unref);
}
static void
text_inserted (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gint *position,
gpointer user_data)
{
GtkEntryBuffer *buffer;
gchar* new_label;
gint i;
gint current_length, max_length;
gboolean valid;
valid = TRUE;
buffer = gtk_entry_get_buffer (GTK_ENTRY (editable));
current_length = gtk_entry_buffer_get_length (buffer);
max_length = gtk_entry_get_max_length (GTK_ENTRY (editable));
/* honor max length property */
if (current_length + new_text_length > max_length)
return;
/* stop the default implementation */
g_signal_stop_emission (editable, g_signal_lookup ("insert-text", GTK_TYPE_ENTRY), 0);
for (i = 0; i < new_text_length; i++)
{
gchar c;
c = *(new_text + i);
/* trying to insert a non-numeric char */
if (c < '0' || c > '9')
{
valid = FALSE;
break;
}
}
if (!valid)
return;
new_label = g_strdup_printf ("%s%s", gtk_entry_buffer_get_text (buffer), new_text);
gtk_entry_buffer_set_text (buffer, new_label, current_length + new_text_length);
*position = *position + new_text_length;
g_free (new_label);
g_object_notify (G_OBJECT (self), "date");
}
static void
@@ -205,7 +77,7 @@ gcal_date_selector_get_property (GObject *object,
switch (prop_id)
{
case PROP_DATE:
g_value_set_boxed (value, self->date);
g_value_set_boxed (value, gcal_date_chooser_get_date (GCAL_DATE_CHOOSER (self->date_chooser)));
break;
default:
@@ -238,7 +110,6 @@ gcal_date_selector_class_init (GcalDateSelectorClass *klass)
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gcal_date_selector_constructed;
object_class->get_property = gcal_date_selector_get_property;
object_class->set_property = gcal_date_selector_set_property;
@@ -257,135 +128,19 @@ gcal_date_selector_class_init (GcalDateSelectorClass *klass)
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/calendar/date-selector.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalDateSelector, date_chooser);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalDateSelector, date_label);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalDateSelector, calendar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalDateSelector, grid);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), text_inserted);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), date_entry_focus_out);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), entry_activated);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), calendar_day_selected);
}
static void
gcal_date_selector_init (GcalDateSelector *self)
{
GDateTime *now;
gint i, d_index, max;
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
gtk_widget_init_template (GTK_WIDGET (self));
now = g_date_time_new_now_local ();
self->date = g_date_time_new_local (g_date_time_get_year (now),
g_date_time_get_month (now),
g_date_time_get_day_of_month (now),
0, 0, 0);
/* This string represents day/month/year order for each of the different
* languages. It could possibly be default value, %m/%d/%y placing the month
* before, or any ordering according to the translator's environment. */
self->mask = g_dpgettext2 ("glib20", "GDateTime", "%m/%d/%y");
/**
* Translators: Select the day, month and year indexes. This will
* be used later on to map the date entries to the
* corresponding indexes. I should have added more validations here.
*/
max = strlen (self->mask);
if (max != 8)
{
/* I'll assume an error and bail out with the default values */
self->day_pos = 0;
self->month_pos = 1;
self->year_pos = 2;
return;
}
d_index = 0;
for (i = 0; i < max; i++)
{
gchar c;
c = *(self->mask + i);
/* No need to check these common separators */
if (c == '%' || c == '-' || c == '/' || c == '.')
continue;
switch (c)
{
/* day */
case 'a':
case 'A':
case 'd':
case 'e':
case 'j':
case 'u':
case 'w':
self->day_pos = d_index++;
break;
/* month */
case 'b':
case 'B':
case 'm':
self->month_pos = d_index++;
break;
/* year */
case 'y':
case 'Y':
self->year_pos = d_index++;
break;
}
}
}
static void
gcal_date_selector_constructed (GObject *object)
{
GcalDateSelector *self;
GtkWidget *label, *box;
GList *l, *aux;
self = GCAL_DATE_SELECTOR (object);
/* chaining up */
G_OBJECT_CLASS (gcal_date_selector_parent_class)->constructed (object);
/* set labels, on the first row */
label = gtk_grid_get_child_at (GTK_GRID (self->grid), self->day_pos, 0);
gtk_label_set_text (GTK_LABEL (label), _("Day"));
label = gtk_grid_get_child_at (GTK_GRID (self->grid), self->month_pos, 0);
gtk_label_set_text (GTK_LABEL (label), _("Month"));
label = gtk_grid_get_child_at (GTK_GRID (self->grid), self->year_pos, 0);
gtk_label_set_text (GTK_LABEL (label), _("Year"));
/* retrieve components from UI definition: entries */
box = gtk_grid_get_child_at (GTK_GRID (self->grid), 0, 1);
aux = gtk_container_get_children (GTK_CONTAINER (box));
for (l = aux; l != NULL; l = g_list_next (l))
{
gint position;
gtk_container_child_get (GTK_CONTAINER (box), l->data, "position", &position, NULL);
if (position == self->day_pos)
self->entries[DAY] = l->data;
if (position == self->month_pos)
self->entries[MONTH] = l->data;
if (position == self->year_pos)
self->entries[YEAR] = l->data;
if (position == self->day_pos || position == self->month_pos)
gtk_entry_set_max_length (GTK_ENTRY (l->data), 2);
}
g_list_free (aux);
gtk_widget_set_direction (box, GTK_TEXT_DIR_LTR);
gtk_widget_set_direction (self->grid, GTK_TEXT_DIR_LTR);
}
/* Public API */
@@ -408,55 +163,11 @@ gcal_date_selector_set_date (GcalDateSelector *selector,
{
g_return_if_fail (GCAL_IS_DATE_SELECTOR (selector));
if (selector->date != date)
{
gchar *label;
/* set calendar's date */
gcal_date_chooser_set_date (GCAL_DATE_CHOOSER (selector->date_chooser), date);
g_clear_pointer (&selector->date, g_date_time_unref);
selector->date = g_date_time_new_local (g_date_time_get_year (date),
g_date_time_get_month (date),
g_date_time_get_day_of_month (date),
0, 0, 0);
/* set calendar's date */
g_signal_handlers_block_by_func (selector->calendar, calendar_day_selected, selector);
g_object_set (selector->calendar,
"day", g_date_time_get_day_of_month (date),
"month", g_date_time_get_month (date) - 1,
"year", g_date_time_get_year (date),
NULL);
g_signal_handlers_unblock_by_func (selector->calendar, calendar_day_selected, selector);
/* rebuild the date label */
label = g_date_time_format (date, selector->mask);
gtk_label_set_label (GTK_LABEL (selector->date_label), label);
g_free (label);
/* set date entries' text */
/* day entry */
label = g_date_time_format (date, "%d");
gtk_entry_set_text (GTK_ENTRY (selector->entries[DAY]), label);
g_free (label);
/* month entry */
label = g_date_time_format (date, "%m");
gtk_entry_set_text (GTK_ENTRY (selector->entries[MONTH]), label);
g_free (label);
/* year entry */
label = g_date_time_format (date, "%Y");
gtk_entry_set_text (GTK_ENTRY (selector->entries[YEAR]), label);
g_free (label);
/* emit the MODIFIED signal */
g_object_notify (G_OBJECT (selector), "date");
}
/* emit the MODIFIED signal */
g_object_notify (G_OBJECT (selector), "date");
}
/**
@@ -472,5 +183,5 @@ gcal_date_selector_get_date (GcalDateSelector *selector)
{
g_return_val_if_fail (GCAL_IS_DATE_SELECTOR (selector), NULL);
return selector->date;
return gcal_date_chooser_get_date (GCAL_DATE_CHOOSER (selector->date_chooser));
}