[gnome-calendar/new-year-view] year-view: add event handling to navigator
- From: Erick Pérez Castellanos <erickpc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar/new-year-view] year-view: add event handling to navigator
- Date: Mon, 19 Jan 2015 19:01:28 +0000 (UTC)
commit b1167d54c1ecb697fab186eeaec55e584679de66
Author: Erick Pérez Castellanos <erick red gmail com>
Date: Sun Jan 18 23:34:06 2015 -0500
year-view: add event handling to navigator
data/theme/gtk-styles.css | 6 +-
data/ui/year-view.ui | 5 +-
src/gcal-year-view.c | 299 +++++++++++++++++++++++++++++++++++++++------
3 files changed, 268 insertions(+), 42 deletions(-)
---
diff --git a/data/theme/gtk-styles.css b/data/theme/gtk-styles.css
index d82bb94..87f2bff 100644
--- a/data/theme/gtk-styles.css
+++ b/data/theme/gtk-styles.css
@@ -100,13 +100,17 @@
font: 6;
}
-/* this is supposed be changed in sync with .calendar-view.current */
+/* these two are supposed be changed in sync with .calendar-view */
.year-navigator.current {
background-color: @theme_fg_color;
border-radius: 2px;
color: white;
font: bold;
}
+.year-navigator:selected {
+ color: @theme_selected_bg_color;
+ font-weight: bold;
+}
GcalEventWidget {
border-radius: 6px;
diff --git a/data/ui/year-view.ui b/data/ui/year-view.ui
index 276cbdc..1fad753 100644
--- a/data/ui/year-view.ui
+++ b/data/ui/year-view.ui
@@ -6,11 +6,14 @@
<object class="GtkDrawingArea" id="navigator">
<property name="visible">True</property>
<property name="hexpand">True</property>
+ <property
name="events">GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_STRUCTURE_MASK</property>
<signal name="draw" handler="draw_navigator" object="GcalYearView" swapped="yes" />
+ <signal name="button-press-event" handler="navigator_button_press_cb" object="GcalYearView"
swapped="yes" />
+ <signal name="button-release-event" handler="navigator_button_release_cb" object="GcalYearView"
swapped="yes" />
+ <signal name="motion-notify-event" handler="navigator_motion_notify_cb" object="GcalYearView"
swapped="yes" />
<style>
<class name="year-navigator" />
</style>
- <!-- FIXME: add some other signals handlers -->
</object>
<packing>
<property name="position">0</property>
diff --git a/src/gcal-year-view.c b/src/gcal-year-view.c
index 9d48c1a..2868877 100644
--- a/src/gcal-year-view.c
+++ b/src/gcal-year-view.c
@@ -22,11 +22,25 @@
#include "gcal-utils.h"
#include <math.h>
+#include <string.h>
#define NAVIGATOR_CELL_WIDTH (210 + 15)
#define NAVIGATOR_CELL_HEIGHT 210
#define SIDEBAR_PREFERRED_WIDTH 200
+typedef struct
+{
+ /* month span from 0 to 11 */
+ gint start_day, start_month;
+ gint end_day, end_month;
+} ButtonData;
+
+typedef struct
+{
+ gint box_side;
+ GdkPoint coordinates [12];
+} GridData;
+
struct _GcalYearViewPrivate
{
/* composite, GtkBuilder's widgets */
@@ -38,8 +52,13 @@ struct _GcalYearViewPrivate
/* manager singleton */
GcalManager *manager;
+ /* geometry info */
+ GridData *navigator_grid;
+
/* state flags */
gboolean popover_mode;
+ gboolean button_pressed;
+ ButtonData *selected_data;
/**
* first day of the week according to user locale, being
@@ -90,34 +109,111 @@ update_date (GcalYearView *year_view,
gtk_widget_queue_draw (GTK_WIDGET (year_view));
}
+static gboolean
+calculate_day_month_for_coord (GcalYearView *year_view,
+ gdouble x,
+ gdouble y,
+ gint *out_day,
+ gint *out_month)
+{
+ GcalYearViewPrivate *priv = year_view->priv;
+ gint row, column, i, sw, box_side, clicked_cell, day, month;
+
+ row = -1;
+ column = -1;
+ box_side = priv->navigator_grid->box_side;
+ sw = 1 - 2 * priv->k;
+
+ /* y selection */
+ for (i = 0; i < 4 && ((row == -1) || (column == -1)); i++)
+ {
+ if (row == -1 &&
+ y > priv->navigator_grid->coordinates[i * 4].y + box_side &&
+ y < priv->navigator_grid->coordinates[i * 4].y + box_side * 7)
+ {
+ row = i;
+ }
+ if (column == -1 &&
+ x > priv->navigator_grid->coordinates[i].x + box_side * 0.5 &&
+ x < priv->navigator_grid->coordinates[i].x + box_side * 7.5)
+ {
+ column = i;
+ }
+ }
+
+ if (row == -1 || column == -1)
+ return FALSE;
+
+ month = row * 4 + column;
+ row = (y - (priv->navigator_grid->coordinates[month].y + box_side)) / box_side;
+ column = (x - (priv->navigator_grid->coordinates[month].x + box_side * 0.5)) / box_side;
+ clicked_cell = row * 7 + column;
+ day = 7 * ((clicked_cell + 7 * priv->k) / 7) + sw * (clicked_cell % 7) + (1 - priv->k);
+ day -= ((time_day_of_week (1, month, priv->date->year) - priv->first_weekday + 7) % 7);
+
+ if (day < 1 || day > time_days_in_month (priv->date->year, month))
+ return FALSE;
+
+ *out_day = day;
+ *out_month = month;
+ return TRUE;
+}
+
+static void
+order_selected_data (ButtonData *selected_data)
+{
+ gint swap;
+ if (selected_data->end_month < selected_data->start_month)
+ {
+ swap = selected_data->start_month;
+ selected_data->start_month = selected_data->end_month;
+ selected_data->end_month = swap;
+
+ swap = selected_data->start_day;
+ selected_data->start_day = selected_data->end_day;
+ selected_data->end_day = swap;
+ }
+ else if (selected_data->start_month == selected_data->end_month && selected_data->end_day <
selected_data->start_day)
+ {
+ swap = selected_data->start_day;
+ selected_data->start_day = selected_data->end_day;
+ selected_data->end_day = swap;
+ }
+}
+
static void
draw_month_grid (GcalYearView *year_view,
GtkWidget *widget,
cairo_t *cr,
gint month_nr,
- gint *weeks_counter,
- gint block_side,
- gdouble x,
- gdouble y)
+ gint *weeks_counter)
{
GcalYearViewPrivate *priv = year_view->priv;
GtkStyleContext *context;
GtkStateFlags state_flags;
- PangoLayout *layout;
- PangoFontDescription *font_desc;
+ PangoLayout *layout, *slayout;
+ PangoFontDescription *font_desc, *sfont_desc;
GdkRGBA color;
gint layout_width, layout_height, i, j, sw;
- gint column, row, box_padding_top, box_padding_start;
+ gint x, y, column, row, box_side, box_padding_top, box_padding_start;
gint days_delay, days, shown_rows, sunday_idx;
gchar *str, *nr_day, *nr_week;
+ gboolean selected_day;
cairo_save (cr);
context = gtk_widget_get_style_context (widget);
state_flags = gtk_widget_get_state_flags (widget);
sw = 1 - 2 * priv->k;
+ box_side = priv->navigator_grid->box_side;
+ x = priv->navigator_grid->coordinates[month_nr].x;
+ y = priv->navigator_grid->coordinates[month_nr].y;
+
+ gtk_style_context_get (context, state_flags | GTK_STATE_FLAG_SELECTED, "font", &sfont_desc, NULL);
+ slayout = gtk_widget_create_pango_layout (widget, NULL);
+ pango_layout_set_font_description (slayout, sfont_desc);
/* header */
gtk_style_context_save (context);
@@ -129,11 +225,11 @@ draw_month_grid (GcalYearView *year_view,
layout = gtk_widget_create_pango_layout (widget, str);
pango_layout_set_font_description (layout, font_desc);
pango_layout_get_pixel_size (layout, &layout_width, &layout_height);
- gtk_render_layout (context, cr, x + (block_side * 8 - layout_width) / 2, y + (block_side - layout_height)
/ 2,
+ gtk_render_layout (context, cr, x + (box_side * 8 - layout_width) / 2, y + (box_side - layout_height) / 2,
layout);
gtk_render_background (context, cr,
- x + (block_side * 8 - layout_width) / 2, y + (block_side - layout_height) / 2,
+ x + (box_side * 8 - layout_width) / 2, y + (box_side - layout_height) / 2,
layout_width, layout_width);
pango_font_description_free (font_desc);
@@ -147,8 +243,8 @@ draw_month_grid (GcalYearView *year_view,
gtk_style_context_get_color (context, state_flags, &color);
cairo_set_line_width (cr, 0.2);
gdk_cairo_set_source_rgba (cr, &color);
- cairo_move_to (cr, x + block_side / 2, y + block_side + 0.4);
- cairo_rel_line_to (cr, 7 * block_side, 0);
+ cairo_move_to (cr, x + box_side / 2, y + box_side + 0.4);
+ cairo_rel_line_to (cr, 7 * box_side, 0);
cairo_stroke (cr);
gtk_style_context_restore (context);
@@ -180,8 +276,31 @@ draw_month_grid (GcalYearView *year_view,
nr_day = g_strdup_printf ("%d", j);
pango_layout_set_text (layout, nr_day, -1);
pango_layout_get_pixel_size (layout, &layout_width, &layout_height);
- box_padding_top = (block_side - layout_height) / 2 > 0 ? (block_side - layout_height) / 2 : 0;
- box_padding_start = (block_side - layout_width) / 2 > 0 ? (block_side - layout_width) / 2 : 0;
+ box_padding_top = (box_side - layout_height) / 2 > 0 ? (box_side - layout_height) / 2 : 0;
+ box_padding_start = (box_side - layout_width) / 2 > 0 ? (box_side - layout_width) / 2 : 0;
+
+ selected_day = FALSE;
+ if (priv->selected_data->start_day != 0)
+ {
+ ButtonData selected_data = *(priv->selected_data);
+ order_selected_data (&selected_data);
+ if (month_nr > selected_data.start_month && month_nr < selected_data.end_month)
+ {
+ selected_day = TRUE;
+ }
+ else if (month_nr == selected_data.start_month && month_nr == selected_data.end_month)
+ {
+ selected_day = j >= selected_data.start_day && j <= selected_data.end_day;
+ }
+ else if (month_nr == selected_data.start_month && j >= selected_data.start_day)
+ {
+ selected_day = TRUE;
+ }
+ else if (month_nr == selected_data.end_month && j <= selected_data.end_day)
+ {
+ selected_day = TRUE;
+ }
+ }
if (priv->date->year == priv->current_date->year && month_nr + 1 == priv->current_date->month &&
j == priv->current_date->day)
@@ -196,35 +315,53 @@ draw_month_grid (GcalYearView *year_view,
gtk_style_context_get (context, state_flags, "font", &cfont_desc, NULL);
pango_layout_set_font_description (clayout, cfont_desc);
pango_layout_get_pixel_size (clayout, &layout_width, &layout_height);
+ box_padding_top = (box_side - layout_height) / 2 > 0 ? (box_side - layout_height) / 2 : 0;
+ box_padding_start = (box_side - layout_width) / 2 > 0 ? (box_side - layout_width) / 2 : 0;
/* FIXME: hardcoded padding of the number background */
gtk_render_background (context, cr,
- block_side * (column + 0.5 + priv->k) + x + sw * box_padding_start -
priv->k * layout_width - 2.0,
- block_side * (row + 1) + y + box_padding_top - 1.0,
+ box_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k
* layout_width - 2.0,
+ box_side * (row + 1) + y + box_padding_top - 1.0,
layout_width + 4.0, layout_height + 2.0);
gtk_render_layout (context, cr,
- block_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
- block_side * (row + 1) + y + box_padding_top,
+ box_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
+ box_side * (row + 1) + y + box_padding_top,
clayout);
gtk_style_context_restore (context);
pango_font_description_free (cfont_desc);
g_object_unref (clayout);
}
+ else if (selected_day)
+ {
+ gtk_style_context_set_state (context, state_flags | GTK_STATE_FLAG_SELECTED);
+
+ pango_layout_set_text (slayout, nr_day, -1);
+ pango_layout_get_pixel_size (slayout, &layout_width, &layout_height);
+ box_padding_top = (box_side - layout_height) / 2 > 0 ? (box_side - layout_height) / 2 : 0;
+ box_padding_start = (box_side - layout_width) / 2 > 0 ? (box_side - layout_width) / 2 : 0;
+
+ gtk_render_layout (context, cr,
+ box_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
+ box_side * (row + 1) + y + box_padding_top,
+ slayout);
+
+ gtk_style_context_set_state (context, state_flags);
+ }
else if (column == sunday_idx)
{
gtk_style_context_add_class (context, "sunday");
gtk_render_layout (context, cr,
- block_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
- block_side * (row + 1) + y + box_padding_top,
+ box_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
+ box_side * (row + 1) + y + box_padding_top,
layout);
gtk_style_context_remove_class (context, "sunday");
}
else
{
gtk_render_layout (context, cr,
- block_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
- block_side * (row + 1) + y + box_padding_top,
+ box_side * (column + 0.5 + priv->k) + x + sw * box_padding_start - priv->k *
layout_width,
+ box_side * (row + 1) + y + box_padding_top,
layout);
}
@@ -254,19 +391,22 @@ draw_month_grid (GcalYearView *year_view,
pango_layout_set_text (layout, nr_week, -1);
pango_layout_get_pixel_size (layout, &layout_width, &layout_height);
- box_padding_top = (block_side - layout_height) / 2 > 0 ? (block_side - layout_height) / 2 : 0;
- box_padding_start = ((block_side / 2) - layout_width) / 2 > 0 ? ((block_side / 2) - layout_width) / 2
: 0;
+ box_padding_top = (box_side - layout_height) / 2 > 0 ? (box_side - layout_height) / 2 : 0;
+ box_padding_start = ((box_side / 2) - layout_width) / 2 > 0 ? ((box_side / 2) - layout_width) / 2 : 0;
gtk_render_layout (context, cr,
- x + sw * box_padding_start + priv->k * (8 * block_side - layout_width),
- block_side * (i + 1) + y + box_padding_top,
+ x + sw * box_padding_start + priv->k * (8 * box_side - layout_width),
+ box_side * (i + 1) + y + box_padding_top,
layout);
g_free (nr_week);
}
- pango_font_description_free (font_desc);
gtk_style_context_restore (context);
+ pango_font_description_free (sfont_desc);
+ g_object_unref (slayout);
+
+ pango_font_description_free (font_desc);
g_object_unref (layout);
cairo_restore (cr);
}
@@ -282,15 +422,13 @@ draw_navigator (GcalYearView *year_view,
GtkStateFlags state_flags;
gint header_padding_left, header_padding_top, header_height, layout_width, layout_height;
- gint width, height, real_padding_left, real_padding_top, block_side, i, sw, weeks_counter;
+ gint width, height, box_side, real_padding_left, real_padding_top, i, sw, weeks_counter;
gchar *header_str;
PangoLayout *header_layout;
PangoFontDescription *font_desc;
- GdkRGBA color;
-
priv = year_view->priv;
context = gtk_widget_get_style_context (GTK_WIDGET (year_view));
state_flags = gtk_widget_get_state_flags (GTK_WIDGET (year_view));
@@ -325,34 +463,106 @@ draw_navigator (GcalYearView *year_view,
g_free (header_str);
header_height = header_padding_top * 2 + layout_height;
-
- /* FIXME: debug statement, drawing frame */
- gtk_style_context_get_color (context, state_flags, &color);
-
height = gtk_widget_get_allocated_height (widget) - header_height;
if (((width / 4) / 8) < ((height / 3) / 7))
- block_side = (width / 4) / 8;
+ box_side = (width / 4) / 8;
else
- block_side = (height / 3) / 7;
+ box_side = (height / 3) / 7;
- real_padding_left = (width - (8 * 4 * block_side)) / 5;
- real_padding_top = (height - (7 * 3 * block_side)) / 5;
+ real_padding_left = (width - (8 * 4 * box_side)) / 5;
+ real_padding_top = (height - (7 * 3 * box_side)) / 4;
+ priv->navigator_grid->box_side = box_side;
weeks_counter = 1;
for (i = 0; i < 12; i++)
{
gint row = i / 4;
gint column = priv->k * 3 + sw * (i % 4);
- draw_month_grid (year_view, widget, cr, i, &weeks_counter, block_side,
- (column + 1) * real_padding_left + column * block_side * 8,
- (row + 1) * real_padding_top + row * block_side * 7 + header_height);
+ priv->navigator_grid->coordinates[i].x = (column + 1) * real_padding_left + column * box_side * 8;
+ priv->navigator_grid->coordinates[i].y = (row + 1) * real_padding_top + row * box_side * 7 +
header_height;
+ draw_month_grid (year_view, widget, cr, i, &weeks_counter);
}
return FALSE;
}
+static gboolean
+navigator_button_press_cb (GcalYearView *year_view,
+ GdkEventButton *event,
+ GtkWidget *widget)
+{
+ gint day, month;
+ if (!calculate_day_month_for_coord (year_view, event->x, event->y, &day, &month))
+ return FALSE;
+
+ year_view->priv->button_pressed = TRUE;
+ year_view->priv->selected_data->start_day = day;
+ year_view->priv->selected_data->start_month = month;
+
+ return TRUE;
+}
+
+static gboolean
+navigator_button_release_cb (GcalYearView *year_view,
+ GdkEventButton *event,
+ GtkWidget *widget)
+{
+ GcalYearViewPrivate *priv = year_view->priv;
+ gint day, month;
+
+ if (!priv->button_pressed)
+ return FALSE;
+
+ if (!calculate_day_month_for_coord (year_view, event->x, event->y, &day, &month))
+ goto fail;
+
+ priv->button_pressed = FALSE;
+ priv->selected_data->end_day = day;
+ priv->selected_data->end_month = month;
+ gtk_widget_queue_draw (widget);
+
+ /* FIXME: */
+ //update events on listbox
+ return TRUE;
+
+fail:
+ priv->button_pressed = FALSE;
+ memset (priv->selected_data, 0, sizeof (ButtonData));
+ gtk_widget_queue_draw (widget);
+
+ /* FIXME: */
+ //reset listbox to today
+ return TRUE;
+}
+
+static gboolean
+navigator_motion_notify_cb (GcalYearView *year_view,
+ GdkEventMotion *event,
+ GtkWidget *widget)
+{
+ GcalYearViewPrivate *priv = year_view->priv;
+ gint day, month;
+
+ if (!priv->button_pressed)
+ return FALSE;
+
+ if (!calculate_day_month_for_coord (year_view, event->x, event->y, &day, &month))
+ goto fail;
+
+ priv->selected_data->end_day = day;
+ priv->selected_data->end_month = month;
+ gtk_widget_queue_draw (widget);
+ return TRUE;
+
+fail:
+ priv->selected_data->end_day = priv->selected_data->start_day;
+ priv->selected_data->end_month = priv->selected_data->start_month;
+ gtk_widget_queue_draw (widget);
+ return TRUE;
+}
+
static void
add_event_clicked_cb (GcalYearView *year_view,
GtkButton *button)
@@ -365,6 +575,9 @@ gcal_year_view_finalize (GObject *object)
{
GcalYearViewPrivate *priv = GCAL_YEAR_VIEW (object)->priv;
+ g_free (priv->navigator_grid);
+ g_free (priv->selected_data);
+
if (priv->date != NULL)
g_free (priv->date);
@@ -520,6 +733,9 @@ gcal_year_view_class_init (GcalYearViewClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GcalYearView, events_listbox);
gtk_widget_class_bind_template_callback (widget_class, draw_navigator);
+ gtk_widget_class_bind_template_callback (widget_class, navigator_button_press_cb);
+ gtk_widget_class_bind_template_callback (widget_class, navigator_button_release_cb);
+ gtk_widget_class_bind_template_callback (widget_class, navigator_motion_notify_cb);
gtk_widget_class_bind_template_callback (widget_class, add_event_clicked_cb);
}
@@ -535,6 +751,9 @@ gcal_year_view_init (GcalYearView *self)
self->priv->k = 0;
else if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
self->priv->k = 1;
+
+ self->priv->navigator_grid = g_new0 (GridData, 1);
+ self->priv->selected_data = g_new0 (ButtonData, 1);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]