month-view: selection across months
In this commit we change the data type of start_mark_cell and end_mark_cell to GDateTime from gint Currently, the mark_cell's are gint and while moving across months, they cause a problem as they don't take the new month into consideration but the cell value of the selector. To fix this, we changed the data type of the mark_cell's and modified all the functions dependant on it. https://bugzilla.gnome.org/show_bug.cgi?id=763641
This commit is contained in:
committed by
Georges Basile Stavracas Neto
parent
640b326de6
commit
a3cbaf1e81
+115
-65
@@ -62,8 +62,8 @@ typedef struct
|
||||
* These keeps the cell index, meaning 0 for left top, 1 for the next in the row from left to right, etc.
|
||||
* Note that this does not take into account the disabled row before the first active row.
|
||||
*/
|
||||
gint start_mark_cell;
|
||||
gint end_mark_cell;
|
||||
GDateTime *start_mark_cell;
|
||||
GDateTime *end_mark_cell;
|
||||
|
||||
/**
|
||||
* This flags signals when the cursor is over an overflow indicator and when once has been clicked
|
||||
@@ -177,6 +177,8 @@ static GList* gcal_month_view_get_children_by_uuid (GcalView *vie
|
||||
|
||||
static void gcal_view_interface_init (GcalViewInterface *iface);
|
||||
|
||||
static void cancel_selection (GcalMonthView *month_view);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GcalMonthView, gcal_month_view,GCAL_TYPE_SUBSCRIBER_VIEW,
|
||||
G_ADD_PRIVATE (GcalMonthView)
|
||||
G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init));
|
||||
@@ -191,6 +193,19 @@ real_cell (gint cell,
|
||||
return rtl ? MIRROR (cell, 0, 7) - 1 : cell;
|
||||
}
|
||||
|
||||
static void
|
||||
cancel_selection (GcalMonthView *month_view)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GcalMonthViewPrivate *priv;
|
||||
|
||||
widget = GTK_WIDGET (month_view);
|
||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||
|
||||
g_clear_pointer (&priv->start_mark_cell, g_date_time_unref);
|
||||
g_clear_pointer (&priv->end_mark_cell, g_date_time_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
get_cell_position (GcalMonthView *view,
|
||||
gint cell,
|
||||
@@ -235,57 +250,51 @@ show_popover_for_position (GcalMonthView *view,
|
||||
GcalSubscriberViewPrivate *ppriv;
|
||||
GcalMonthViewPrivate *priv;
|
||||
GtkWidget *widget;
|
||||
|
||||
gint start_day, end_day;
|
||||
GDateTime *end_dt,*start_dt;
|
||||
|
||||
widget = GTK_WIDGET (view);
|
||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||
ppriv = GCAL_SUBSCRIBER_VIEW (widget)->priv;
|
||||
start_dt = priv->start_mark_cell;
|
||||
end_dt = priv->end_mark_cell;
|
||||
|
||||
if (priv->start_mark_cell < 0)
|
||||
if (priv->start_mark_cell == NULL)
|
||||
return FALSE;
|
||||
|
||||
start_day = priv->start_mark_cell - priv->days_delay + 1;
|
||||
end_day = priv->end_mark_cell - priv->days_delay + 1;
|
||||
|
||||
if (priv->pressed_overflow_indicator != -1 && priv->start_mark_cell == priv->end_mark_cell &&
|
||||
if (priv->pressed_overflow_indicator != -1 && !g_date_time_equal (priv->start_mark_cell, priv->end_mark_cell) &&
|
||||
g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (priv->pressed_overflow_indicator)))
|
||||
{
|
||||
priv->hovered_overflow_indicator = priv->pressed_overflow_indicator;
|
||||
|
||||
rebuild_popover_for_day (GCAL_MONTH_VIEW (widget), end_day);
|
||||
rebuild_popover_for_day (GCAL_MONTH_VIEW (widget), g_date_time_get_day_of_month (priv->end_mark_cell));
|
||||
gtk_widget_show_all (priv->overflow_popover);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
priv->pressed_overflow_indicator = -1;
|
||||
priv->start_mark_cell = -1;
|
||||
priv->end_mark_cell = -1;
|
||||
|
||||
cancel_selection (GCAL_MONTH_VIEW (widget));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GDateTime *start_dt, *end_dt;
|
||||
|
||||
start_dt = NULL;
|
||||
end_dt = NULL;
|
||||
|
||||
/* Swap dates if start > end */
|
||||
if (start_day > end_day)
|
||||
if (g_date_time_compare (start_dt, end_dt) > 0)
|
||||
{
|
||||
gint aux;
|
||||
aux = end_day;
|
||||
end_day = start_day;
|
||||
start_day = aux;
|
||||
GDateTime *aux;
|
||||
aux = start_dt;
|
||||
start_dt = end_dt;
|
||||
end_dt = aux;
|
||||
}
|
||||
|
||||
start_dt = g_date_time_new_local (priv->date->year, priv->date->month, start_day, 0, 0, 0);
|
||||
|
||||
/* Only setup an end date when days are different */
|
||||
if (start_day != end_day)
|
||||
if (g_date_time_compare (priv->start_mark_cell, priv->end_mark_cell))
|
||||
{
|
||||
GDateTime *tmp_dt;
|
||||
|
||||
tmp_dt = g_date_time_new_local (priv->date->year, priv->date->month, end_day, 0, 0, 0);
|
||||
tmp_dt = g_date_time_new_local (g_date_time_get_year (end_dt),
|
||||
g_date_time_get_month (end_dt),
|
||||
g_date_time_get_day_of_month (end_dt),
|
||||
0, 0, 0);
|
||||
end_dt = g_date_time_add_days (tmp_dt, 1);
|
||||
|
||||
g_clear_pointer (&tmp_dt, g_date_time_unref);
|
||||
@@ -666,7 +675,7 @@ gcal_month_view_key_press (GtkWidget *widget,
|
||||
GcalMonthViewPrivate *priv;
|
||||
gboolean selection, valid_key;
|
||||
gdouble x, y;
|
||||
gint min, max, diff, month_change;
|
||||
gint min, max, diff, month_change, current_day;
|
||||
|
||||
g_return_val_if_fail (GCAL_IS_MONTH_VIEW (widget), FALSE);
|
||||
|
||||
@@ -675,6 +684,7 @@ gcal_month_view_key_press (GtkWidget *widget,
|
||||
valid_key = FALSE;
|
||||
diff = 0;
|
||||
month_change = 0;
|
||||
current_day = priv->keyboard_cell - priv->days_delay + 1;
|
||||
min = priv->days_delay;
|
||||
max = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year) - 1;
|
||||
|
||||
@@ -683,10 +693,8 @@ gcal_month_view_key_press (GtkWidget *widget,
|
||||
* focused cell as the start, and then update the end mark after updating the
|
||||
* focused cell.
|
||||
*/
|
||||
if (selection && priv->start_mark_cell == -1)
|
||||
{
|
||||
priv->start_mark_cell = priv->keyboard_cell;
|
||||
}
|
||||
if (selection && priv->start_mark_cell == NULL)
|
||||
priv->start_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month, current_day, 0, 0, 0);
|
||||
|
||||
switch (event->keyval)
|
||||
{
|
||||
@@ -715,15 +723,15 @@ gcal_month_view_key_press (GtkWidget *widget,
|
||||
* If it's not on the selection mode (i.e. shift is not pressed), we should
|
||||
* simulate it by changing the start & end selected cells = keyboard cell.
|
||||
*/
|
||||
if (!selection && priv->start_mark_cell == -1 && priv->end_mark_cell == -1)
|
||||
priv->start_mark_cell = priv->end_mark_cell = priv->keyboard_cell;
|
||||
if (!selection && priv->start_mark_cell == NULL && priv->end_mark_cell == NULL)
|
||||
priv->start_mark_cell = priv->end_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month, current_day, 0, 0, 0);
|
||||
|
||||
get_cell_position (GCAL_MONTH_VIEW (widget), real_cell (priv->end_mark_cell, priv->k), &x, &y);
|
||||
get_cell_position (GCAL_MONTH_VIEW (widget), real_cell (current_day + priv->days_delay - 1, priv->k), &x, &y);
|
||||
show_popover_for_position (GCAL_MONTH_VIEW (widget), x, y, FALSE);
|
||||
break;
|
||||
|
||||
case GDK_KEY_Escape:
|
||||
priv->start_mark_cell = priv->end_mark_cell = -1;
|
||||
cancel_selection (GCAL_MONTH_VIEW (widget));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -757,14 +765,16 @@ gcal_month_view_key_press (GtkWidget *widget,
|
||||
g_object_notify (G_OBJECT (widget), "active-date");
|
||||
}
|
||||
|
||||
current_day = priv->keyboard_cell - priv->days_delay + 1;
|
||||
|
||||
if (selection)
|
||||
{
|
||||
priv->end_mark_cell = priv->keyboard_cell;
|
||||
priv->end_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month, current_day, 0, 0, 0);
|
||||
}
|
||||
else if (!selection && valid_key)
|
||||
{
|
||||
/* Cancel selection if SHIFT is not pressed */
|
||||
priv->start_mark_cell = priv->end_mark_cell = -1;
|
||||
cancel_selection (GCAL_MONTH_VIEW (widget));
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
@@ -837,8 +847,7 @@ gcal_month_view_init (GcalMonthView *self)
|
||||
|
||||
priv = gcal_month_view_get_instance_private (self);
|
||||
|
||||
priv->start_mark_cell = -1;
|
||||
priv->end_mark_cell = -1;
|
||||
cancel_selection (self);
|
||||
|
||||
priv->pressed_overflow_indicator = -1;
|
||||
priv->hovered_overflow_indicator = -1;
|
||||
@@ -901,8 +910,8 @@ gcal_month_view_set_property (GObject *object,
|
||||
priv->date = g_value_dup_boxed (value);
|
||||
priv->days_delay = (time_day_of_week (1, priv->date->month - 1, priv->date->year) - priv->first_weekday + 7) % 7;
|
||||
priv->keyboard_cell = priv->days_delay + (priv->date->day - 1);
|
||||
priv->start_mark_cell = -1;
|
||||
priv->end_mark_cell = -1;
|
||||
|
||||
cancel_selection (GCAL_MONTH_VIEW (object));
|
||||
|
||||
ppriv->children_changed = TRUE;
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
@@ -1416,10 +1425,28 @@ gcal_month_view_draw (GtkWidget *widget,
|
||||
sw = 1 - 2 * priv->k;
|
||||
|
||||
/* active cells */
|
||||
if (priv->start_mark_cell > -1 && priv->end_mark_cell > -1)
|
||||
if (priv->start_mark_cell && priv->end_mark_cell)
|
||||
{
|
||||
lower_mark = priv->start_mark_cell - priv->days_delay + 1;
|
||||
upper_mark = priv->end_mark_cell - priv->days_delay + 1;
|
||||
gint start_year, end_year, start_month, end_month;
|
||||
|
||||
upper_mark = g_date_time_get_day_of_month(priv->end_mark_cell);
|
||||
|
||||
start_year = g_date_time_get_year (priv->start_mark_cell);
|
||||
end_year = g_date_time_get_year (priv->end_mark_cell);
|
||||
start_month = g_date_time_get_month (priv->start_mark_cell);
|
||||
end_month = g_date_time_get_month (priv->end_mark_cell);
|
||||
|
||||
if (start_year == end_year && start_month == end_month)
|
||||
{
|
||||
lower_mark = g_date_time_get_day_of_month(priv->start_mark_cell);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (start_year != end_year)
|
||||
lower_mark = start_year < end_year ? 1 : icaltime_days_in_month (end_month, end_year);
|
||||
else
|
||||
lower_mark = start_month < end_month ? 1 : icaltime_days_in_month (end_month, end_year);
|
||||
}
|
||||
|
||||
if (lower_mark > upper_mark)
|
||||
{
|
||||
@@ -1653,13 +1680,36 @@ gcal_month_view_draw (GtkWidget *widget,
|
||||
gtk_style_context_restore (context);
|
||||
|
||||
/* selection borders */
|
||||
if (priv->start_mark_cell != -1 && priv->end_mark_cell != -1)
|
||||
if (priv->start_mark_cell && priv->end_mark_cell)
|
||||
{
|
||||
gint first_mark, last_mark;
|
||||
gint pos_x2, pos_y2;
|
||||
gint start_year, end_year, start_month, end_month;
|
||||
|
||||
start_year = g_date_time_get_year (priv->start_mark_cell);
|
||||
end_year = g_date_time_get_year (priv->end_mark_cell);
|
||||
start_month = g_date_time_get_month (priv->start_mark_cell);
|
||||
end_month = g_date_time_get_month (priv->end_mark_cell);
|
||||
|
||||
last_mark = real_cell (g_date_time_get_day_of_month (priv->end_mark_cell) + priv->days_delay - 1, priv->k);
|
||||
|
||||
if (start_year == end_year && start_month == end_month)
|
||||
{
|
||||
first_mark = real_cell (g_date_time_get_day_of_month (priv->start_mark_cell) + priv->days_delay - 1, priv->k);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint start_cell, end_cell;
|
||||
|
||||
start_cell = priv->days_delay;
|
||||
end_cell = icaltime_days_in_month (end_month, end_year) + priv->days_delay - 1;
|
||||
|
||||
if (start_year != end_year)
|
||||
first_mark = start_year < end_year ? real_cell (start_cell, priv->k) : real_cell(end_cell, priv->k);
|
||||
else
|
||||
first_mark = start_month < end_month ? real_cell (start_cell, priv->k) : real_cell (end_cell, priv->k);
|
||||
}
|
||||
|
||||
first_mark = real_cell (priv->start_mark_cell, priv->k);
|
||||
last_mark = real_cell (priv->end_mark_cell, priv->k);
|
||||
if (first_mark > last_mark)
|
||||
{
|
||||
gint tmp = first_mark;
|
||||
@@ -1816,8 +1866,10 @@ gcal_month_view_button_press (GtkWidget *widget,
|
||||
|
||||
if (clicked_cell >= priv->days_delay && clicked_cell < days)
|
||||
{
|
||||
priv->start_mark_cell = clicked_cell;
|
||||
priv->keyboard_cell = clicked_cell;
|
||||
priv->start_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month,
|
||||
priv->keyboard_cell - priv->days_delay + 1,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (pressed_indicator && g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (clicked_cell)))
|
||||
@@ -1853,7 +1905,7 @@ gcal_month_view_motion_notify_event (GtkWidget *widget,
|
||||
new_end_cell = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y, &hovered_indicator, NULL, NULL);
|
||||
new_end_cell = real_cell (new_end_cell, priv->k);
|
||||
|
||||
if (priv->start_mark_cell != -1)
|
||||
if (priv->start_mark_cell)
|
||||
{
|
||||
if (!(event->state & GDK_BUTTON_PRESS_MASK))
|
||||
return TRUE;
|
||||
@@ -1862,12 +1914,12 @@ gcal_month_view_motion_notify_event (GtkWidget *widget,
|
||||
{
|
||||
priv->keyboard_cell = new_end_cell;
|
||||
|
||||
if (priv->end_mark_cell != priv->start_mark_cell)
|
||||
if (g_date_time_compare (priv->start_mark_cell, priv->end_mark_cell))
|
||||
priv->hovered_overflow_indicator = -1;
|
||||
if (priv->end_mark_cell != new_end_cell)
|
||||
if (g_date_time_get_day_of_month (priv->end_mark_cell) + priv->days_delay - 1 != new_end_cell)
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
priv->end_mark_cell = new_end_cell;
|
||||
priv->end_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month, new_end_cell - priv->days_delay + 1, 0, 0, 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1898,24 +1950,26 @@ gcal_month_view_button_release (GtkWidget *widget,
|
||||
{
|
||||
GcalMonthViewPrivate *priv;
|
||||
gdouble x, y;
|
||||
gint days;
|
||||
gint days, current_day;
|
||||
gboolean released_indicator = FALSE;
|
||||
|
||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
||||
|
||||
priv->end_mark_cell = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y, &released_indicator, &x, &y);
|
||||
priv->end_mark_cell = real_cell (priv->end_mark_cell, priv->k);
|
||||
current_day = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y, &released_indicator, &x, &y);
|
||||
current_day = real_cell (current_day, priv->k);
|
||||
|
||||
if (priv->end_mark_cell >= priv->days_delay && priv->end_mark_cell < days)
|
||||
if (current_day >= priv->days_delay && current_day < days)
|
||||
{
|
||||
priv->keyboard_cell = priv->end_mark_cell;
|
||||
priv->keyboard_cell = current_day;
|
||||
priv->end_mark_cell = g_date_time_new_local (priv->date->year, priv->date->month, current_day - priv->days_delay + 1, 0, 0, 0);
|
||||
return show_popover_for_position (GCAL_MONTH_VIEW (widget), x, y, released_indicator);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the button is released over an invalid cell, entirely cancel the selection */
|
||||
priv->start_mark_cell = priv->end_mark_cell = -1;
|
||||
cancel_selection (GCAL_MONTH_VIEW (widget));
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return FALSE;
|
||||
@@ -1969,8 +2023,8 @@ gcal_month_view_clear_state (GcalSubscriberView *subscriber)
|
||||
|
||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (subscriber));
|
||||
|
||||
priv->start_mark_cell = -1;
|
||||
priv->end_mark_cell = -1;
|
||||
cancel_selection (GCAL_MONTH_VIEW (subscriber));
|
||||
|
||||
priv->pressed_overflow_indicator = -1;
|
||||
|
||||
gtk_widget_hide (priv->overflow_popover);
|
||||
@@ -2034,12 +2088,8 @@ gcal_month_view_get_final_date (GcalView *view)
|
||||
static void
|
||||
gcal_month_view_clear_marks (GcalView *view)
|
||||
{
|
||||
GcalMonthViewPrivate *priv;
|
||||
cancel_selection (GCAL_MONTH_VIEW (view));
|
||||
|
||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (view));
|
||||
|
||||
priv->start_mark_cell = -1;
|
||||
priv->end_mark_cell = -1;
|
||||
gtk_widget_queue_draw (GTK_WIDGET (view));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user