month-view: implement keyboard navigation
For this to be made, some significant changes on the inners of GcalMonthView had to be done. Later on, I'll do a complete rewrite of it, deprecating the use of 'sw' and 'k'.
This commit is contained in:
+238
-142
@@ -75,7 +75,7 @@ typedef struct
|
|||||||
gboolean use_24h_format;
|
gboolean use_24h_format;
|
||||||
|
|
||||||
/* text direction factors */
|
/* text direction factors */
|
||||||
gint k;
|
gboolean k;
|
||||||
|
|
||||||
icaltimetype *current_date;
|
icaltimetype *current_date;
|
||||||
|
|
||||||
@@ -89,6 +89,8 @@ enum
|
|||||||
PROP_DATE, /* active-date inherited property */
|
PROP_DATE, /* active-date inherited property */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MIRROR(val,start,end) (start + (val / end) * end + (end - cell % end))
|
||||||
|
|
||||||
static gint gather_button_event_data (GcalMonthView *view,
|
static gint gather_button_event_data (GcalMonthView *view,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
gdouble y,
|
gdouble y,
|
||||||
@@ -180,6 +182,118 @@ G_DEFINE_TYPE_WITH_CODE (GcalMonthView, gcal_month_view,GCAL_TYPE_SUBSCRIBER_VIE
|
|||||||
G_ADD_PRIVATE (GcalMonthView)
|
G_ADD_PRIVATE (GcalMonthView)
|
||||||
G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init));
|
G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init));
|
||||||
|
|
||||||
|
static gint
|
||||||
|
real_cell (gint cell,
|
||||||
|
gboolean rtl)
|
||||||
|
{
|
||||||
|
return rtl ? MIRROR (cell, 0, 7) - 1 : cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_cell_position (GcalMonthView *view,
|
||||||
|
gint cell,
|
||||||
|
gdouble *out_x,
|
||||||
|
gdouble *out_y)
|
||||||
|
{
|
||||||
|
GcalMonthViewPrivate *priv;
|
||||||
|
GtkWidget *widget;
|
||||||
|
|
||||||
|
gdouble start_grid_y;
|
||||||
|
|
||||||
|
gint shown_rows;
|
||||||
|
gdouble first_row_gap;
|
||||||
|
|
||||||
|
gdouble cell_width;
|
||||||
|
gdouble cell_height;
|
||||||
|
|
||||||
|
priv = gcal_month_view_get_instance_private (view);
|
||||||
|
widget = GTK_WIDGET (view);
|
||||||
|
|
||||||
|
start_grid_y = get_start_grid_y (widget);
|
||||||
|
|
||||||
|
shown_rows = ceil ((priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year)) / 7.0);
|
||||||
|
first_row_gap = (6 - shown_rows) * 0.5; /* invalid area before the actual rows */
|
||||||
|
|
||||||
|
cell_width = gtk_widget_get_allocated_width (widget) / 7.0;
|
||||||
|
cell_height = (gtk_widget_get_allocated_height (widget) - start_grid_y) / 6.0;
|
||||||
|
|
||||||
|
if (out_x != NULL)
|
||||||
|
*out_x = cell_width * ((cell % 7) + 0.5);
|
||||||
|
|
||||||
|
if (out_y != NULL)
|
||||||
|
*out_y = cell_height * ((cell / 7) + first_row_gap + 0.5) + start_grid_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
show_popover_for_position (GcalMonthView *view,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
gboolean on_indicator)
|
||||||
|
{
|
||||||
|
GcalSubscriberViewPrivate *ppriv;
|
||||||
|
GcalMonthViewPrivate *priv;
|
||||||
|
GtkWidget *widget;
|
||||||
|
|
||||||
|
gint start_day, end_day;
|
||||||
|
|
||||||
|
icaltimetype *start_date;
|
||||||
|
icaltimetype *end_date = NULL;
|
||||||
|
|
||||||
|
widget = GTK_WIDGET (view);
|
||||||
|
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||||
|
ppriv = GCAL_SUBSCRIBER_VIEW (widget)->priv;
|
||||||
|
|
||||||
|
if (priv->start_mark_cell < 0)
|
||||||
|
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 &&
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_date = gcal_dup_icaltime (priv->date);
|
||||||
|
start_date->day = start_day;
|
||||||
|
start_date->is_date = 1;
|
||||||
|
|
||||||
|
end_date = gcal_dup_icaltime (priv->date);
|
||||||
|
end_date->day = end_day;
|
||||||
|
end_date->is_date = 1;
|
||||||
|
|
||||||
|
if (start_date->day > end_date->day)
|
||||||
|
{
|
||||||
|
gint day = start_date->day;
|
||||||
|
start_date->day = end_date->day;
|
||||||
|
end_date->day = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_date->day += 1;
|
||||||
|
|
||||||
|
g_signal_emit_by_name (GCAL_VIEW (widget), "create-event", start_date, end_date, x, y);
|
||||||
|
|
||||||
|
g_free (start_date);
|
||||||
|
g_free (end_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (widget);
|
||||||
|
priv->pressed_overflow_indicator = -1;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
gather_button_event_data (GcalMonthView *view,
|
gather_button_event_data (GcalMonthView *view,
|
||||||
gdouble x,
|
gdouble x,
|
||||||
@@ -362,6 +476,7 @@ rebuild_popover_for_day (GcalMonthView *view,
|
|||||||
gdouble start_grid_y, cell_width, cell_height;
|
gdouble start_grid_y, cell_width, cell_height;
|
||||||
|
|
||||||
gint shown_rows;
|
gint shown_rows;
|
||||||
|
gint real_clicked_popover_cell;
|
||||||
|
|
||||||
GtkStyleContext *context;
|
GtkStyleContext *context;
|
||||||
GtkStateFlags state;
|
GtkStateFlags state;
|
||||||
@@ -434,23 +549,24 @@ rebuild_popover_for_day (GcalMonthView *view,
|
|||||||
pango_font_description_free (ofont_desc);
|
pango_font_description_free (ofont_desc);
|
||||||
g_object_unref (overflow_layout);
|
g_object_unref (overflow_layout);
|
||||||
|
|
||||||
rect.y = cell_height * ((priv->pressed_overflow_indicator / 7) + 1.0 + (6 - shown_rows) * 0.5) + start_grid_y - padding_bottom - font_height / 2;
|
real_clicked_popover_cell = real_cell (priv->pressed_overflow_indicator, priv->k);
|
||||||
|
rect.y = cell_height * ((real_clicked_popover_cell / 7) + 1.0 + (6 - shown_rows) * 0.5) + start_grid_y - padding_bottom - font_height / 2;
|
||||||
rect.width = 1;
|
rect.width = 1;
|
||||||
rect.height = 1;
|
rect.height = 1;
|
||||||
|
|
||||||
if (priv->pressed_overflow_indicator % 7 < 3)
|
if (real_clicked_popover_cell % 7 < 3)
|
||||||
{
|
{
|
||||||
rect.x = cell_width * ((priv->pressed_overflow_indicator % 7) + 1.0);
|
rect.x = cell_width * ((real_clicked_popover_cell % 7) + 1.0);
|
||||||
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), priv->k == 0 ? GTK_POS_RIGHT : GTK_POS_LEFT);
|
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), priv->k ? GTK_POS_LEFT : GTK_POS_RIGHT);
|
||||||
}
|
}
|
||||||
else if (priv->pressed_overflow_indicator % 7 > 3)
|
else if (real_clicked_popover_cell % 7 > 3)
|
||||||
{
|
{
|
||||||
rect.x = cell_width * ((priv->pressed_overflow_indicator % 7));
|
rect.x = cell_width * ((real_clicked_popover_cell % 7));
|
||||||
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), priv->k == 0 ? GTK_POS_LEFT : GTK_POS_RIGHT);
|
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), priv->k ? GTK_POS_RIGHT : GTK_POS_LEFT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rect.x = cell_width * ((priv->pressed_overflow_indicator % 7) + 1.0 - priv->k);
|
rect.x = cell_width * ((real_clicked_popover_cell % 7) + 1.0 - priv->k);
|
||||||
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), GTK_POS_RIGHT);
|
gtk_popover_set_position (GTK_POPOVER (priv->overflow_popover), GTK_POS_RIGHT);
|
||||||
}
|
}
|
||||||
gtk_popover_set_pointing_to (GTK_POPOVER (priv->overflow_popover), &rect);
|
gtk_popover_set_pointing_to (GTK_POPOVER (priv->overflow_popover), &rect);
|
||||||
@@ -523,48 +639,86 @@ gcal_month_view_key_press (GtkWidget *widget,
|
|||||||
GdkEventKey *event)
|
GdkEventKey *event)
|
||||||
{
|
{
|
||||||
GcalMonthViewPrivate *priv;
|
GcalMonthViewPrivate *priv;
|
||||||
|
gboolean selection, valid_key;
|
||||||
|
gdouble x, y;
|
||||||
|
gint min, max, diff;
|
||||||
|
|
||||||
g_return_val_if_fail (GCAL_IS_MONTH_VIEW (widget), FALSE);
|
g_return_val_if_fail (GCAL_IS_MONTH_VIEW (widget), FALSE);
|
||||||
|
|
||||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||||
|
selection = event->state & GDK_SHIFT_MASK;
|
||||||
|
valid_key = FALSE;
|
||||||
|
diff = 0;
|
||||||
|
min = priv->days_delay;
|
||||||
|
max = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year) - 1;
|
||||||
|
|
||||||
if (!(event->state & GDK_MODIFIER_MASK))
|
/*
|
||||||
|
* If it's starting the selection right now, it should mark the current keyboard
|
||||||
|
* focused cell as the start, and then update the end mark after updating the
|
||||||
|
* focused cell.
|
||||||
|
*/
|
||||||
|
if (selection && priv->start_mark_cell == -1)
|
||||||
{
|
{
|
||||||
switch (event->keyval)
|
priv->start_mark_cell = priv->keyboard_cell;
|
||||||
{
|
|
||||||
case GDK_KEY_Up:
|
|
||||||
priv->keyboard_cell -= 7;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Down:
|
|
||||||
priv->keyboard_cell += 7;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Left:
|
|
||||||
priv->keyboard_cell--;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Right:
|
|
||||||
priv->keyboard_cell++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Return:
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->keyboard_cell = CLAMP (priv->keyboard_cell, priv->days_delay,
|
|
||||||
(priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year) - 1));
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
switch (event->keyval)
|
||||||
|
{
|
||||||
|
case GDK_KEY_Up:
|
||||||
|
valid_key = TRUE;
|
||||||
|
diff = -7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Down:
|
||||||
|
valid_key = TRUE;
|
||||||
|
diff = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Left:
|
||||||
|
valid_key = TRUE;
|
||||||
|
diff = priv->k ? 1 : -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Right:
|
||||||
|
valid_key = TRUE;
|
||||||
|
diff = priv->k ? -1 : 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Return:
|
||||||
|
/*
|
||||||
|
* 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 = real_cell (priv->keyboard_cell, priv->k);
|
||||||
|
|
||||||
|
get_cell_position (GCAL_MONTH_VIEW (widget), priv->start_mark_cell, &x, &y);
|
||||||
|
show_popover_for_position (GCAL_MONTH_VIEW (widget), x, y, FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->keyboard_cell + diff <= max && priv->keyboard_cell + diff >= min)
|
||||||
|
{
|
||||||
|
priv->keyboard_cell += diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selection)
|
||||||
|
{
|
||||||
|
priv->end_mark_cell = priv->keyboard_cell;
|
||||||
|
}
|
||||||
|
else if (!selection && valid_key)
|
||||||
|
{
|
||||||
|
/* Cancel selection if SHIFT is not pressed */
|
||||||
|
priv->start_mark_cell = priv->end_mark_cell = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff != 0)
|
||||||
|
gtk_widget_queue_draw (widget);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -640,10 +794,7 @@ gcal_month_view_init (GcalMonthView *self)
|
|||||||
|
|
||||||
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "calendar-view");
|
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "calendar-view");
|
||||||
|
|
||||||
if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_LTR)
|
priv->k = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
|
||||||
priv->k = 0;
|
|
||||||
else if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
|
|
||||||
priv->k = 1;
|
|
||||||
|
|
||||||
priv->overflow_popover = gtk_popover_new (GTK_WIDGET (self));
|
priv->overflow_popover = gtk_popover_new (GTK_WIDGET (self));
|
||||||
gtk_style_context_add_class (gtk_widget_get_style_context (priv->overflow_popover), "events");
|
gtk_style_context_add_class (gtk_widget_get_style_context (priv->overflow_popover), "events");
|
||||||
@@ -698,7 +849,9 @@ gcal_month_view_set_property (GObject *object,
|
|||||||
|
|
||||||
priv->date = g_value_dup_boxed (value);
|
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->days_delay = (time_day_of_week (1, priv->date->month - 1, priv->date->year) - priv->first_weekday + 7) % 7;
|
||||||
priv->keyboard_cell = -1;
|
priv->keyboard_cell = priv->days_delay;
|
||||||
|
priv->start_mark_cell = -1;
|
||||||
|
priv->end_mark_cell = -1;
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (object));
|
gtk_widget_queue_draw (GTK_WIDGET (object));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1151,10 +1304,11 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
sw = 1 - 2 * priv->k;
|
sw = 1 - 2 * priv->k;
|
||||||
|
|
||||||
/* active cells */
|
/* active cells */
|
||||||
if (priv->start_mark_cell != -1 && priv->end_mark_cell != -1)
|
if (priv->start_mark_cell > -1 && priv->end_mark_cell > -1)
|
||||||
{
|
{
|
||||||
lower_mark = 7 * ((priv->start_mark_cell + 7 * priv->k) / 7) + sw * (priv->start_mark_cell % 7) + (1 - priv->k);
|
lower_mark = priv->start_mark_cell - priv->days_delay + 1;
|
||||||
upper_mark = 7 * ((priv->end_mark_cell + 7 * priv->k) / 7) + sw * (priv->end_mark_cell % 7) + (1 - priv->k);
|
upper_mark = priv->end_mark_cell - priv->days_delay + 1;
|
||||||
|
|
||||||
if (lower_mark > upper_mark)
|
if (lower_mark > upper_mark)
|
||||||
{
|
{
|
||||||
gint cell;
|
gint cell;
|
||||||
@@ -1162,9 +1316,6 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
lower_mark = upper_mark;
|
lower_mark = upper_mark;
|
||||||
upper_mark = cell;
|
upper_mark = cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
lower_mark -= priv->days_delay;
|
|
||||||
upper_mark -= priv->days_delay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* view headers */
|
/* view headers */
|
||||||
@@ -1238,6 +1389,7 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
gchar *nr_day;
|
gchar *nr_day;
|
||||||
gint column = i % 7;
|
gint column = i % 7;
|
||||||
gint row = i / 7;
|
gint row = i / 7;
|
||||||
|
gint real_i = real_cell (i, priv->k);
|
||||||
|
|
||||||
j = 7 * ((i + 7 * priv->k) / 7) + sw * (i % 7) + (1 - priv->k);
|
j = 7 * ((i + 7 * priv->k) / 7) + sw * (i % 7) + (1 - priv->k);
|
||||||
if (j <= priv->days_delay)
|
if (j <= priv->days_delay)
|
||||||
@@ -1248,7 +1400,7 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
|
|
||||||
nr_day = g_strdup_printf ("%d", j);
|
nr_day = g_strdup_printf ("%d", j);
|
||||||
|
|
||||||
if (g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (i)))
|
if (g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (real_i)))
|
||||||
{
|
{
|
||||||
GList *l;
|
GList *l;
|
||||||
PangoLayout *overflow_layout;
|
PangoLayout *overflow_layout;
|
||||||
@@ -1256,7 +1408,7 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
gchar *overflow_str;
|
gchar *overflow_str;
|
||||||
gdouble y_value;
|
gdouble y_value;
|
||||||
|
|
||||||
l = g_hash_table_lookup (ppriv->overflow_cells, GINT_TO_POINTER (i));
|
l = g_hash_table_lookup (ppriv->overflow_cells, GINT_TO_POINTER (real_i));
|
||||||
|
|
||||||
/* TODO: Warning in some languages this string can be too long and may overlap wit the number */
|
/* TODO: Warning in some languages this string can be too long and may overlap wit the number */
|
||||||
overflow_str = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "Other event", "Other %d events", g_list_length (l)),
|
overflow_str = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "Other event", "Other %d events", g_list_length (l)),
|
||||||
@@ -1264,7 +1416,7 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
|
|
||||||
gtk_style_context_save (context);
|
gtk_style_context_save (context);
|
||||||
gtk_style_context_add_class (context, "overflow");
|
gtk_style_context_add_class (context, "overflow");
|
||||||
if (priv->hovered_overflow_indicator == i)
|
if (priv->hovered_overflow_indicator == real_i)
|
||||||
{
|
{
|
||||||
gtk_style_context_set_state (context, state | GTK_STATE_FLAG_PRELIGHT);
|
gtk_style_context_set_state (context, state | GTK_STATE_FLAG_PRELIGHT);
|
||||||
gtk_style_context_get (context, state | GTK_STATE_FLAG_PRELIGHT, "font", &ofont_desc, NULL);
|
gtk_style_context_get (context, state | GTK_STATE_FLAG_PRELIGHT, "font", &ofont_desc, NULL);
|
||||||
@@ -1282,7 +1434,7 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
pango_layout_get_pixel_size (overflow_layout, &font_width, &font_height);
|
pango_layout_get_pixel_size (overflow_layout, &font_width, &font_height);
|
||||||
y_value = cell_height * (row + 1 + first_row_gap) - font_height - padding.bottom + start_grid_y;
|
y_value = cell_height * (row + 1 + first_row_gap) - font_height - padding.bottom + start_grid_y;
|
||||||
|
|
||||||
if ((!gtk_widget_is_visible (priv->overflow_popover) && priv->hovered_overflow_indicator == i) ||
|
if ((!gtk_widget_is_visible (priv->overflow_popover) && priv->hovered_overflow_indicator == real_i) ||
|
||||||
gtk_widget_is_visible (priv->overflow_popover))
|
gtk_widget_is_visible (priv->overflow_popover))
|
||||||
{
|
{
|
||||||
gtk_render_background (context, cr, cell_width * column, y_value - padding.bottom,
|
gtk_render_background (context, cr, cell_width * column, y_value - padding.bottom,
|
||||||
@@ -1395,12 +1547,13 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
gint first_mark, last_mark;
|
gint first_mark, last_mark;
|
||||||
gint pos_x2, pos_y2;
|
gint pos_x2, pos_y2;
|
||||||
|
|
||||||
first_mark = priv->start_mark_cell;
|
first_mark = real_cell (priv->start_mark_cell, priv->k);
|
||||||
last_mark = priv->end_mark_cell;
|
last_mark = real_cell (priv->end_mark_cell, priv->k);
|
||||||
if (priv->start_mark_cell > priv->end_mark_cell)
|
if (first_mark > last_mark)
|
||||||
{
|
{
|
||||||
last_mark = priv->start_mark_cell;
|
gint tmp = first_mark;
|
||||||
first_mark = priv->end_mark_cell;
|
first_mark = last_mark;
|
||||||
|
last_mark = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_style_context_get_color (context, state | GTK_STATE_FLAG_SELECTED, &color);
|
gtk_style_context_get_color (context, state | GTK_STATE_FLAG_SELECTED, &color);
|
||||||
@@ -1455,12 +1608,16 @@ gcal_month_view_draw (GtkWidget *widget,
|
|||||||
cairo_stroke (cr);
|
cairo_stroke (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw focus rectangle */
|
||||||
if (priv->keyboard_cell > priv->days_delay - 1)
|
if (priv->keyboard_cell > priv->days_delay - 1)
|
||||||
{
|
{
|
||||||
|
gint localized_cell;
|
||||||
gint x;
|
gint x;
|
||||||
gint y;
|
gint y;
|
||||||
|
|
||||||
x = cell_width * (priv->keyboard_cell % 7);
|
localized_cell = real_cell (priv->keyboard_cell % 7, priv->k);
|
||||||
|
|
||||||
|
x = cell_width * (localized_cell);
|
||||||
y = cell_height * (priv->keyboard_cell / 7 + first_row_gap) + start_grid_y;
|
y = cell_height * (priv->keyboard_cell / 7 + first_row_gap) + start_grid_y;
|
||||||
|
|
||||||
gtk_render_focus (context, cr, x, y, cell_width, cell_height);
|
gtk_render_focus (context, cr, x, y, cell_width, cell_height);
|
||||||
@@ -1481,21 +1638,20 @@ gcal_month_view_button_press (GtkWidget *widget,
|
|||||||
GcalSubscriberViewPrivate *ppriv;
|
GcalSubscriberViewPrivate *ppriv;
|
||||||
GcalMonthViewPrivate *priv;
|
GcalMonthViewPrivate *priv;
|
||||||
|
|
||||||
gint days, j, sw, clicked_cell;
|
gint days, clicked_cell;
|
||||||
gboolean pressed_indicator = FALSE;
|
gboolean pressed_indicator = FALSE;
|
||||||
|
|
||||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||||
ppriv = GCAL_SUBSCRIBER_VIEW (widget)->priv;
|
ppriv = GCAL_SUBSCRIBER_VIEW (widget)->priv;
|
||||||
|
|
||||||
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
||||||
sw = 1 - 2 * priv->k;
|
|
||||||
|
|
||||||
clicked_cell = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y,
|
clicked_cell = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y,
|
||||||
&pressed_indicator, NULL, NULL);
|
&pressed_indicator, NULL, NULL);
|
||||||
|
|
||||||
j = 7 * ((clicked_cell + 7 * priv->k) / 7) + sw * (clicked_cell % 7) + (1 - priv->k);
|
clicked_cell = real_cell (clicked_cell, priv->k);
|
||||||
|
|
||||||
if (j > priv->days_delay && j <= days)
|
if (clicked_cell >= priv->days_delay && clicked_cell <= days)
|
||||||
priv->start_mark_cell = clicked_cell;
|
priv->start_mark_cell = clicked_cell;
|
||||||
|
|
||||||
if (pressed_indicator && g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (clicked_cell)))
|
if (pressed_indicator && g_hash_table_contains (ppriv->overflow_cells, GINT_TO_POINTER (clicked_cell)))
|
||||||
@@ -1521,22 +1677,22 @@ gcal_month_view_motion_notify_event (GtkWidget *widget,
|
|||||||
GcalMonthViewPrivate *priv;
|
GcalMonthViewPrivate *priv;
|
||||||
|
|
||||||
gint days;
|
gint days;
|
||||||
gint j, sw;
|
|
||||||
gint new_end_cell, new_hovered_cell;
|
gint new_end_cell, new_hovered_cell;
|
||||||
gboolean hovered_indicator = FALSE;
|
gboolean hovered_indicator = FALSE;
|
||||||
|
|
||||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
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);
|
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
||||||
sw = 1 - 2 * priv->k;
|
|
||||||
|
|
||||||
new_end_cell = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y, &hovered_indicator, NULL, NULL);
|
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);
|
||||||
j = 7 * ((new_end_cell + 7 * priv->k) / 7) + sw * (new_end_cell % 7) + (1 - priv->k);
|
|
||||||
|
|
||||||
if (priv->start_mark_cell != -1)
|
if (priv->start_mark_cell != -1)
|
||||||
{
|
{
|
||||||
if (j > priv->days_delay && j <= days)
|
if (!(event->state & GDK_BUTTON_PRESS_MASK))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (new_end_cell >= priv->days_delay && new_end_cell < days)
|
||||||
{
|
{
|
||||||
if (priv->end_mark_cell != priv->start_mark_cell)
|
if (priv->end_mark_cell != priv->start_mark_cell)
|
||||||
priv->hovered_overflow_indicator = -1;
|
priv->hovered_overflow_indicator = -1;
|
||||||
@@ -1572,89 +1728,29 @@ static gboolean
|
|||||||
gcal_month_view_button_release (GtkWidget *widget,
|
gcal_month_view_button_release (GtkWidget *widget,
|
||||||
GdkEventButton *event)
|
GdkEventButton *event)
|
||||||
{
|
{
|
||||||
GcalSubscriberViewPrivate *ppriv;
|
|
||||||
GcalMonthViewPrivate *priv;
|
GcalMonthViewPrivate *priv;
|
||||||
|
gdouble x, y;
|
||||||
gint days;
|
gint days;
|
||||||
|
|
||||||
gint j, sw;
|
|
||||||
gint released;
|
|
||||||
gboolean released_indicator = FALSE;
|
gboolean released_indicator = FALSE;
|
||||||
|
|
||||||
gdouble x, y;
|
|
||||||
|
|
||||||
icaltimetype *start_date;
|
|
||||||
icaltimetype *end_date = NULL;
|
|
||||||
|
|
||||||
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||||
ppriv = GCAL_SUBSCRIBER_VIEW (widget)->priv;
|
|
||||||
|
|
||||||
if (priv->start_mark_cell == -1)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
days = priv->days_delay + icaltime_days_in_month (priv->date->month, priv->date->year);
|
||||||
sw = 1 - 2 * priv->k;
|
|
||||||
|
|
||||||
priv->keyboard_cell = -1;
|
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);
|
||||||
|
|
||||||
released = gather_button_event_data (GCAL_MONTH_VIEW (widget), event->x, event->y, &released_indicator, &x, &y);
|
if (priv->end_mark_cell >= priv->days_delay && priv->end_mark_cell < days)
|
||||||
|
|
||||||
j = 7 * ((released + 7 * priv->k) / 7) + sw * (released % 7) + (1 - priv->k);
|
|
||||||
|
|
||||||
if (j <= priv->days_delay || j > days)
|
|
||||||
{
|
{
|
||||||
priv->pressed_overflow_indicator = -1;
|
return show_popover_for_position (GCAL_MONTH_VIEW (widget), x, y, released_indicator);
|
||||||
priv->start_mark_cell = -1;
|
|
||||||
priv->end_mark_cell = -1;
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->end_mark_cell = released;
|
|
||||||
|
|
||||||
if (priv->pressed_overflow_indicator != -1 && 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), j - priv->days_delay);
|
|
||||||
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;
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
start_date = gcal_dup_icaltime (priv->date);
|
/* If the button is released over an invalid cell, entirely cancel the selection */
|
||||||
start_date->day = 7 * ((priv->start_mark_cell + 7 * priv->k) / 7) + sw * (priv->start_mark_cell % 7) + (1 - priv->k);
|
priv->start_mark_cell = priv->end_mark_cell = -1;
|
||||||
start_date->day -= priv->days_delay;
|
gtk_widget_queue_draw (widget);
|
||||||
start_date->is_date = 1;
|
|
||||||
|
|
||||||
end_date = gcal_dup_icaltime (priv->date);
|
return FALSE;
|
||||||
end_date->day = j - priv->days_delay;
|
|
||||||
end_date->is_date = 1;
|
|
||||||
|
|
||||||
if (start_date->day > end_date->day)
|
|
||||||
{
|
|
||||||
gint day = start_date->day;
|
|
||||||
start_date->day = end_date->day;
|
|
||||||
end_date->day = day;
|
|
||||||
}
|
|
||||||
end_date->day += 1 ;
|
|
||||||
|
|
||||||
g_signal_emit_by_name (GCAL_VIEW (widget), "create-event", start_date, end_date, x, y);
|
|
||||||
|
|
||||||
g_free (start_date);
|
|
||||||
g_free (end_date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
priv->pressed_overflow_indicator = -1;
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user