From 343283e37ad75e561b3704a5a5da5bae49d17878 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 9 Dec 2016 14:46:40 -0200 Subject: [PATCH] week-grid: implement event creation --- data/theme/gtk-styles.css | 4 + data/ui/window.ui | 1 + src/views/gcal-week-grid.c | 192 +++++++++++++++++++++++++++++++++++++ src/views/gcal-week-grid.h | 2 + src/views/gcal-week-view.c | 11 ++- 5 files changed, 208 insertions(+), 2 deletions(-) diff --git a/data/theme/gtk-styles.css b/data/theme/gtk-styles.css index 1cee1723..c33ed852 100644 --- a/data/theme/gtk-styles.css +++ b/data/theme/gtk-styles.css @@ -421,3 +421,7 @@ weekgrid.now-strip { margin: 0 0 0 1px; min-height: 2px; } + +weekgrid:selected { + background-color: alpha(@theme_selected_bg_color, 0.4); +} diff --git a/data/ui/window.ui b/data/ui/window.ui index b6a89dd7..085c84d3 100644 --- a/data/ui/window.ui +++ b/data/ui/window.ui @@ -56,6 +56,7 @@ True + diff --git a/src/views/gcal-week-grid.c b/src/views/gcal-week-grid.c index c2ff9452..7c7358fc 100644 --- a/src/views/gcal-week-grid.c +++ b/src/views/gcal-week-grid.c @@ -60,6 +60,13 @@ struct _GcalWeekGrid gboolean children_changed; gint redraw_timeout_id; + /* + * These fields are "cells" rather than minutes. Each cell + * correspond to 30 minutes. + */ + gint selection_start; + gint selection_end; + GcalManager *manager; }; @@ -461,6 +468,45 @@ gcal_week_grid_draw (GtkWidget *widget, cairo_set_line_width (cr, 0.65); + /* First, draw the selection */ + if (self->selection_start != -1 && self->selection_end != -1) + { + gdouble minutes_height; + gint selection_height; + gint column; + gint start; + gint end; + + start = self->selection_start; + end = self->selection_end; + + /* Swap cells if needed */ + if (start > end) + { + start = start + end; + end = start - end; + start = start - end; + } + + minutes_height = (gdouble) height / MINUTES_PER_DAY; + column = start * 30 / MINUTES_PER_DAY; + selection_height = (end - start + 1) * 30 * minutes_height; + + x = column * column_width; + + gtk_style_context_save (context); + gtk_style_context_set_state (context, state | GTK_STATE_FLAG_SELECTED); + + gtk_render_background (context, + cr, + ALIGNED (x), + round ((start * 30 % MINUTES_PER_DAY) * minutes_height), + column_width, + selection_height); + + gtk_style_context_restore (context); + } + /* Today column */ today_column = get_today_column (GCAL_WEEK_GRID (widget)); @@ -720,6 +766,135 @@ gcal_week_grid_get_preferred_height (GtkWidget *widget, *natural_height = height; } +static gboolean +gcal_week_grid_button_press (GtkWidget *widget, + GdkEventButton *event_button) +{ + GcalWeekGrid *self; + GtkAllocation alloc; + gboolean ltr; + gdouble minute_height; + gint column_width; + gint column; + gint minute; + + self = GCAL_WEEK_GRID (widget); + ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL; + + gtk_widget_get_allocation (widget, &alloc); + minute_height = (gdouble) alloc.height / MINUTES_PER_DAY; + column_width = floor (alloc.width / 7); + column = (gint) event_button->x / column_width; + minute = event_button->y / minute_height; + minute = minute - (minute % 30); + + self->selection_start = (column * MINUTES_PER_DAY + minute) / 30; + self->selection_end = self->selection_start; + + gtk_widget_queue_draw (widget); + + return GDK_EVENT_STOP; +} + +static gboolean +gcal_week_grid_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event) +{ + GcalWeekGrid *self; + GtkAllocation alloc; + gboolean ltr; + gdouble minute_height; + gint column; + gint minute; + + if (!(event->state & GDK_BUTTON_PRESS_MASK)) + return GDK_EVENT_PROPAGATE; + + self = GCAL_WEEK_GRID (widget); + ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL; + + gtk_widget_get_allocation (widget, &alloc); + minute_height = (gdouble) alloc.height / MINUTES_PER_DAY; + column = self->selection_start * 30 / MINUTES_PER_DAY; + minute = event->y / minute_height; + minute = minute - (minute % 30); + + self->selection_end = (column * MINUTES_PER_DAY + minute) / 30; + + gtk_widget_queue_draw (widget); + + return GDK_EVENT_STOP; +} + +static gboolean +gcal_week_grid_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GcalWeekGrid *self; + GtkAllocation alloc; + GDateTime *week_start; + GDateTime *start, *end; + GtkWidget *weekview; + gboolean ltr; + gdouble minute_height; + gdouble x, y; + gint column; + gint minute; + gint out_x; + gint out_y; + + self = GCAL_WEEK_GRID (widget); + ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL; + + gtk_widget_get_allocation (widget, &alloc); + minute_height = (gdouble) alloc.height / MINUTES_PER_DAY; + column = self->selection_start * 30 / MINUTES_PER_DAY; + minute = event->y / minute_height; + minute = minute - (minute % 30); + + self->selection_end = (column * MINUTES_PER_DAY + minute) / 30; + + gtk_widget_queue_draw (widget); + + /* Fake the week view's event so we can control the X and Y values */ + weekview = gtk_widget_get_ancestor (widget, GCAL_TYPE_WEEK_VIEW); + week_start = get_start_of_week (self->active_date); + + if (ltr) + { + start = g_date_time_add_minutes (week_start, self->selection_start * 30); + end = g_date_time_add_minutes (week_start, (self->selection_end + 1) * 30); + } + else + { + start = g_date_time_add_minutes (week_start, MAX_MINUTES - column * MINUTES_PER_DAY + minute); + end = g_date_time_add_minutes (week_start, MAX_MINUTES - column * MINUTES_PER_DAY + (self->selection_end + 1) * 30); + } + + x = round ((column + 0.5) * (alloc.width / 7.0)); + y = (minute + 15) * minute_height; + + gtk_widget_translate_coordinates (widget, + weekview, + x, + y, + &out_x, + &out_y); + + g_signal_emit_by_name (weekview, + "create-event", + start, + end, + (gdouble) out_x, + (gdouble) out_y); + + gcal_clear_datetime (&week_start); + gcal_clear_datetime (&start); + gcal_clear_datetime (&end); + + return GDK_EVENT_STOP; +} + static void gcal_week_grid_class_init (GcalWeekGridClass *klass) { @@ -742,6 +917,9 @@ gcal_week_grid_class_init (GcalWeekGridClass *klass) widget_class->map = gcal_week_grid_map; widget_class->unmap = gcal_week_grid_unmap; widget_class->get_preferred_height = gcal_week_grid_get_preferred_height; + widget_class->button_press_event = gcal_week_grid_button_press; + widget_class->motion_notify_event = gcal_week_grid_motion_notify_event; + widget_class->button_release_event = gcal_week_grid_button_release; properties[PROP_ACTIVE_DATE] = g_param_spec_boxed ("active-date", "Date", @@ -768,6 +946,9 @@ gcal_week_grid_init (GcalWeekGrid *self) { gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); + self->selection_start = -1; + self->selection_end = -1; + self->events = gcal_range_tree_new (); } @@ -903,3 +1084,14 @@ gcal_week_grid_get_children_by_uuid (GcalWeekGrid *self, return result; } + +void +gcal_week_grid_clear_marks (GcalWeekGrid *self) +{ + g_return_if_fail (GCAL_IS_WEEK_GRID (self)); + + self->selection_start = -1; + self->selection_end = -1; + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} diff --git a/src/views/gcal-week-grid.h b/src/views/gcal-week-grid.h index 34eaa327..34d48812 100644 --- a/src/views/gcal-week-grid.h +++ b/src/views/gcal-week-grid.h @@ -52,6 +52,8 @@ void gcal_week_grid_remove_event (GcalWeekGrid GList* gcal_week_grid_get_children_by_uuid (GcalWeekGrid *self, const gchar *uid); +void gcal_week_grid_clear_marks (GcalWeekGrid *self); + G_END_DECLS #endif /* GCAL_WEEK_GRID_H */ diff --git a/src/views/gcal-week-view.c b/src/views/gcal-week-view.c index 85aff04f..91108be4 100644 --- a/src/views/gcal-week-view.c +++ b/src/views/gcal-week-view.c @@ -235,6 +235,14 @@ gcal_week_view_get_children_by_uuid (GcalView *view, return g_list_concat (grid, header); } +static void +gcal_week_view_clear_marks (GcalView *view) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (view); + + gcal_week_grid_clear_marks (GCAL_WEEK_GRID (self->week_grid)); +} + static void update_hours_sidebar_size (GcalWeekView *self) { @@ -503,8 +511,7 @@ gcal_view_interface_init (GcalViewInterface *iface) iface->get_initial_date = gcal_week_view_get_initial_date; iface->get_final_date = gcal_week_view_get_final_date; iface->get_children_by_uuid = gcal_week_view_get_children_by_uuid; - - /* iface->clear_marks = gcal_week_view_clear_marks; */ + iface->clear_marks = gcal_week_view_clear_marks; } static void