[gnome-calendar/gbsneto/gtk4: 3/13] week-view: Port to GTK4
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar/gbsneto/gtk4: 3/13] week-view: Port to GTK4
- Date: Wed, 2 Feb 2022 19:46:55 +0000 (UTC)
commit 27abf12d0b5f3b31725b4e958bd1b7234181404b
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Sun Jan 23 19:48:47 2022 -0300
week-view: Port to GTK4
src/gui/views/gcal-week-grid.c | 830 ++++++++++++++--------------------
src/gui/views/gcal-week-grid.h | 2 +-
src/gui/views/gcal-week-header.c | 758 ++++++++++++-------------------
src/gui/views/gcal-week-header.h | 2 +-
src/gui/views/gcal-week-header.ui | 143 ++----
src/gui/views/gcal-week-hour-bar.c | 144 ++++++
src/gui/views/gcal-week-hour-bar.h | 35 ++
src/gui/views/gcal-week-view-common.c | 87 ++++
src/gui/views/gcal-week-view-common.h | 34 ++
src/gui/views/gcal-week-view.c | 213 +--------
src/gui/views/gcal-week-view.ui | 10 +-
src/gui/views/meson.build | 2 +
src/theme/Adwaita.css | 33 +-
src/utils/gcal-utils.c | 26 +-
src/utils/gcal-utils.h | 2 +-
15 files changed, 1001 insertions(+), 1320 deletions(-)
---
diff --git a/src/gui/views/gcal-week-grid.c b/src/gui/views/gcal-week-grid.c
index 8df2a5e4..e4bc29cf 100644
--- a/src/gui/views/gcal-week-grid.c
+++ b/src/gui/views/gcal-week-grid.c
@@ -25,6 +25,7 @@
#include "gcal-debug.h"
#include "gcal-week-grid.h"
#include "gcal-week-view.h"
+#include "gcal-week-view-common.h"
#include "gcal-utils.h"
#include "gcal-view.h"
#include "gcal-event-widget.h"
@@ -34,12 +35,6 @@
#include <string.h>
#include <math.h>
-static const double dashed [] =
-{
- 5.0,
- 6.0
-};
-
typedef struct
{
GtkWidget *widget;
@@ -48,10 +43,11 @@ typedef struct
struct _GcalWeekGrid
{
- GtkContainer parent;
+ GtkWidget parent;
GtkWidget *hours_sidebar;
- GdkWindow *event_window;
+ GtkWidget *now_strip;
+ GtkEventController *motion_controller;
GDateTime *active_date;
@@ -68,7 +64,7 @@ struct _GcalWeekGrid
GcalContext *context;
};
-G_DEFINE_TYPE (GcalWeekGrid, gcal_week_grid, GTK_TYPE_CONTAINER);
+G_DEFINE_TYPE (GcalWeekGrid, gcal_week_grid, GTK_TYPE_WIDGET);
enum
@@ -79,7 +75,10 @@ enum
static guint signals[LAST_SIGNAL] = { 0, };
-/* ChildData methods */
+/*
+ * Auxiliary methods
+ */
+
static ChildData*
child_data_new (GtkWidget *widget,
GcalEvent *event)
@@ -93,31 +92,19 @@ child_data_new (GtkWidget *widget,
return data;
}
-/* Event activation methods */
static void
-on_event_widget_activated (GcalEventWidget *widget,
- GcalWeekGrid *self)
+child_data_free (gpointer data)
{
- g_signal_emit (self, signals[EVENT_ACTIVATED], 0, widget);
-}
+ ChildData *child_data = data;
+ if (!child_data)
+ return;
-static inline void
-setup_event_widget (GcalWeekGrid *self,
- GtkWidget *widget)
-{
- g_signal_connect (widget, "activate", G_CALLBACK (on_event_widget_activated), self);
-}
-
-static inline void
-destroy_event_widget (GcalWeekGrid *self,
- GtkWidget *widget)
-{
- g_signal_handlers_disconnect_by_func (widget, on_event_widget_activated, self);
- gtk_widget_destroy (widget);
+ g_clear_pointer (&child_data->widget, gtk_widget_unparent);
+ g_clear_object (&child_data->event);
+ g_free (child_data);
}
-/* Auxiliary methods */
static inline gint
uint16_compare (gconstpointer a,
gconstpointer b)
@@ -187,156 +174,191 @@ count_overlaps_at_range (GcalRangeTree *self,
return counter;
}
+/*
+ * Callbacks
+ */
+
static void
-gcal_week_grid_finalize (GObject *object)
+on_click_gesture_pressed_cb (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GcalWeekGrid *self)
{
- GcalWeekGrid *self = GCAL_WEEK_GRID (object);
+ GtkAllocation alloc;
+ gdouble minute_height;
+ gint column_width;
+ gint column;
+ gint minute;
- g_clear_pointer (&self->events, gcal_range_tree_unref);
- gcal_clear_date_time (&self->active_date);
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+ minute_height = (gdouble) alloc.height / MINUTES_PER_DAY;
+ column_width = floor (alloc.width / 7);
+ column = (gint) x / column_width;
+ minute = y / minute_height;
+ minute = minute - (minute % 30);
- G_OBJECT_CLASS (gcal_week_grid_parent_class)->finalize (object);
+ self->selection_start = (column * MINUTES_PER_DAY + minute) / 30;
+ self->selection_end = self->selection_start;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_BUBBLE);
}
static void
-gcal_week_grid_add (GtkContainer *container,
- GtkWidget *widget)
+on_event_widget_activated_cb (GcalEventWidget *widget,
+ GcalWeekGrid *self)
{
- if (!gtk_widget_get_parent (widget))
- gtk_widget_set_parent (widget, GTK_WIDGET (container));
+ g_signal_emit (self, signals[EVENT_ACTIVATED], 0, widget);
}
static void
-gcal_week_grid_remove (GtkContainer *container,
- GtkWidget *widget)
+on_motion_controller_motion_cb (GtkEventControllerMotion *motion_controller,
+ gdouble x,
+ gdouble y,
+ GcalWeekGrid *self)
{
+ GtkAllocation alloc;
+ gdouble minute_height;
+ gint column;
+ gint minute;
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+ minute_height = (gdouble) alloc.height / MINUTES_PER_DAY;
+ column = self->selection_start * 30 / MINUTES_PER_DAY;
+ minute = y / minute_height;
+ minute = minute - (minute % 30);
+
+ self->selection_end = (column * MINUTES_PER_DAY + minute) / 30;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
-gcal_week_grid_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data)
+on_click_gesture_released_cb (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GcalWeekGrid *self)
{
- GcalWeekGrid *self;
- GPtrArray *widgets_data;
- guint i;
+ g_autoptr (GDateTime) week_start = NULL;
+ g_autoptr (GDateTime) start = NULL;
+ g_autoptr (GDateTime) end = NULL;
+ GtkAllocation alloc;
+ GtkWidget *weekview;
+ gboolean ltr;
+ gdouble minute_height;
+ gdouble local_x;
+ gdouble local_y;
+ gdouble out_x;
+ gdouble out_y;
+ gint column;
+ gint minute;
+ gint start_cell;
+ gint end_cell;
- self = GCAL_WEEK_GRID (container);
- widgets_data = gcal_range_tree_get_all_data (self->events);
+ ltr = gtk_widget_get_direction (GTK_WIDGET (self)) != GTK_TEXT_DIR_RTL;
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+ minute_height = (gdouble) alloc.height / MINUTES_PER_DAY;
+ column = self->selection_start * 30 / MINUTES_PER_DAY;
+ minute = y / minute_height;
+ minute = minute - (minute % 30);
+
+ self->selection_end = (column * MINUTES_PER_DAY + minute) / 30;
- for (i = 0; i < widgets_data->len; i++)
+ start_cell = self->selection_start;
+ end_cell = self->selection_end;
+
+ if (start_cell > end_cell)
{
- ChildData *data;
+ start_cell = start_cell + end_cell;
+ end_cell = start_cell - end_cell;
+ start_cell = start_cell - end_cell;
+ }
- data = g_ptr_array_index (widgets_data, i);
- callback (data->widget, callback_data);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ /* Fake the week view's event so we can control the X and Y values */
+ weekview = gtk_widget_get_ancestor (GTK_WIDGET (self), GCAL_TYPE_WEEK_VIEW);
+ week_start = gcal_date_time_get_start_of_week (self->active_date);
+
+ if (ltr)
+ {
+ start = g_date_time_add_minutes (week_start, start_cell * 30);
+ end = g_date_time_add_minutes (week_start, (end_cell + 1) * 30);
}
+ else
+ {
+ guint rtl_start_cell, rtl_end_cell, rtl_column;
- g_clear_pointer (&widgets_data, g_ptr_array_unref);
-}
+ /* Fix the minute */
+ rtl_column = 6 - column;
+ rtl_start_cell = start_cell + (rtl_column - column) * 48;
+ rtl_end_cell = (rtl_column * MINUTES_PER_DAY + minute) / 30;
-static void
-gcal_week_grid_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
+ start = g_date_time_add_minutes (week_start, rtl_start_cell * 30);
+ end = g_date_time_add_minutes (week_start, (rtl_end_cell + 1) * 30);
+ }
-static void
-gcal_week_grid_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
+ local_x = round ((column + 0.5) * (alloc.width / 7.0));
+ local_y = (minute + 15) * minute_height;
-static void
-gcal_week_grid_realize (GtkWidget *widget)
-{
- GcalWeekGrid *self;
- GdkWindow *parent_window;
- GdkWindowAttr attributes;
- gint attributes_mask;
- GtkAllocation allocation;
+ gtk_widget_translate_coordinates (GTK_WIDGET (self),
+ weekview,
+ local_x,
+ local_y,
+ &out_x,
+ &out_y);
- self = GCAL_WEEK_GRID (widget);
- parent_window = gtk_widget_get_parent_window (widget);
-
- gtk_widget_set_realized (widget, TRUE);
- gtk_widget_set_window (widget, parent_window);
- g_object_ref (parent_window);
-
- gtk_widget_get_allocation (widget, &allocation);
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.wclass = GDK_INPUT_ONLY;
- attributes.x = allocation.x;
- attributes.y = allocation.y;
- attributes.width = allocation.width;
- attributes.height = allocation.height;
- attributes.event_mask = gtk_widget_get_events (widget);
- attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_BUTTON1_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK |
- GDK_SCROLL_MASK |
- GDK_SMOOTH_SCROLL_MASK);
- attributes_mask = GDK_WA_X | GDK_WA_Y;
-
- self->event_window = gdk_window_new (parent_window,
- &attributes,
- attributes_mask);
- gtk_widget_register_window (widget, self->event_window);
+ g_signal_emit_by_name (weekview,
+ "create-event",
+ start,
+ end,
+ out_x,
+ out_y);
+
+ gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
}
static void
-gcal_week_grid_unrealize (GtkWidget *widget)
+gcal_week_grid_dispose (GObject *object)
{
- GcalWeekGrid *self;
-
- self = GCAL_WEEK_GRID (widget);
+ GcalWeekGrid *self = GCAL_WEEK_GRID (object);
- if (self->event_window)
- {
- gtk_widget_unregister_window (widget, self->event_window);
- gdk_window_destroy (self->event_window);
- self->event_window = NULL;
- }
+ g_clear_pointer (&self->events, gcal_range_tree_unref);
+ g_clear_pointer (&self->now_strip, gtk_widget_unparent);
- GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->unrealize (widget);
+ G_OBJECT_CLASS (gcal_week_grid_parent_class)->dispose (object);
}
static void
-gcal_week_grid_map (GtkWidget *widget)
+gcal_week_grid_finalize (GObject *object)
{
- GcalWeekGrid *self;
-
- self = GCAL_WEEK_GRID (widget);
+ GcalWeekGrid *self = GCAL_WEEK_GRID (object);
- if (self->event_window)
- gdk_window_show (self->event_window);
+ gcal_clear_date_time (&self->active_date);
- GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->map (widget);
+ G_OBJECT_CLASS (gcal_week_grid_parent_class)->finalize (object);
}
static void
-gcal_week_grid_unmap (GtkWidget *widget)
+gcal_week_grid_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GcalWeekGrid *self;
-
- self = GCAL_WEEK_GRID (widget);
-
- if (self->event_window)
- gdk_window_hide (self->event_window);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
- GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->unmap (widget);
+static void
+gcal_week_grid_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static inline gint
@@ -357,40 +379,95 @@ get_today_column (GcalWeekGrid *self)
return days_diff;
}
-static gboolean
-gcal_week_grid_draw (GtkWidget *widget,
- cairo_t *cr)
+static void
+gcal_week_grid_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ g_autoptr (PangoLayout) layout = NULL;
+ PangoFontDescription *font_desc;
+ GtkStyleContext *context;
+ PangoContext *pango_context;
+ GtkBorder padding;
+ gint hours_12_height;
+ gint hours_24_height;
+ gint cell_height;
+ gint height;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (minimum)
+ *minimum = 1;
+ if (natural)
+ *natural = 1;
+ return;
+ }
+
+ context = gtk_widget_get_style_context (widget);
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "hours");
+
+ gtk_style_context_get_padding (context, &padding);
+
+ pango_context = gtk_widget_get_pango_context (widget);
+ font_desc = pango_context_get_font_description (pango_context);
+
+ layout = pango_layout_new (pango_context);
+ pango_layout_set_font_description (layout, font_desc);
+
+ pango_layout_set_text (layout, _("00 AM"), -1);
+ pango_layout_get_pixel_size (layout, NULL, &hours_12_height);
+
+ pango_layout_set_text (layout, _("00:00"), -1);
+ pango_layout_get_pixel_size (layout, NULL, &hours_24_height);
+
+ cell_height = MAX (hours_12_height, hours_24_height) + padding.top + padding.bottom;
+ height = cell_height * 48;
+
+ gtk_style_context_restore (context);
+
+ /* Report the height */
+ if (minimum)
+ *minimum = height;
+
+ if (natural)
+ *natural = height;
+}
+
+static void
+gcal_week_grid_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
+ g_autoptr (GPtrArray) widgets = NULL;
GtkStyleContext *context;
GtkStateFlags state;
GcalWeekGrid *self;
GtkBorder padding;
GdkRGBA color;
-
- gboolean ltr;
gdouble minutes_height;
gdouble x, column_width;
- gint i, width, height, today_column;
+ guint i;
+ gint width, height;
self = GCAL_WEEK_GRID (widget);
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
gtk_style_context_save (context);
gtk_style_context_add_class (context, "lines");
- gtk_style_context_get_color (context, state, &color);
- gtk_style_context_get_padding (context, state, &padding);
+ gtk_style_context_get_color (context, &color);
+ gtk_style_context_get_padding (context, &padding);
- gdk_cairo_set_source_rgba (cr, &color);
-
- width = gtk_widget_get_allocated_width (widget);
- height = gtk_widget_get_allocated_height (widget);
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_height (widget);
column_width = width / 7.0;
minutes_height = (gdouble) height / MINUTES_PER_DAY;
- cairo_set_line_width (cr, 0.65);
-
/* First, draw the selection */
if (self->selection_start != -1 && self->selection_end != -1)
{
@@ -418,12 +495,12 @@ gcal_week_grid_draw (GtkWidget *widget,
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_snapshot_render_background (snapshot,
+ context,
+ ALIGNED (x),
+ round ((start * 30 % MINUTES_PER_DAY) * minutes_height),
+ column_width,
+ selection_height);
gtk_style_context_restore (context);
}
@@ -438,93 +515,35 @@ gcal_week_grid_draw (GtkWidget *widget,
column = self->dnd_cell / (MINUTES_PER_DAY / 30);
row = self->dnd_cell - column * 48;
- gtk_render_background (context,
- cr,
- column * column_width,
- row * cell_height,
- column_width,
- cell_height);
- }
-
- /* Vertical lines */
- for (i = 0; i < 7; i++)
- {
- if (ltr)
- x = column_width * i;
- else
- x = width - column_width * i;
-
- cairo_move_to (cr, ALIGNED (x), 0);
- cairo_rel_line_to (cr, 0, height);
+ gtk_snapshot_render_background (snapshot,
+ context,
+ column * column_width,
+ row * cell_height,
+ column_width,
+ cell_height);
}
- /* Horizontal lines */
- for (i = 1; i < 24; i++)
- {
- cairo_move_to (cr, 0, ALIGNED ((height / 24.0) * i));
- cairo_rel_line_to (cr, width, 0);
- }
-
- cairo_stroke (cr);
-
- /* Dashed lines between the vertical lines */
- cairo_set_dash (cr, dashed, 2, 0);
-
- for (i = 0; i < 24; i++)
- {
- cairo_move_to (cr, 0, ALIGNED ((height / 24.0) * i + (height / 48.0)));
- cairo_rel_line_to (cr, width, 0);
- }
-
- cairo_stroke (cr);
+ gcal_week_view_common_snapshot_hour_lines (widget, snapshot, GTK_ORIENTATION_HORIZONTAL, &color, width,
height);
+ gcal_week_view_common_snapshot_hour_lines (widget, snapshot, GTK_ORIENTATION_VERTICAL, &color, width,
height);
gtk_style_context_restore (context);
- GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->draw (widget, cr);
-
- /* Today column */
- today_column = get_today_column (GCAL_WEEK_GRID (widget));
-
- if (today_column != -1)
+ widgets = gcal_range_tree_get_all_data (self->events);
+ for (i = 0; i < widgets->len; i++)
{
- g_autoptr (GDateTime) now = NULL;
- GtkBorder margin;
- gdouble strip_width;
- guint minutes_from_midnight;
- gint min_stip_height;
-
- now = g_date_time_new_now_local ();
- minutes_from_midnight = g_date_time_get_hour (now) * 60 + g_date_time_get_minute (now);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "now-strip");
-
- gtk_style_context_get (context, state, "min-height", &min_stip_height, NULL);
- gtk_style_context_get_margin (context, state, &margin);
-
- strip_width = column_width - margin.left - margin.right;
-
- if (ltr)
- x = today_column * column_width + margin.left;
- else
- x = width - (today_column * column_width + margin.right) - strip_width;
-
- gtk_render_background (context,
- cr,
- x,
- round (minutes_from_midnight * ((gdouble) height / MINUTES_PER_DAY) +
margin.top),
- strip_width,
- MAX (1, min_stip_height - margin.top - margin.bottom));
+ ChildData *child_data = g_ptr_array_index (widgets, i);
- gtk_style_context_restore (context);
+ gtk_widget_snapshot_child (widget, child_data->widget, snapshot);
}
- return FALSE;
+ gtk_widget_snapshot_child (widget, self->now_strip, snapshot);
}
static void
-gcal_week_grid_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+gcal_week_grid_size_allocate (GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
{
GcalWeekGrid *self = GCAL_WEEK_GRID (widget);
g_autoptr (GDateTime) week_start = NULL;
@@ -534,25 +553,13 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
gdouble column_width;
guint x, y;
guint i;
-
- /* Allocate the widget */
- gtk_widget_set_allocation (widget, allocation);
+ gint today_column;
ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
- if (gtk_widget_get_realized (widget))
- {
- gdk_window_move_resize (self->event_window,
- allocation->x,
- allocation->y,
- allocation->width,
- allocation->height);
- }
-
-
/* Preliminary calculations */
- minutes_height = (gdouble) allocation->height / MINUTES_PER_DAY;
- column_width = (gdouble) allocation->width / 7.0;
+ minutes_height = (gdouble) height / MINUTES_PER_DAY;
+ column_width = (gdouble) width / 7.0;
/* Temporary range tree to hold positioned events' indexes */
overlaps = gcal_range_tree_new ();
@@ -578,26 +585,27 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
{
g_autoptr (GDateTime) event_start = NULL;
g_autoptr (GDateTime) event_end = NULL;
- GtkStyleContext *context;
GtkAllocation child_allocation;
GtkWidget *event_widget;
GcalRange *event_range;
ChildData *data;
- GtkBorder margin;
guint64 events_at_range;
gint event_minutes;
gint natural_height;
gint widget_index;
gint offset;
- gint height;
- gint width;
+ gint event_height;
+ gint event_width;
data = g_ptr_array_index (widgets_data, j);
event_widget = data->widget;
+
+ if (!gtk_widget_should_layout (event_widget))
+ continue;
+
event_range = gcal_event_get_range (data->event);
event_start = g_date_time_to_local (gcal_event_get_date_start (data->event));
event_end = g_date_time_to_local (gcal_event_get_date_end (data->event));
- context = gtk_widget_get_style_context (event_widget);
/* The total number of events available in this range */
events_at_range = count_overlaps_at_range (self->events, event_range);
@@ -606,36 +614,26 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
widget_index = get_event_index (overlaps, event_range);
/* Gtk complains about that */
- gtk_widget_get_preferred_height (event_widget, NULL, &natural_height);
-
- /* Consider the margins of the child */
- gtk_style_context_get_margin (context,
- gtk_style_context_get_state (context),
- &margin);
+ gtk_widget_measure (event_widget, GTK_ORIENTATION_VERTICAL, -1, NULL, &natural_height, NULL, NULL);
event_minutes = g_date_time_difference (event_end, event_start) / G_TIME_SPAN_MINUTE;
- width = column_width / events_at_range - margin.left - margin.right;
- height = event_minutes * minutes_height - margin.top - margin.bottom;
- offset = (width + margin.left + margin.right) * widget_index;
- y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) *
minutes_height + margin.top;
+ event_width = column_width / events_at_range;
+ event_height = event_minutes * minutes_height;
+ offset = event_width * widget_index;
+ y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) *
minutes_height;
if (ltr)
- x = column_width * i + offset + allocation->x + margin.left + 1;
+ x = column_width * i + offset + 1;
else
- x = allocation->width - width - (column_width * i + offset + allocation->x + margin.left + 1);
-
- /* TODO: find a better way to handle line widths */
- height -= 2;
- width -= 1;
- y += 2;
+ x = width - event_width - (column_width * i + offset + x + 1);
/* Setup the child position and size */
child_allocation.x = x;
child_allocation.y = y;
- child_allocation.width = width;
- child_allocation.height = height;
+ child_allocation.width = event_width;
+ child_allocation.height = event_height;
- gtk_widget_size_allocate (event_widget, &child_allocation);
+ gtk_widget_size_allocate (event_widget, &child_allocation, baseline);
/*
* Add the current event to the temporary overlaps tree so we have a way to
@@ -648,202 +646,45 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
}
g_clear_pointer (&overlaps, gcal_range_tree_unref);
-}
-
-static void
-gcal_week_grid_get_preferred_height (GtkWidget *widget,
- gint *minimum_height,
- gint *natural_height)
-{
- GtkStyleContext *context;
- GtkStateFlags state;
- GtkBorder padding;
-
- PangoLayout *layout;
- PangoFontDescription *font_desc;
-
- gint hours_12_height, hours_24_height, cell_height, height;
-
- context = gtk_widget_get_style_context (widget);
- state = gtk_style_context_get_state (context);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "hours");
-
- gtk_style_context_get (context, state,
- "font", &font_desc,
- NULL);
- gtk_style_context_get_padding (context, state, &padding);
-
- layout = pango_layout_new (gtk_widget_get_pango_context (widget));
- pango_layout_set_font_description (layout, font_desc);
-
- pango_layout_set_text (layout, _("00 AM"), -1);
- pango_layout_get_pixel_size (layout, NULL, &hours_12_height);
-
- pango_layout_set_text (layout, _("00:00"), -1);
- pango_layout_get_pixel_size (layout, NULL, &hours_24_height);
-
- cell_height = MAX (hours_12_height, hours_24_height) + padding.top + padding.bottom;
- height = cell_height * 48;
-
- gtk_style_context_restore (context);
-
- pango_font_description_free (font_desc);
- g_object_unref (layout);
-
- /* Report the height */
- if (minimum_height)
- *minimum_height = height;
-
- if (natural_height)
- *natural_height = height;
-}
-
-static gboolean
-gcal_week_grid_button_press (GtkWidget *widget,
- GdkEventButton *event_button)
-{
- GcalWeekGrid *self;
- GtkAllocation alloc;
- gdouble minute_height;
- gint column_width;
- gint column;
- gint minute;
-
- self = GCAL_WEEK_GRID (widget);
-
- 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_PROPAGATE;
-}
-
-static gboolean
-gcal_week_grid_motion_notify_event (GtkWidget *widget,
- GdkEventMotion *event)
-{
- GcalWeekGrid *self;
- GtkAllocation alloc;
- gdouble minute_height;
- gint column;
- gint minute;
-
- if (!(event->state & GDK_BUTTON_PRESS_MASK))
- return GDK_EVENT_PROPAGATE;
-
- self = GCAL_WEEK_GRID (widget);
-
- 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 start_cell;
- gint end_cell;
- 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;
+ /* Today column */
+ today_column = get_today_column (GCAL_WEEK_GRID (widget));
- start_cell = self->selection_start;
- end_cell = self->selection_end;
+ gtk_widget_set_child_visible (self->now_strip, today_column != -1);
- if (start_cell > end_cell)
+ if (today_column != -1)
{
- start_cell = start_cell + end_cell;
- end_cell = start_cell - end_cell;
- start_cell = start_cell - end_cell;
- }
+ g_autoptr (GDateTime) now = NULL;
+ GtkAllocation allocation;
+ guint minutes_from_midnight;
+ gint now_strip_height;
- gtk_widget_queue_draw (widget);
+ now = g_date_time_new_now_local ();
+ minutes_from_midnight = g_date_time_get_hour (now) * 60 + g_date_time_get_minute (now);
- /* 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 = gcal_date_time_get_start_of_week (self->active_date);
+ gtk_widget_measure (self->now_strip,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ &now_strip_height,
+ NULL,
+ NULL,
+ NULL);
- if (ltr)
- {
- start = g_date_time_add_minutes (week_start, start_cell * 30);
- end = g_date_time_add_minutes (week_start, (end_cell + 1) * 30);
- }
- else
- {
- guint rtl_start_cell, rtl_end_cell, rtl_column;
+ if (ltr)
+ x = today_column * column_width;
+ else
+ x = width - (today_column * column_width) - column_width;
- /* Fix the minute */
- rtl_column = 6 - column;
- rtl_start_cell = start_cell + (rtl_column - column) * 48;
- rtl_end_cell = (rtl_column * MINUTES_PER_DAY + minute) / 30;
+ allocation.x = x;
+ allocation.y = round (minutes_from_midnight * ((gdouble) height / MINUTES_PER_DAY));
+ allocation.width = column_width;
+ allocation.height = MAX (1, now_strip_height);
- start = g_date_time_add_minutes (week_start, rtl_start_cell * 30);
- end = g_date_time_add_minutes (week_start, (rtl_end_cell + 1) * 30);
+ gtk_widget_size_allocate (self->now_strip, &allocation, baseline);
}
-
- 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_date_time (&week_start);
- gcal_clear_date_time (&start);
- gcal_clear_date_time (&end);
-
- return GDK_EVENT_STOP;
}
+#if 0 // TODO: DND
static gint
get_dnd_cell (GtkWidget *widget,
gint x,
@@ -995,35 +836,22 @@ gcal_week_grid_drag_leave (GtkWidget *widget,
gtk_widget_queue_draw (widget);
}
+#endif
static void
gcal_week_grid_class_init (GcalWeekGridClass *klass)
{
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- container_class->add = gcal_week_grid_add;
- container_class->remove = gcal_week_grid_remove;
- container_class->forall = gcal_week_grid_forall;
-
+ object_class->dispose = gcal_week_grid_dispose;
object_class->finalize = gcal_week_grid_finalize;
object_class->get_property = gcal_week_grid_get_property;
object_class->set_property = gcal_week_grid_set_property;
- widget_class->draw = gcal_week_grid_draw;
+ widget_class->measure = gcal_week_grid_measure;
widget_class->size_allocate = gcal_week_grid_size_allocate;
- widget_class->realize = gcal_week_grid_realize;
- widget_class->unrealize = gcal_week_grid_unrealize;
- 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;
- widget_class->drag_motion = gcal_week_grid_drag_motion;
- widget_class->drag_leave = gcal_week_grid_drag_leave;
- widget_class->drag_drop = gcal_week_grid_drag_drop;
+ widget_class->snapshot = gcal_week_grid_snapshot;
signals[EVENT_ACTIVATED] = g_signal_new ("event-activated",
GCAL_TYPE_WEEK_GRID,
@@ -1039,20 +867,38 @@ gcal_week_grid_class_init (GcalWeekGridClass *klass)
static void
gcal_week_grid_init (GcalWeekGrid *self)
{
- gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+ GtkGesture *click_gesture;
self->selection_start = -1;
self->selection_end = -1;
self->dnd_cell = -1;
- self->events = gcal_range_tree_new ();
+ self->events = gcal_range_tree_new_with_free_func (child_data_free);
+
+ self->now_strip = adw_bin_new ();
+ gtk_widget_add_css_class (self->now_strip, "now-strip");
+ gtk_widget_set_can_target (self->now_strip, FALSE);
+ gtk_widget_set_parent (self->now_strip, GTK_WIDGET (self));
+ click_gesture = gtk_gesture_click_new ();
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (click_gesture), GDK_BUTTON_PRIMARY);
+ g_signal_connect (click_gesture, "pressed", G_CALLBACK (on_click_gesture_pressed_cb), self);
+ g_signal_connect (click_gesture, "released", G_CALLBACK (on_click_gesture_released_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (click_gesture));
+
+ self->motion_controller = gtk_event_controller_motion_new ();
+ g_signal_connect (self->motion_controller, "motion", G_CALLBACK (on_motion_controller_motion_cb), self);
+ gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
+ gtk_widget_add_controller (GTK_WIDGET (self), self->motion_controller);
+
+#if 0 // TODO: DND
/* Setup the week view as a drag n' drop destination */
gtk_drag_dest_set (GTK_WIDGET (self),
0,
NULL,
0,
GDK_ACTION_MOVE);
+#endif
}
/* Public API */
@@ -1066,8 +912,8 @@ gcal_week_grid_set_context (GcalWeekGrid *self,
g_signal_connect_object (gcal_context_get_clock (context),
"minute-changed",
- G_CALLBACK (gtk_widget_queue_draw),
- self,
+ G_CALLBACK (gtk_widget_queue_resize),
+ self->now_strip,
G_CONNECT_SWAPPED);
}
@@ -1091,10 +937,9 @@ gcal_week_grid_add_event (GcalWeekGrid *self,
gcal_event_get_range (event),
child_data_new (widget, event));
- setup_event_widget (self, widget);
- gtk_widget_show (widget);
+ g_signal_connect (widget, "activate", G_CALLBACK (on_event_widget_activated_cb), self);
- gtk_container_add (GTK_CONTAINER (self), widget);
+ gtk_widget_set_parent (widget, GTK_WIDGET (self));
}
void
@@ -1120,10 +965,7 @@ gcal_week_grid_remove_event (GcalWeekGrid *self,
continue;
gcal_range_tree_remove_range (self->events, gcal_event_get_range (event), data);
- destroy_event_widget (self, data->widget);
gtk_widget_queue_allocate (GTK_WIDGET (self));
- g_object_unref (event);
- g_free (data);
}
g_clear_pointer (&widgets, g_ptr_array_unref);
@@ -1134,29 +976,13 @@ gcal_week_grid_get_children_by_uuid (GcalWeekGrid *self,
GcalRecurrenceModType mod,
const gchar *uid)
{
- GPtrArray *widgets;
- GList *events;
- GList *result;
- guint i;
+ g_autoptr (GList) result = NULL;
GCAL_ENTRY;
- events = NULL;
- result = NULL;
- widgets = gcal_range_tree_get_all_data (self->events);
-
- for (i = 0; widgets && i < widgets->len; i++)
- {
- ChildData *data = g_ptr_array_index (widgets, i);
- events = g_list_prepend (events, data->widget);
- }
-
- result = filter_event_list_by_uid_and_modtype (events, mod, uid);
-
- g_clear_pointer (&widgets, g_ptr_array_unref);
- g_clear_pointer (&events, g_list_free);
+ result = filter_children_by_uid_and_modtype (GTK_WIDGET (self), mod, uid);
- GCAL_RETURN (result);
+ GCAL_RETURN (g_steal_pointer (&result));
}
void
diff --git a/src/gui/views/gcal-week-grid.h b/src/gui/views/gcal-week-grid.h
index f21487c0..299ebe4d 100644
--- a/src/gui/views/gcal-week-grid.h
+++ b/src/gui/views/gcal-week-grid.h
@@ -28,7 +28,7 @@ G_BEGIN_DECLS
#define GCAL_TYPE_WEEK_GRID (gcal_week_grid_get_type())
-G_DECLARE_FINAL_TYPE (GcalWeekGrid, gcal_week_grid, GCAL, WEEK_GRID, GtkContainer)
+G_DECLARE_FINAL_TYPE (GcalWeekGrid, gcal_week_grid, GCAL, WEEK_GRID, GtkWidget)
void gcal_week_grid_set_context (GcalWeekGrid *week_grid,
GcalContext *context);
diff --git a/src/gui/views/gcal-week-header.c b/src/gui/views/gcal-week-header.c
index e722bdb6..3ccc8105 100644
--- a/src/gui/views/gcal-week-header.c
+++ b/src/gui/views/gcal-week-header.c
@@ -30,13 +30,12 @@
#include "gcal-view.h"
#include "gcal-week-header.h"
#include "gcal-week-view.h"
+#include "gcal-week-view-common.h"
#include <glib/gi18n.h>
#include <string.h>
#include <math.h>
-#define COLUMN_PADDING 6
-
/* WeatherInfoDay:
* @winfo: (nullable): Holds weather information for this week-day. All other fields are only valid if this
one is not %NULL.
* @icon_buf: (nullable): Buffered weather icon.
@@ -52,22 +51,29 @@
typedef struct
{
GcalWeatherInfo *winfo; /* owned */
- GdkPixbuf *icon_buf; /* owned */
+ GtkIconPaintable *icon_buf; /* owned */
} WeatherInfoDay;
+typedef struct
+{
+ GtkWidget *day_number_label;
+ GtkWidget *weekday_name_label;
+} WeekdayHeader;
+
struct _GcalWeekHeader
{
- GtkGrid parent;
+ GtkBox parent;
- GtkWidget *grid;
+ GtkGrid *grid;
GtkWidget *month_label;
GtkWidget *week_label;
GtkWidget *year_label;
GtkWidget *scrolledwindow;
- GtkWidget *expand_button;
+ GtkButton *expand_button;
GtkWidget *expand_button_box;
- GtkWidget *expand_button_image;
GtkWidget *header_labels_box;
+ GtkEventController *motion_controller;
+ GtkBox *weekdays_box;
GcalContext *context;
@@ -78,6 +84,7 @@ struct _GcalWeekHeader
*/
GList *events[7];
GtkWidget *overflow_label[7];
+ WeekdayHeader weekday_header[7];
gint first_weekday;
@@ -113,7 +120,7 @@ enum
static guint signals[LAST_SIGNAL] = { 0, };
-G_DEFINE_TYPE (GcalWeekHeader, gcal_week_header, GTK_TYPE_GRID);
+G_DEFINE_TYPE (GcalWeekHeader, gcal_week_header, GTK_TYPE_BOX);
/* WeatherInfoDay methods */
@@ -128,11 +135,8 @@ wid_clear (WeatherInfoDay *wid)
{
g_return_if_fail (wid != NULL);
- if (wid->winfo != NULL)
- g_clear_object (&wid->winfo);
-
- if (wid->icon_buf != NULL)
- g_clear_object (&wid->icon_buf);
+ g_clear_object (&wid->winfo);
+ g_clear_object (&wid->icon_buf);
}
static gint
@@ -229,62 +233,63 @@ destroy_event_widget (GcalWeekHeader *self,
GtkWidget *widget)
{
g_signal_handlers_disconnect_by_func (widget, on_event_widget_activated, self);
- gtk_widget_destroy (widget);
+ gtk_grid_remove (self->grid, widget);
}
/* Auxiliary methods */
-static gboolean
-on_button_pressed (GcalWeekHeader *self,
- GdkEventButton *event,
- GtkWidget *widget)
+static void
+on_button_pressed (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GcalWeekHeader *self)
{
gboolean ltr;
gdouble column_width;
gint column;
gint width;
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
- width = gtk_widget_get_allocated_width (widget);
+ ltr = gtk_widget_get_direction (GTK_WIDGET (self)) != GTK_TEXT_DIR_RTL;
+ width = gtk_widget_get_allocated_width (self->scrolledwindow);
column_width = width / 7.0;
- column = ltr ? (event->x / column_width) : (7 - event->x / column_width);
+ column = ltr ? (x / column_width) : (7 - x / column_width);
self->selection_start = column;
self->selection_end = column;
gtk_widget_queue_draw (GTK_WIDGET (self));
- return GDK_EVENT_PROPAGATE;
+ gtk_event_controller_set_propagation_phase (self->motion_controller,
+ GTK_PHASE_BUBBLE);
}
-static gboolean
-on_motion_notify (GcalWeekHeader *self,
- GdkEventMotion *event,
- GtkWidget *widget)
+static void
+on_motion_notify (GtkEventControllerMotion *motion_event,
+ gdouble x,
+ gdouble y,
+ GcalWeekHeader *self)
{
gboolean ltr;
gdouble column_width;
gint column;
gint width;
- if (!(event->state & GDK_BUTTON_PRESS_MASK))
- return GDK_EVENT_PROPAGATE;
-
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
- width = gtk_widget_get_allocated_width (widget);
+ ltr = gtk_widget_get_direction (GTK_WIDGET (self)) != GTK_TEXT_DIR_RTL;
+ width = gtk_widget_get_allocated_width (self->scrolledwindow);
column_width = width / 7.0;
- column = ltr ? (event->x / column_width) : (7 - event->x / column_width);
+ column = ltr ? (x / column_width) : (7 - x / column_width);
self->selection_end = column;
gtk_widget_queue_draw (GTK_WIDGET (self));
-
- return GDK_EVENT_STOP;
}
-static gboolean
-on_button_released (GcalWeekHeader *self,
- GdkEventButton *event,
- GtkWidget *widget)
+static void
+on_button_released (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GcalWeekHeader *self)
{
g_autoptr (GDateTime) selection_start = NULL;
g_autoptr (GDateTime) selection_end = NULL;
@@ -292,23 +297,23 @@ on_button_released (GcalWeekHeader *self,
GtkWidget *weekview;
gboolean ltr;
gdouble column_width;
- gint out_x, out_y;
+ gdouble out_x, out_y;
gint column;
gint width;
gint start;
gint end;
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
- width = gtk_widget_get_allocated_width (widget);
+ ltr = gtk_widget_get_direction (GTK_WIDGET (self)) != GTK_TEXT_DIR_RTL;
+ width = gtk_widget_get_allocated_width (self->scrolledwindow);
column_width = width / 7.0;
- column = ltr ? (event->x / column_width) : (7 - event->x / column_width);
+ column = ltr ? (x / column_width) : (7 - x / column_width);
self->selection_end = column;
gtk_widget_queue_draw (GTK_WIDGET (self));
/* 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);
+ weekview = gtk_widget_get_ancestor (GTK_WIDGET (self), GCAL_TYPE_WEEK_VIEW);
start = self->selection_start;
end = self->selection_end;
@@ -327,7 +332,7 @@ on_button_released (GcalWeekHeader *self,
out_x = ltr ? (column_width * (column + 0.5)) : (width - column_width * (column + 0.5));
/* Translate X... */
- gtk_widget_translate_coordinates (widget, weekview, out_x, 0, &out_x, NULL);
+ gtk_widget_translate_coordinates (self->scrolledwindow, weekview, out_x, 0, &out_x, NULL);
/* And Y */
gtk_widget_translate_coordinates (GTK_WIDGET (self),
@@ -341,10 +346,11 @@ on_button_released (GcalWeekHeader *self,
"create-event",
selection_start,
selection_end,
- (gdouble) out_x,
- (gdouble) out_y);
+ out_x,
+ out_y);
- return GDK_EVENT_STOP;
+ gtk_event_controller_set_propagation_phase (self->motion_controller,
+ GTK_PHASE_NONE);
}
static void
@@ -464,15 +470,11 @@ update_overflow (GcalWeekHeader *self)
text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "Other event", "Other %d events", n_events -
2), n_events - 2);
- /* Show the button if not visible yet */
- if (!gtk_widget_get_visible (self->expand_button))
- gtk_widget_show (self->expand_button);
-
/* TODO: use a button and show an overflow popover */
if (!label)
{
label = gtk_label_new ("");
- gtk_grid_attach (GTK_GRID (self->grid),
+ gtk_grid_attach (self->grid,
label,
i,
3,
@@ -480,8 +482,6 @@ update_overflow (GcalWeekHeader *self)
1);
self->overflow_label[i] = label;
-
- gtk_widget_show (label);
}
gtk_label_set_label (GTK_LABEL (label), text);
@@ -489,12 +489,12 @@ update_overflow (GcalWeekHeader *self)
}
else if (label)
{
- gtk_widget_destroy (label);
+ gtk_grid_remove (self->grid, label);
self->overflow_label[i] = NULL;
}
}
- gtk_widget_set_visible (self->expand_button, show_expand);
+ gtk_widget_set_visible (GTK_WIDGET (self->expand_button), show_expand);
}
static void
@@ -502,6 +502,8 @@ merge_events (GcalWeekHeader *self,
GtkWidget *event,
GtkWidget *to_be_removed)
{
+ GtkLayoutManager *layout_manager;
+ GtkLayoutChild *layout_child;
GDateTime *end_date;
gint deleted_width, current_width;
@@ -510,23 +512,18 @@ merge_events (GcalWeekHeader *self,
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (event), end_date);
/* Retrieve the current sizes */
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- to_be_removed,
- "width", &deleted_width,
- NULL);
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, to_be_removed);
+ deleted_width = gtk_grid_layout_child_get_column_span (GTK_GRID_LAYOUT_CHILD (layout_child));
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- event,
- "width", ¤t_width,
- NULL);
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, event);
+ current_width = gtk_grid_layout_child_get_column_span (GTK_GRID_LAYOUT_CHILD (layout_child));
destroy_event_widget (self, to_be_removed);
/* Update the event's size */
- gtk_container_child_set (GTK_CONTAINER (self->grid),
- event,
- "width", current_width + deleted_width,
- NULL);
+ gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (layout_child),
+ current_width + deleted_width);
}
static void
@@ -587,8 +584,8 @@ check_mergeable_events (GcalWeekHeader *self)
{
GtkWidget *current_widget, *to_be_removed;
- current_widget = gtk_grid_get_child_at (GTK_GRID (self->grid), weekday + i, index + 1);
- to_be_removed = gtk_grid_get_child_at (GTK_GRID (self->grid), weekday + i + 1, index + 1);
+ current_widget = gtk_grid_get_child_at (self->grid, weekday + i, index + 1);
+ to_be_removed = gtk_grid_get_child_at (self->grid, weekday + i + 1, index + 1);
/*
* We don't want to merge:
@@ -622,6 +619,8 @@ split_event_widget_at_column (GcalWeekHeader *self,
GtkWidget *widget,
gint column)
{
+ GtkLayoutManager *layout_manager;
+ GtkLayoutChild *layout_child;
GDateTime *week_start, *column_date, *end_column_date;
gboolean create_before;
gboolean create_after;
@@ -634,12 +633,11 @@ split_event_widget_at_column (GcalWeekHeader *self,
column_date = g_date_time_add_days (week_start, column);
end_column_date = g_date_time_add_days (column_date, 1);
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- widget,
- "top_attach", &top_attach,
- "left_attach", &left_attach,
- "width", &old_width,
- NULL);
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, widget);
+ top_attach = gtk_grid_layout_child_get_row (GTK_GRID_LAYOUT_CHILD (layout_child));
+ left_attach = gtk_grid_layout_child_get_column (GTK_GRID_LAYOUT_CHILD (layout_child));
+ old_width = gtk_grid_layout_child_get_column_span (GTK_GRID_LAYOUT_CHILD (layout_child));
create_before = column > 0 && left_attach < column;
create_after = column < 6 && old_width > 1 && left_attach + old_width > column + 1;
@@ -653,7 +651,7 @@ split_event_widget_at_column (GcalWeekHeader *self,
setup_event_widget (self, widget_before);
- gtk_grid_attach (GTK_GRID (self->grid),
+ gtk_grid_attach (self->grid,
widget_before,
left_attach,
top_attach,
@@ -667,11 +665,8 @@ split_event_widget_at_column (GcalWeekHeader *self,
left_attach = column;
/* Update the current event position, size and start date */
- gtk_container_child_set (GTK_CONTAINER (self->grid),
- widget,
- "left_attach", left_attach,
- "width", new_width,
- NULL);
+ gtk_grid_layout_child_set_column (GTK_GRID_LAYOUT_CHILD (layout_child), left_attach);
+ gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (layout_child), new_width);
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (widget), column_date);
gtk_widget_set_visible (widget, is_event_visible (self, left_attach, top_attach - 1));
@@ -691,7 +686,7 @@ split_event_widget_at_column (GcalWeekHeader *self,
setup_event_widget (self, widget_after);
- gtk_grid_attach (GTK_GRID (self->grid),
+ gtk_grid_attach (self->grid,
widget_after,
column + 1,
top_attach,
@@ -701,10 +696,7 @@ split_event_widget_at_column (GcalWeekHeader *self,
new_width = column - left_attach + 1;
/* Only update the current widget's width */
- gtk_container_child_set (GTK_CONTAINER (self->grid),
- widget,
- "width", new_width,
- NULL);
+ gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (layout_child), new_width);
gtk_widget_set_visible (widget_after, is_event_visible (self, column + 1, top_attach - 1));
}
@@ -720,42 +712,39 @@ move_events_at_column (GcalWeekHeader *self,
gint column,
gint start_at)
{
- GList *children, *l;
+ GtkLayoutManager *layout_manager;
+ GtkWidget *child;
- children = gtk_container_get_children (GTK_CONTAINER (self->grid));
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
/* First, lets find the widgets at this column */
- for (l = children; l != NULL; l = l->next)
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->grid));
+ child;
+ child = gtk_widget_get_next_sibling (child))
{
gint top_attach, left_attach, width;
+ GtkLayoutChild *layout_child;
/* Get the widget's current position... */
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- l->data,
- "top_attach", &top_attach,
- "left_attach", &left_attach,
- "width", &width,
- NULL);
-
- if (left_attach != column || start_at > top_attach - 1 || !GCAL_IS_EVENT_WIDGET (l->data))
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, child);
+ top_attach = gtk_grid_layout_child_get_row (GTK_GRID_LAYOUT_CHILD (layout_child));
+ left_attach = gtk_grid_layout_child_get_column (GTK_GRID_LAYOUT_CHILD (layout_child));
+ width = gtk_grid_layout_child_get_column_span (GTK_GRID_LAYOUT_CHILD (layout_child));
+
+ if (left_attach != column || start_at > top_attach - 1 || !GCAL_IS_EVENT_WIDGET (child))
continue;
/* If this is a multiday event, break it */
if (width > 1)
- split_event_widget_at_column (self, l->data, column);
+ split_event_widget_at_column (self, child, column);
top_attach = top_attach + (direction == DOWN ? 1 : -1);
/* And move it to position + 1 */
- gtk_container_child_set (GTK_CONTAINER (self->grid),
- l->data,
- "top_attach", top_attach,
- NULL);
+ gtk_grid_layout_child_set_row (GTK_GRID_LAYOUT_CHILD (layout_child), top_attach);
- gtk_widget_set_visible (l->data, is_event_visible (self, left_attach, top_attach - 1));
+ gtk_widget_set_visible (child, is_event_visible (self, left_attach, top_attach - 1));
}
-
- g_clear_pointer (&children, g_list_free);
}
static void
@@ -771,7 +760,7 @@ apply_overflow_at_weekday (GcalWeekHeader *self,
if (self->expanded || self->overflow_label[weekday] || g_list_length (self->events[weekday]) < 4)
return;
- child = gtk_grid_get_child_at (GTK_GRID (self->grid), weekday, 3);
+ child = gtk_grid_get_child_at (self->grid, weekday, 3);
split_event_widget_at_column (self, child, weekday);
gtk_widget_hide (child);
@@ -785,6 +774,7 @@ add_event_to_grid (GcalWeekHeader *self,
{
g_autoptr (GDateTime) week_start = NULL;
g_autoptr (GDateTime) week_end = NULL;
+ GtkLayoutManager *layout_manager;
GtkWidget *widget;
gboolean is_visible, was_visible;
gint position;
@@ -802,7 +792,7 @@ add_event_to_grid (GcalWeekHeader *self,
widget = gcal_event_widget_new (self->context, event);
setup_event_widget (self, widget);
- gtk_grid_attach (GTK_GRID (self->grid),
+ gtk_grid_attach (self->grid,
widget,
start,
position + 1,
@@ -827,6 +817,8 @@ add_event_to_grid (GcalWeekHeader *self,
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (widget), week_start);
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (widget), week_end);
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
+
/*
* In addition to moving the current column's events below, multiday
* events must also move the events from ~all~ the columns it spans
@@ -847,10 +839,11 @@ add_event_to_grid (GcalWeekHeader *self,
/* Add the event to the grid */
if (new_position == position && was_visible == is_visible)
{
- gtk_container_child_set (GTK_CONTAINER (self->grid),
- widget,
- "width", i - start + 1,
- NULL);
+ GtkLayoutChild *layout_child;
+
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, widget);
+ gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (layout_child),
+ i - start + 1);
}
else
{
@@ -861,7 +854,7 @@ add_event_to_grid (GcalWeekHeader *self,
cloned_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (widget));
setup_event_widget (self, cloned_widget);
- gtk_grid_attach (GTK_GRID (self->grid),
+ gtk_grid_attach (self->grid,
cloned_widget,
i,
new_position + 1,
@@ -971,6 +964,8 @@ update_title (GcalWeekHeader *self)
{
GDateTime *week_start, *week_end, *week_mid;
gchar *year_label, *month_label, *week_label;
+ gint today_column;
+ gint i;
if(!self->active_date)
return;
@@ -1007,6 +1002,44 @@ update_title (GcalWeekHeader *self)
gtk_label_set_label (GTK_LABEL (self->week_label), week_label);
gtk_label_set_label (GTK_LABEL (self->year_label), year_label);
+ today_column = get_today_column (self);
+
+ for (i = 0; i < 7; i++)
+ {
+ g_autoptr (GDateTime) day = NULL;
+ g_autofree gchar *weekday_date = NULL;
+ g_autofree gchar *weekday_abv = NULL;
+ g_autofree gchar *weekday = NULL;
+ WeekdayHeader *header;
+ gint n_day;
+
+ day = g_date_time_add_days (week_start, i);
+ n_day = g_date_time_get_day_of_month (day);
+
+ if (n_day > g_date_get_days_in_month (g_date_time_get_month (week_start), g_date_time_get_year
(week_start)))
+ n_day = n_day - g_date_get_days_in_month (g_date_time_get_month (week_start), g_date_time_get_year
(week_start));
+
+ header = &self->weekday_header[i];
+
+ if (i == today_column)
+ {
+ gtk_widget_add_css_class (header->weekday_name_label, "accent");
+ gtk_widget_add_css_class (header->day_number_label, "accent");
+ }
+ else
+ {
+ gtk_widget_remove_css_class (header->weekday_name_label, "accent");
+ gtk_widget_remove_css_class (header->day_number_label, "accent");
+ }
+
+ weekday_date = g_strdup_printf ("%d", n_day);
+ gtk_label_set_label (GTK_LABEL (header->day_number_label), weekday_date);
+
+ weekday = g_date_time_format (day, "%a");
+ weekday_abv = g_utf8_strup (weekday, -1);
+ gtk_label_set_label (GTK_LABEL (header->weekday_name_label), weekday_abv);
+ }
+
g_clear_pointer (&week_start, g_date_time_unref);
g_clear_pointer (&week_end, g_date_time_unref);
g_clear_pointer (&week_mid, g_date_time_unref);
@@ -1018,9 +1051,8 @@ update_title (GcalWeekHeader *self)
static void
header_collapse (GcalWeekHeader *self)
{
- GList *children, *l;
-
- children = gtk_container_get_children (GTK_CONTAINER (self->grid));
+ GtkLayoutManager *layout_manager;
+ GtkWidget *child;
self->expanded = FALSE;
@@ -1028,36 +1060,38 @@ header_collapse (GcalWeekHeader *self)
GTK_POLICY_NEVER,
GTK_POLICY_NEVER);
gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (self->scrolledwindow), -1);
- gtk_image_set_from_icon_name (GTK_IMAGE (self->expand_button_image), "go-down-symbolic", 4);
+ gtk_button_set_icon_name (self->expand_button, "go-down-symbolic");
+
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
- for (l = children; l != NULL; l = l->next)
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->grid));
+ child;
+ child = gtk_widget_get_next_sibling (child))
{
+ GtkLayoutChild *layout_child;
gint top_attach, left_attach;
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- l->data,
- "top-attach", &top_attach,
- "left_attach", &left_attach,
- NULL);
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, child);
+ left_attach = gtk_grid_layout_child_get_column (GTK_GRID_LAYOUT_CHILD (layout_child));
+ top_attach = gtk_grid_layout_child_get_row (GTK_GRID_LAYOUT_CHILD (layout_child));
- gtk_widget_set_visible (l->data, is_event_visible (self, left_attach, top_attach - 1));
+ gtk_widget_set_visible (child, is_event_visible (self, left_attach, top_attach - 1));
apply_overflow_at_weekday (self, left_attach);
}
update_overflow (self);
-
- g_clear_pointer (&children, g_list_free);
}
static void
header_expand (GcalWeekHeader *self)
{
+ GtkLayoutManager *layout_manager;
GtkWidget *week_view;
- GList *children, *l;
+ GtkWidget *child;
- children = gtk_container_get_children (GTK_CONTAINER (self->grid));
week_view = gtk_widget_get_ancestor (GTK_WIDGET (self), GCAL_TYPE_WEEK_VIEW);
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self->grid));
self->expanded = TRUE;
@@ -1069,33 +1103,35 @@ header_expand (GcalWeekHeader *self)
gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (self->scrolledwindow),
gtk_widget_get_allocated_height (week_view) / 2);
- gtk_image_set_from_icon_name (GTK_IMAGE (self->expand_button_image), "go-up-symbolic", 4);
+ gtk_button_set_icon_name (self->expand_button, "go-up-symbolic");
- for (l = children; l != NULL; l = l->next)
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->grid));
+ while (child)
{
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
/* Remove any remaining labels */
- if (GTK_IS_LABEL (l->data))
+ if (GTK_IS_LABEL (child))
{
- gint left_attach;
+ GtkLayoutChild *layout_child;
+ gint column;
- gtk_container_child_get (GTK_CONTAINER (self->grid),
- l->data,
- "left_attach", &left_attach,
- NULL);
+ layout_child = gtk_layout_manager_get_layout_child (layout_manager, child);
+ column = gtk_grid_layout_child_get_column (GTK_GRID_LAYOUT_CHILD (layout_child));
- self->overflow_label[left_attach] = NULL;
- gtk_widget_destroy (l->data);
+ self->overflow_label[column] = NULL;
+ gtk_grid_remove (self->grid, child);
}
else
{
- gtk_widget_show (l->data);
+ gtk_widget_show (child);
}
+
+ child = next;
}
/* Merge events that were broken because of the overflow label */
check_mergeable_events (self);
-
- g_clear_pointer (&children, g_list_free);
}
static void
@@ -1109,105 +1145,26 @@ on_expand_action_activated (GcalWeekHeader *self,
}
/* Drawing area content and size */
-static gdouble
-get_weekday_names_height (GtkWidget *widget)
-{
- PangoFontDescription *font_desc;
- GtkStyleContext* context;
- GtkStateFlags state_flags;
- PangoLayout *layout;
- GtkBorder padding;
- gint final_height;
- gint font_height;
-
- context = gtk_widget_get_style_context (widget);
- state_flags = gtk_style_context_get_state (context);
-
- layout = gtk_widget_create_pango_layout (widget, "A");
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "week-dates");
- gtk_style_context_get (context, state_flags, "font", &font_desc, NULL);
- gtk_style_context_get_padding (context, state_flags, &padding);
-
- pango_layout_set_font_description (layout, font_desc);
- pango_layout_get_pixel_size (layout, NULL, &font_height);
-
- pango_font_description_free (font_desc);
- gtk_style_context_restore (context);
-
- final_height = padding.top + font_height + padding.bottom;
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "week-names");
- gtk_style_context_get (context, state_flags, "font", &font_desc, NULL);
- gtk_style_context_get_padding (context, state_flags, &padding);
-
- pango_layout_set_font_description (layout, font_desc);
- pango_layout_get_pixel_size (layout, NULL, &font_height);
-
- pango_font_description_free (font_desc);
- gtk_style_context_restore (context);
-
- final_height += padding.top + font_height + padding.bottom;
-
- return final_height;
-}
static void
-gcal_week_header_finalize (GObject *object)
-{
- GcalWeekHeader *self = GCAL_WEEK_HEADER (object);
- gint i;
-
- gcal_clear_date_time (&self->active_date);
-
- for (i = 0; i < 7; i++)
- g_list_free (self->events[i]);
-
- for (i = 0; i < G_N_ELEMENTS (self->weather_infos); i++)
- wid_clear (&self->weather_infos[i]);
-
- G_OBJECT_CLASS (gcal_week_header_parent_class)->finalize (object);
-}
-
-static void
-gcal_week_header_size_allocate (GtkWidget *widget,
- GtkAllocation *alloc)
-{
- GcalWeekHeader *self = GCAL_WEEK_HEADER (widget);
- gint min_header_height;
-
- min_header_height = get_weekday_names_height (widget);
-
- gtk_widget_set_margin_top (self->scrolledwindow, min_header_height);
-
- GTK_WIDGET_CLASS (gcal_week_header_parent_class)->size_allocate (widget, alloc);
-}
-
-static gboolean
-gcal_week_header_draw (GtkWidget *widget,
- cairo_t *cr)
+gcal_week_header_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
GtkStyleContext *context;
GcalWeekHeader *self;
GtkStateFlags state;
GdkRGBA color;
GtkAllocation alloc;
- GtkBorder padding;
-
GDateTime *week_start, *week_end;
-
- PangoLayout *layout;
- PangoFontDescription *bold_font;
-
- gdouble cell_width;
- gint i, day_abv_font_height, current_cell, today_column;
- gint start_x, start_y;
-
gboolean ltr;
-
- cairo_save (cr);
+ gdouble cell_width;
+ gint current_cell;
+ gint start_x;
+ gint start_y;
+ gint height;
+ gint width;
+ gint x;
+ gint y;
/* Fonts and colour selection */
self = GCAL_WEEK_HEADER (widget);
@@ -1218,29 +1175,20 @@ gcal_week_header_draw (GtkWidget *widget,
start_x = ltr ? gtk_widget_get_allocated_width (self->expand_button_box) : 0;
start_y = gtk_widget_get_allocated_height (self->header_labels_box);
- gtk_style_context_get_padding (context, state, &padding);
gtk_widget_get_allocation (widget, &alloc);
if (!ltr)
alloc.width -= gtk_widget_get_allocated_width (self->expand_button_box);
- gtk_style_context_get_color (context, state, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- layout = pango_cairo_create_layout (cr);
- gtk_style_context_get (context, state, "font", &bold_font, NULL);
- pango_font_description_set_weight (bold_font, PANGO_WEIGHT_MEDIUM);
- pango_layout_set_font_description (layout, bold_font);
-
week_start = gcal_date_time_get_start_of_week (self->active_date);
week_end = g_date_time_add_days (week_start, 6);
current_cell = g_date_time_get_day_of_week (self->active_date) - 1;
current_cell = (7 + current_cell - self->first_weekday) % 7;
- today_column = get_today_column (self);
cell_width = (alloc.width - start_x) / 7.0;
/* Drag and Drop highlight */
+#if 0 // TODO: DND
if (self->dnd_cell != -1)
{
gtk_drag_highlight (widget);
@@ -1253,6 +1201,7 @@ gcal_week_header_draw (GtkWidget *widget,
gtk_drag_unhighlight (widget);
}
+#endif
/* Draw the selection background */
if (self->selection_start != -1 && self->selection_end != -1)
@@ -1277,216 +1226,45 @@ gcal_week_header_draw (GtkWidget *widget,
selection_width = (end - start + 1) * cell_width;
selection_x = ltr ? (start * cell_width) : (alloc.width - (start * cell_width + selection_width));
- gtk_render_background (context,
- cr,
- ALIGNED (start_x + selection_x) + 0.33,
- start_y - 6,
- ALIGNED (selection_width + 1),
- alloc.height - start_y + 6);
+ gtk_snapshot_render_background (snapshot,
+ context,
+ ALIGNED (start_x + selection_x) + 0.33,
+ start_y - 6,
+ ALIGNED (selection_width + 1),
+ alloc.height - start_y + 6);
- gtk_render_frame (context,
- cr,
- ALIGNED (start_x + selection_x) + 0.33,
- start_y - 6,
- ALIGNED (selection_width + 1),
- alloc.height - start_y + 6);
+ gtk_snapshot_render_frame (snapshot,
+ context,
+ ALIGNED (start_x + selection_x) + 0.33,
+ start_y - 6,
+ ALIGNED (selection_width + 1),
+ alloc.height - start_y + 6);
gtk_style_context_restore (context);
}
- pango_layout_get_pixel_size (layout, NULL, &day_abv_font_height);
-
- for (i = 0; i < 7; i++)
- {
- g_autoptr (GDateTime) day = NULL;
- WeatherInfoDay *wdinfo; /* unowned */
- gchar *weekday_date, *weekday_abv, *weekday;
- gdouble x;
- gint day_num_font_height, day_num_font_baseline;
- gint font_width;
- gint n_day;
-
- day = g_date_time_add_days (week_start, i);
- n_day = g_date_time_get_day_of_month (day);
-
- if (n_day > g_date_get_days_in_month (g_date_time_get_month (week_start), g_date_time_get_year
(week_start)))
- n_day = n_day - g_date_get_days_in_month (g_date_time_get_month (week_start), g_date_time_get_year
(week_start));
-
- /* Draws the date of days in the week */
- weekday_date = g_strdup_printf ("%d", n_day);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "week-dates");
- gtk_style_context_get (context, state, "font", &bold_font, NULL);
-
- if (i == today_column)
- gtk_style_context_add_class (context, "today");
-
- pango_layout_set_font_description (layout, bold_font);
- pango_layout_set_text (layout, weekday_date, -1);
-
- pango_layout_get_pixel_size (layout, &font_width, &day_num_font_height);
- day_num_font_baseline = pango_layout_get_baseline (layout) / PANGO_SCALE;
-
- if (ltr)
- x = padding.left + cell_width * i + COLUMN_PADDING + start_x;
- else
- x = alloc.width - (cell_width * i + font_width + COLUMN_PADDING + start_x);
-
- gtk_render_layout (context,
- cr,
- x,
- day_abv_font_height + padding.bottom + start_y,
- layout);
-
- gtk_style_context_restore (context);
-
- /* Draws the days name */
- weekday = g_date_time_format (day, "%a");
- weekday_abv = g_utf8_strup (weekday, -1);
- g_free (weekday);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "week-names");
- gtk_style_context_get (context, state, "font", &bold_font, NULL);
-
- if (i == today_column)
- gtk_style_context_add_class (context, "today");
-
- pango_layout_set_font_description (layout, bold_font);
- pango_layout_set_text (layout, weekday_abv, -1);
-
- pango_layout_get_pixel_size (layout, &font_width, NULL);
-
- if (ltr)
- x = padding.left + cell_width * i + COLUMN_PADDING + start_x;
- else
- x = alloc.width - (cell_width * i + font_width + COLUMN_PADDING + start_x);
-
- gtk_render_layout (context,
- cr,
- x,
- start_y,
- layout);
-
- gtk_style_context_restore (context);
-
- /* Draws weather icon if given */
- wdinfo = &self->weather_infos[ltr? i : 6 - i];
- if (wdinfo->winfo != NULL)
- {
- const gchar *weather_icon_name = gcal_weather_info_get_icon_name (wdinfo->winfo);
- const gchar *weather_temp = gcal_weather_info_get_temperature (wdinfo->winfo);
-
- /* Imagine a box around weather indicators with length MAX(imgW,tempW)
- * We compute its width and position in this section.
- * Its height is derived from day name and numbers. The icon sticks on
- * the very top and the temperature on its base.
- */
- gint icon_size = day_num_font_height - 3; /* available space - space between temperature and icon
*/
- gint temp_width = 0;
- gint temp_height = 0;
- gint temp_baseline = 0;
-
- gdouble wibox_width;
- gdouble wibox_x;
-
- if (weather_icon_name != NULL && wdinfo->icon_buf == NULL)
- {
- GtkIconTheme *theme; /* unowned */
- g_autoptr (GError) err = NULL;
- gint icon_flags;
-
- theme = gtk_icon_theme_get_default ();
- /* TODO: catch icon theme changes */
-
- icon_flags = ltr? GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_DIR_LTR
- : GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_DIR_RTL;
- wdinfo->icon_buf = gtk_icon_theme_load_icon (theme, weather_icon_name, icon_size, icon_flags,
&err);
- if (err != NULL)
- {
- g_assert (wdinfo->icon_buf == NULL);
- g_warning ("Could not load icon %s: %s", weather_icon_name, err->message);
- }
- }
-
- if (G_LIKELY (weather_temp != NULL))
- {
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "week-temperature");
- gtk_style_context_get (context, state, "font", &bold_font, NULL);
-
- pango_layout_set_font_description (layout, bold_font);
- pango_layout_set_text (layout, weather_temp, -1);
-
- pango_layout_get_pixel_size (layout, &temp_width, &temp_height);
- temp_baseline = pango_layout_get_baseline (layout) / PANGO_SCALE;
- }
-
- wibox_width = MAX(icon_size, temp_width);
- wibox_x = ltr ? alloc.width - (cell_width * (6 - i) + wibox_width + COLUMN_PADDING)
- : padding.left + cell_width * i + COLUMN_PADDING + start_x;
-
- /* Actually draw weather indicator: */
- if (G_LIKELY (weather_temp != NULL))
- {
- gtk_render_layout (context,
- cr,
- wibox_x + (wibox_width - temp_width) / 2,
- day_abv_font_height + padding.bottom + start_y + day_num_font_baseline -
temp_baseline,
- layout);
- gtk_style_context_restore (context);
- }
-
- if (G_LIKELY (wdinfo->icon_buf != NULL))
- {
- gdk_cairo_set_source_pixbuf (cr,
- wdinfo->icon_buf,
- wibox_x + (wibox_width - icon_size) / 2,
- start_y);
- cairo_paint (cr);
- }
- }
-
-
- /* Draws the lines after each day of the week */
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "lines");
-
- gtk_style_context_get_color (context, state, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- cairo_set_line_width (cr, 0.25);
-
- cairo_move_to (cr,
- ALIGNED (ltr ? (cell_width * i + start_x) : (alloc.width - (cell_width * i + start_x))),
- day_abv_font_height + padding.bottom + start_y);
-
- cairo_rel_line_to (cr,
- 0.0,
- gtk_widget_get_allocated_height (widget) - day_abv_font_height - start_y +
padding.bottom);
- cairo_stroke (cr);
+ x = ALIGNED (ltr ? start_x : alloc.width - start_x);
+ y = start_y;
+ width = gtk_widget_get_width (widget) - start_x;
+ height = gtk_widget_get_height (widget) - start_y;
- gtk_style_context_restore (context);
-
- g_free (weekday_date);
- g_free (weekday_abv);
- }
-
- cairo_restore (cr);
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "lines");
+ gtk_style_context_get_color (context, &color);
+ gtk_style_context_restore (context);
- pango_font_description_free (bold_font);
- g_object_unref (layout);
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
+ gcal_week_view_common_snapshot_hour_lines (widget, snapshot, GTK_ORIENTATION_HORIZONTAL, &color, width,
height);
+ gtk_snapshot_restore (snapshot);
- GTK_WIDGET_CLASS (gcal_week_header_parent_class)->draw (widget, cr);
+ GTK_WIDGET_CLASS (gcal_week_header_parent_class)->snapshot (widget, snapshot);
g_clear_pointer (&week_start, g_date_time_unref);
g_clear_pointer (&week_end, g_date_time_unref);
-
- return FALSE;
}
-
+#if 0 // TODO: DND
static gint
get_dnd_cell (GtkWidget *widget,
gint x,
@@ -1633,6 +1411,28 @@ gcal_week_header_drag_leave (GtkWidget *widget,
gtk_widget_queue_draw (widget);
}
+#endif
+
+/*
+ * GObject overrides
+ */
+
+static void
+gcal_week_header_finalize (GObject *object)
+{
+ GcalWeekHeader *self = GCAL_WEEK_HEADER (object);
+ gint i;
+
+ gcal_clear_date_time (&self->active_date);
+
+ for (i = 0; i < 7; i++)
+ g_list_free (self->events[i]);
+
+ for (i = 0; i < G_N_ELEMENTS (self->weather_infos); i++)
+ wid_clear (&self->weather_infos[i]);
+
+ G_OBJECT_CLASS (gcal_week_header_parent_class)->finalize (object);
+}
static void
gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
@@ -1642,11 +1442,7 @@ gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
object_class->finalize = gcal_week_header_finalize;
- widget_class->draw = gcal_week_header_draw;
- widget_class->size_allocate = gcal_week_header_size_allocate;
- widget_class->drag_motion = gcal_week_header_drag_motion;
- widget_class->drag_leave = gcal_week_header_drag_leave;
- widget_class->drag_drop = gcal_week_header_drag_drop;
+ widget_class->snapshot = gcal_week_header_snapshot;
signals[EVENT_ACTIVATED] = g_signal_new ("event-activated",
GCAL_TYPE_WEEK_HEADER,
@@ -1660,13 +1456,14 @@ gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, expand_button);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, expand_button_box);
- gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, expand_button_image);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, grid);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, header_labels_box);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, month_label);
+ gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, motion_controller);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, scrolledwindow);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, sizegroup);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, week_label);
+ gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, weekdays_box);
gtk_widget_class_bind_template_child (widget_class, GcalWeekHeader, year_label);
gtk_widget_class_bind_template_callback (widget_class, on_button_pressed);
@@ -1680,6 +1477,8 @@ gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
static void
gcal_week_header_init (GcalWeekHeader *self)
{
+ gint i;
+
self->expanded = FALSE;
self->selection_start = -1;
self->selection_end = -1;
@@ -1688,17 +1487,42 @@ gcal_week_header_init (GcalWeekHeader *self)
gtk_widget_init_template (GTK_WIDGET (self));
- /* This is to avoid stray lines when adding and removing events */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gtk_container_set_reallocate_redraws (GTK_CONTAINER (self), TRUE);
-G_GNUC_END_IGNORE_DEPRECATIONS
+ for (i = 0; i < 7; i++)
+ {
+ WeekdayHeader *header = &self->weekday_header[i];
+ GtkWidget *box;
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_margin_start (box, 6);
+
+ header->weekday_name_label = gtk_label_new ("");
+ gtk_widget_set_hexpand (header->weekday_name_label, TRUE);
+ gtk_widget_add_css_class (header->weekday_name_label, "heading");
+ gtk_widget_add_css_class (header->weekday_name_label, "dim-label");
+ gtk_label_set_xalign (GTK_LABEL (header->weekday_name_label), 0.0);
+ gtk_box_append (GTK_BOX (box), header->weekday_name_label);
+
+ header->day_number_label = gtk_label_new ("");
+ gtk_widget_set_hexpand (header->day_number_label, TRUE);
+ gtk_widget_add_css_class (header->day_number_label, "title-2");
+ gtk_widget_add_css_class (header->day_number_label, "dim-label");
+ gtk_label_set_xalign (GTK_LABEL (header->day_number_label), 0.0);
+ gtk_box_append (GTK_BOX (box), header->day_number_label);
+
+ gtk_box_append (self->weekdays_box, box);
+
+ /* Add 7 empty widget to the grid to ensure proper spacing */
+ gtk_grid_attach (self->grid, gtk_box_new (GTK_ORIENTATION_VERTICAL, 0), i, 0, 1, 1);
+ }
+#if 0 // TODO: DND
/* Setup the week header as a drag n' drop destination */
gtk_drag_dest_set (GTK_WIDGET (self),
0,
NULL,
0,
GDK_ACTION_MOVE);
+#endif
}
void
@@ -1811,7 +1635,7 @@ gcal_week_header_remove_event (GcalWeekHeader *self,
const gchar *uuid)
{
g_autoptr (GcalEvent) removed_event = NULL;
- GList *children, *l;
+ GtkWidget *child;
gint weekday;
g_return_if_fail (GCAL_IS_WEEK_HEADER (self));
@@ -1821,26 +1645,30 @@ gcal_week_header_remove_event (GcalWeekHeader *self,
if (!removed_event)
return;
- children = gtk_container_get_children (GTK_CONTAINER (self->grid));
-
- for (l = children; l != NULL; l = l->next)
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->grid));
+ while (child)
{
- GcalEventWidget *child_widget;
- GcalEvent *event;
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
- if (!GCAL_IS_EVENT_WIDGET (l->data))
- continue;
+ if (GCAL_IS_EVENT_WIDGET (child))
+ {
+ GcalEventWidget *child_widget;
+ GcalEvent *event;
+
+ child_widget = GCAL_EVENT_WIDGET (child);
+ event = gcal_event_widget_get_event (child_widget);
- child_widget = GCAL_EVENT_WIDGET (l->data);
- event = gcal_event_widget_get_event (child_widget);
+ if (g_strcmp0 (uuid, gcal_event_get_uid (event)) == 0)
+ destroy_event_widget (self, child);
+ }
- if (g_strcmp0 (uuid, gcal_event_get_uid (event)) == 0)
- destroy_event_widget (self, l->data);
+ child = next;
}
/* Remove from the weekday's GList */
for (weekday = 0; weekday < 7; weekday++)
{
+ GList *l;
gint event_position;
l = self->events[weekday];
@@ -1855,7 +1683,6 @@ gcal_week_header_remove_event (GcalWeekHeader *self,
/* Move remaining events up */
move_events_at_column (self, UP, weekday, event_position);
-
}
/* Check if we eventually can merge events */
@@ -1863,8 +1690,6 @@ gcal_week_header_remove_event (GcalWeekHeader *self,
/* And also update the overflow labels */
update_overflow (self);
-
- g_clear_pointer (&children, g_list_free);
}
GList*
@@ -1872,16 +1697,13 @@ gcal_week_header_get_children_by_uuid (GcalWeekHeader *self,
GcalRecurrenceModType mod,
const gchar *uuid)
{
- GList *children, *result;
+ g_autolist (GcalEventWidget) result = NULL;
GCAL_ENTRY;
- children = gtk_container_get_children (GTK_CONTAINER (self->grid));
- result = filter_event_list_by_uid_and_modtype (children, mod, uuid);
-
- g_list_free (children);
+ result = filter_children_by_uid_and_modtype (GTK_WIDGET (self->grid), mod, uuid);
- GCAL_RETURN (result);
+ GCAL_RETURN (g_steal_pointer (&result));
}
GtkSizeGroup*
diff --git a/src/gui/views/gcal-week-header.h b/src/gui/views/gcal-week-header.h
index 5a37940f..5d45b976 100644
--- a/src/gui/views/gcal-week-header.h
+++ b/src/gui/views/gcal-week-header.h
@@ -30,7 +30,7 @@ G_BEGIN_DECLS
#define GCAL_TYPE_WEEK_HEADER (gcal_week_header_get_type())
-G_DECLARE_FINAL_TYPE (GcalWeekHeader, gcal_week_header, GCAL, WEEK_HEADER, GtkGrid)
+G_DECLARE_FINAL_TYPE (GcalWeekHeader, gcal_week_header, GCAL, WEEK_HEADER, GtkBox)
void gcal_week_header_set_context (GcalWeekHeader *self,
GcalContext *context);
diff --git a/src/gui/views/gcal-week-header.ui b/src/gui/views/gcal-week-header.ui
index fbf001f2..262b9619 100644
--- a/src/gui/views/gcal-week-header.ui
+++ b/src/gui/views/gcal-week-header.ui
@@ -1,19 +1,17 @@
<?xml version="1.0"?>
<interface>
- <template class="GcalWeekHeader" parent="GtkGrid">
- <property name="visible">True</property>
+ <template class="GcalWeekHeader" parent="GtkBox">
<property name="hexpand">True</property>
<property name="vexpand">False</property>
+ <property name="orientation">vertical</property>
<style>
<class name="week-header" />
</style>
<child>
<object class="GtkBox" id="header_labels_box">
- <property name="visible">True</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkLabel" id="month_label">
- <property name="visible">True</property>
<property name="label">Month</property>
<property name="yalign">0</property>
<style>
@@ -23,7 +21,6 @@
</child>
<child>
<object class="GtkLabel" id="week_label">
- <property name="visible">True</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
@@ -35,7 +32,6 @@
</child>
<child>
<object class="GtkLabel" id="year_label">
- <property name="visible">True</property>
<property name="label">Year</property>
<property name="yalign">0</property>
<style>
@@ -44,159 +40,82 @@
</object>
</child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
<child>
<object class="GtkBox">
- <property name="visible">True</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkBox" id="expand_button_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="hexpand">False</property>
<child>
<object class="GtkButton" id="expand_button">
- <property name="can_focus">True</property>
+ <property name="visible">False</property>
<property name="hexpand">True</property>
<property name="halign">center</property>
<property name="valign">end</property>
<property name="margin-bottom">6</property>
+ <property name="icon_name">go-down-symbolic</property>
<signal name="clicked" handler="on_expand_action_activated" object="GcalWeekHeader"
swapped="yes"/>
<style>
<class name="flat" />
<class name="circular" />
</style>
- <child>
- <object class="GtkImage" id="expand_button_image">
- <property name="visible">True</property>
- <property name="icon_name">go-down-symbolic</property>
- </object>
- </child>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkEventBox">
- <property name="visible">True</property>
- <signal name="button-press-event" handler="on_button_pressed" object="GcalWeekHeader"
swapped="yes" />
- <signal name="motion-notify-event" handler="on_motion_notify" object="GcalWeekHeader"
swapped="yes" />
- <signal name="button-release-event" handler="on_button_released" object="GcalWeekHeader"
swapped="yes" />
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Gestures -->
+ <child>
+ <object class="GtkGestureClick">
+ <property name="button">1</property>
+ <signal name="pressed" handler="on_button_pressed" object="GcalWeekHeader" swapped="no" />
+ <signal name="released" handler="on_button_released" object="GcalWeekHeader" swapped="no" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkEventControllerMotion" id="motion_controller">
+ <property name="propagation-phase">none</property>
+ <signal name="motion" handler="on_motion_notify" object="GcalWeekHeader" swapped="no" />
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="weekdays_box">
+ <property name="homogeneous">True</property>
+ </object>
+ </child>
+
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
- <property name="visible">True</property>
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="margin-bottom">2</property>
+
<child>
<object class="GtkViewport">
- <property name="visible">True</property>
- <property name="shadow_type">none</property>
<child>
<object class="GtkGrid" id="grid">
- <property name="visible">True</property>
<property name="column-homogeneous">True</property>
<property name="hexpand">True</property>
<property name="column-spacing">6</property>
<property name="row-spacing">2</property>
<property name="margin-start">6</property>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">4</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">5</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">6</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
</object>
</child>
</object>
</child>
+
</object>
</child>
+
</object>
</child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
</child>
</template>
<object class="GtkSizeGroup" id="sizegroup">
diff --git a/src/gui/views/gcal-week-hour-bar.c b/src/gui/views/gcal-week-hour-bar.c
new file mode 100644
index 00000000..037c8ab8
--- /dev/null
+++ b/src/gui/views/gcal-week-hour-bar.c
@@ -0,0 +1,144 @@
+/* gcal-week-hour-bar.c
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "gcal-week-hour-bar.h"
+#include "gcal-week-view-common.h"
+
+#include <glib/gi18n.h>
+
+struct _GcalWeekHourBar
+{
+ GtkBox parent_instance;
+
+ GtkLabel *labels[24];
+
+ GcalContext *context;
+};
+
+G_DEFINE_FINAL_TYPE (GcalWeekHourBar, gcal_week_hour_bar, GTK_TYPE_BOX)
+
+static void
+update_labels (GcalWeekHourBar *self)
+{
+ GcalTimeFormat time_format;
+ gint i;
+
+ time_format = gcal_context_get_time_format (self->context);
+
+ for (i = 0; i < 24; i++)
+ {
+ g_autofree gchar *hours = NULL;
+
+ if (time_format == GCAL_TIME_FORMAT_24H)
+ {
+ hours = g_strdup_printf ("%02d:00", i);
+ }
+ else
+ {
+ hours = g_strdup_printf ("%d %s",
+ i % 12 == 0 ? 12 : i % 12,
+ i >= 12 ? _("PM") : _("AM"));
+ }
+
+ gtk_label_set_label (self->labels[i], hours);
+ }
+}
+
+static void
+gcal_week_hour_bar_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkStyleContext *context;
+ GtkWidget *child;
+ GdkRGBA color;
+
+ context = gtk_widget_get_style_context (widget);
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, "lines");
+ gtk_style_context_get_color (context, &color);
+ gtk_style_context_restore (context);
+
+ gcal_week_view_common_snapshot_hour_lines (widget,
+ snapshot,
+ GTK_ORIENTATION_VERTICAL,
+ &color,
+ gtk_widget_get_width (widget),
+ gtk_widget_get_height (widget));
+
+ for (child = gtk_widget_get_first_child (widget);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ gtk_widget_snapshot_child (widget, child, snapshot);
+ }
+}
+
+static void
+gcal_week_hour_bar_class_init (GcalWeekHourBarClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->snapshot = gcal_week_hour_bar_snapshot;
+
+ gtk_widget_class_set_css_name (widget_class, "weekhourbar");
+}
+
+static void
+gcal_week_hour_bar_init (GcalWeekHourBar *self)
+{
+ gint i;
+
+ g_object_set (self,
+ "orientation", GTK_ORIENTATION_VERTICAL,
+ "homogeneous", TRUE,
+ "spacing", 1,
+ NULL);
+
+
+ for (i = 0; i < 24; i++)
+ {
+ GtkWidget *label = gtk_label_new ("");
+
+ gtk_widget_add_css_class (label, "line");
+ gtk_widget_add_css_class (label, "dim-label");
+ gtk_widget_set_vexpand (label, TRUE);
+ gtk_label_set_yalign (GTK_LABEL (label), 0.20);
+ gtk_box_append (GTK_BOX (self), label);
+
+ self->labels[i] = GTK_LABEL (label);
+ }
+}
+
+void
+gcal_week_hour_bar_set_context (GcalWeekHourBar *self,
+ GcalContext *context)
+{
+ g_return_if_fail (GCAL_IS_WEEK_HOUR_BAR (self));
+
+ self->context = context;
+
+ g_signal_connect_object (context,
+ "notify::time-format",
+ G_CALLBACK (update_labels),
+ self,
+ G_CONNECT_SWAPPED);
+ update_labels (self);
+}
diff --git a/src/gui/views/gcal-week-hour-bar.h b/src/gui/views/gcal-week-hour-bar.h
new file mode 100644
index 00000000..7261287d
--- /dev/null
+++ b/src/gui/views/gcal-week-hour-bar.h
@@ -0,0 +1,35 @@
+/* gcal-week-hour-bar.h
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "gcal-context.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_WEEK_HOUR_BAR (gcal_week_hour_bar_get_type())
+G_DECLARE_FINAL_TYPE (GcalWeekHourBar, gcal_week_hour_bar, GCAL, WEEK_HOUR_BAR, GtkBox)
+
+void gcal_week_hour_bar_set_context (GcalWeekHourBar *self,
+ GcalContext *context);
+
+G_END_DECLS
diff --git a/src/gui/views/gcal-week-view-common.c b/src/gui/views/gcal-week-view-common.c
new file mode 100644
index 00000000..dc7aea94
--- /dev/null
+++ b/src/gui/views/gcal-week-view-common.c
@@ -0,0 +1,87 @@
+/* gcal-week-view-common.c
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "gcal-week-view-common.h"
+#include "gcal-utils.h"
+
+void
+gcal_week_view_common_snapshot_hour_lines (GtkWidget *widget,
+ GtkSnapshot *snapshot,
+ GtkOrientation orientation,
+ const GdkRGBA *line_color,
+ gint width,
+ gint height)
+{
+ GdkRGBA color;
+ gboolean ltr;
+ gdouble column_width;
+ guint i;
+
+ ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
+ color = *line_color;
+
+ column_width = width / 7.0;
+
+ switch (orientation)
+ {
+ case GTK_ORIENTATION_HORIZONTAL:
+ for (i = 0; i < 7; i++)
+ {
+ gdouble x;
+
+ if (ltr)
+ x = column_width * i;
+ else
+ x = width - column_width * i;
+
+ gtk_snapshot_append_color (snapshot,
+ &color,
+ &GRAPHENE_RECT_INIT (x, 0.f, 1.0, height));
+ }
+ break;
+
+
+ case GTK_ORIENTATION_VERTICAL:
+ /* Main lines */
+ for (i = 1; i < 24; i++)
+ {
+ gtk_snapshot_append_color (snapshot,
+ line_color,
+ &GRAPHENE_RECT_INIT (0.f,
+ ALIGNED ((height / 24.0) * i),
+ width,
+ 1.0));
+ }
+
+ /* In-between lines */
+ color.alpha /= 2.0;
+ for (i = 0; i < 24; i++)
+ {
+ gdouble half_cell_height = (height / 24.0) / 2.0;
+ gtk_snapshot_append_color (snapshot,
+ &color,
+ &GRAPHENE_RECT_INIT (0.f,
+ ALIGNED ((height / 24.0) * i + half_cell_height),
+ width,
+ 1.0));
+ }
+ break;
+ }
+}
diff --git a/src/gui/views/gcal-week-view-common.h b/src/gui/views/gcal-week-view-common.h
new file mode 100644
index 00000000..232e7b95
--- /dev/null
+++ b/src/gui/views/gcal-week-view-common.h
@@ -0,0 +1,34 @@
+/* gcal-week-view-common.h
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void gcal_week_view_common_snapshot_hour_lines (GtkWidget *widget,
+ GtkSnapshot *snapshot,
+ GtkOrientation orientation,
+ const GdkRGBA *line_color,
+ gint width,
+ gint height);
+
+G_END_DECLS
diff --git a/src/gui/views/gcal-week-view.c b/src/gui/views/gcal-week-view.c
index 5f8e5452..e68f37ac 100644
--- a/src/gui/views/gcal-week-view.c
+++ b/src/gui/views/gcal-week-view.c
@@ -25,27 +25,21 @@
#include "gcal-utils.h"
#include "gcal-view.h"
#include "gcal-week-header.h"
+#include "gcal-week-hour-bar.h"
#include "gcal-week-grid.h"
#include "gcal-week-view.h"
+#include <adwaita.h>
#include <glib/gi18n.h>
#include <math.h>
-#define ALL_DAY_CELLS_HEIGHT 40
-
-static const double dashed [] =
-{
- 5.0,
- 6.0
-};
-
struct _GcalWeekView
{
GtkBox parent;
GtkWidget *header;
- GtkWidget *hours_bar;
+ GcalWeekHourBar *hours_bar;
GtkWidget *scrolled_window;
GtkWidget *week_grid;
@@ -54,6 +48,7 @@ struct _GcalWeekView
GcalContext *context;
guint scroll_grid_timeout_id;
+ gulong stack_page_changed_id;
gint clicked_cell;
};
@@ -87,16 +82,16 @@ on_event_activated (GcalWeekView *self,
}
static void
-stack_visible_child_changed_cb (GtkStack *stack,
+stack_visible_child_changed_cb (AdwViewStack *stack,
GParamSpec *pspec,
GcalWeekView *self)
{
- if (gtk_stack_get_visible_child (stack) != (GtkWidget*) self)
+ if (adw_view_stack_get_visible_child (stack) != (GtkWidget*) self)
return;
schedule_position_scroll (self);
- g_signal_handlers_disconnect_by_func (stack, stack_visible_child_changed_cb, self);
+ g_clear_signal_handler (&self->stack_page_changed_id, stack);
}
/* Auxiliary methods */
@@ -115,15 +110,16 @@ update_grid_scroll_position (GcalWeekView *self)
if (!gtk_widget_get_realized (self->scrolled_window) ||
!gtk_widget_get_mapped (self->scrolled_window))
{
- GtkWidget *stack;
-
- stack = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_STACK);
+ if (self->stack_page_changed_id == 0)
+ {
+ GtkWidget *stack = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_VIEW_STACK);
- g_signal_connect_object (stack,
- "notify::visible-child",
- G_CALLBACK (stack_visible_child_changed_cb),
- self,
- 0);
+ self->stack_page_changed_id = g_signal_connect_object (stack,
+ "notify::visible-child",
+ G_CALLBACK (stack_visible_child_changed_cb),
+ self,
+ 0);
+ }
self->scroll_grid_timeout_id = 0;
@@ -260,59 +256,6 @@ gcal_view_interface_init (GcalViewInterface *iface)
iface->get_previous_date = gcal_week_view_get_previous_date;
}
-static void
-update_hours_sidebar_size (GcalWeekView *self)
-{
- GtkStyleContext *context;
- GtkStateFlags state;
- GtkSizeGroup *sidebar_sizegroup;
- GtkWidget *widget;
- GtkBorder padding;
-
- PangoLayout *layout;
- PangoFontDescription *font_desc;
-
- gint hours_12_width, hours_24_width, sidebar_width;
- gint hours_12_height, hours_24_height, cell_height;
-
- widget = GTK_WIDGET (self);
- context = gtk_widget_get_style_context (widget);
- state = gtk_style_context_get_state (context);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "hours");
-
- gtk_style_context_get (context, state,
- "font", &font_desc,
- NULL);
- gtk_style_context_get_padding (context, state, &padding);
-
- layout = pango_layout_new (gtk_widget_get_pango_context (widget));
- pango_layout_set_font_description (layout, font_desc);
-
- pango_layout_set_text (layout, _("00 AM"), -1);
- pango_layout_get_pixel_size (layout, &hours_12_width, &hours_12_height);
-
- pango_layout_set_text (layout, _("00:00"), -1);
- pango_layout_get_pixel_size (layout, &hours_24_width, &hours_24_height);
-
- sidebar_width = MAX (hours_12_width, hours_24_width) + padding.left + padding.right;
- cell_height = MAX (hours_12_height, hours_24_height) + padding.top + padding.bottom + 1;
-
- gtk_style_context_restore (context);
-
- /* Update the size requests */
- gtk_widget_set_size_request (self->hours_bar,
- sidebar_width,
- 48 * cell_height);
-
- /* Sync with the week header sidebar */
- sidebar_sizegroup = gcal_week_header_get_sidebar_size_group (GCAL_WEEK_HEADER (self->header));
- gtk_size_group_add_widget (sidebar_sizegroup, self->hours_bar);
-
- pango_font_description_free (font_desc);
- g_object_unref (layout);
-}
/*
* GcalTimelineSubscriber iface
@@ -386,114 +329,10 @@ gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface)
iface->remove_event = gcal_week_view_remove_event;
}
-static gboolean
-gcal_week_view_draw_hours (GcalWeekView *self,
- cairo_t *cr,
- GtkWidget *widget)
-{
- GtkStyleContext *context;
- GcalTimeFormat time_format;
- GtkStateFlags state;
- GtkBorder padding;
- GdkRGBA color;
-
- gboolean ltr;
- gint i, width, height;
- gint font_width;
-
- PangoLayout *layout;
- PangoFontDescription *font_desc;
-
- time_format = gcal_context_get_time_format (self->context);
- context = gtk_widget_get_style_context (widget);
- state = gtk_widget_get_state_flags (widget);
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "hours");
- gtk_style_context_get_color (context, state, &color);
- gtk_style_context_get_padding (context, state, &padding);
- gtk_style_context_get (context, state, "font", &font_desc, NULL);
-
- layout = pango_cairo_create_layout (cr);
- pango_layout_set_font_description (layout, font_desc);
- gdk_cairo_set_source_rgba (cr, &color);
-
- /* Gets the size of the widget */
- width = gtk_widget_get_allocated_width (widget);
- height = gtk_widget_get_allocated_height (widget);
-
- /* Draws the hours in the sidebar */
- for (i = 0; i < 24; i++)
- {
- gchar *hours;
-
- if (time_format == GCAL_TIME_FORMAT_24H)
- {
- hours = g_strdup_printf ("%02d:00", i);
- }
- else
- {
- hours = g_strdup_printf ("%d %s",
- i % 12 == 0 ? 12 : i % 12,
- i >= 12 ? _("PM") : _("AM"));
- }
-
- pango_layout_set_text (layout, hours, -1);
- pango_layout_get_pixel_size (layout, &font_width, NULL);
-
- gtk_render_layout (context,
- cr,
- ltr ? padding.left : width - font_width - padding.right,
- (height / 24) * i + padding.top,
- layout);
-
- g_free (hours);
- }
-
- gtk_style_context_restore (context);
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "lines");
- gtk_style_context_get_color (context, state, &color);
-
- gdk_cairo_set_source_rgba (cr, &color);
- cairo_set_line_width (cr, 0.65);
-
- if (!ltr)
- {
- cairo_move_to (cr, 0.5, 0);
- cairo_rel_line_to (cr, 0, height);
- }
-
- /* Draws the horizontal complete lines */
- for (i = 1; i < 24; i++)
- {
- cairo_move_to (cr, 0, (height / 24) * i + 0.4);
- cairo_rel_line_to (cr, width, 0);
- }
-
- cairo_stroke (cr);
-
- cairo_set_dash (cr, dashed, 2, 0);
-
- /* Draws the horizontal dashed lines */
- for (i = 0; i < 24; i++)
- {
- cairo_move_to (cr, 0, (height / 24) * i + (height / 48) + 0.4);
- cairo_rel_line_to (cr, width, 0);
- }
-
- cairo_stroke (cr);
-
- gtk_style_context_restore (context);
-
- pango_font_description_free (font_desc);
- g_object_unref (layout);
-
- return FALSE;
-}
+/*
+ * GObject overrides
+ */
static void
gcal_week_view_finalize (GObject *object)
@@ -530,12 +369,7 @@ gcal_week_view_set_property (GObject *object,
gcal_week_grid_set_context (GCAL_WEEK_GRID (self->week_grid), self->context);
gcal_week_header_set_context (GCAL_WEEK_HEADER (self->header), self->context);
-
- g_signal_connect_object (self->context,
- "notify::time-format",
- G_CALLBACK (gtk_widget_queue_draw),
- self->hours_bar,
- G_CONNECT_SWAPPED);
+ gcal_week_hour_bar_set_context (self->hours_bar, self->context);
break;
default:
@@ -579,6 +413,7 @@ gcal_week_view_class_init (GcalWeekViewClass *klass)
g_type_ensure (GCAL_TYPE_WEEK_GRID);
g_type_ensure (GCAL_TYPE_WEEK_HEADER);
+ g_type_ensure (GCAL_TYPE_WEEK_HOUR_BAR);
object_class->finalize = gcal_week_view_finalize;
object_class->set_property = gcal_week_view_set_property;
@@ -594,7 +429,6 @@ gcal_week_view_class_init (GcalWeekViewClass *klass)
gtk_widget_class_bind_template_child (widget_class, GcalWeekView, scrolled_window);
gtk_widget_class_bind_template_child (widget_class, GcalWeekView, week_grid);
- gtk_widget_class_bind_template_callback (widget_class, gcal_week_view_draw_hours);
gtk_widget_class_bind_template_callback (widget_class, on_event_activated);
gtk_widget_class_set_css_name (widget_class, "calendar-view");
@@ -603,8 +437,11 @@ gcal_week_view_class_init (GcalWeekViewClass *klass)
static void
gcal_week_view_init (GcalWeekView *self)
{
+ GtkSizeGroup *size_group;
+
gtk_widget_init_template (GTK_WIDGET (self));
- update_hours_sidebar_size (self);
+ size_group = gcal_week_header_get_sidebar_size_group (GCAL_WEEK_HEADER (self->header));
+ gtk_size_group_add_widget (size_group, GTK_WIDGET (self->hours_bar));
}
diff --git a/src/gui/views/gcal-week-view.ui b/src/gui/views/gcal-week-view.ui
index 7540bcb8..8ac99f73 100644
--- a/src/gui/views/gcal-week-view.ui
+++ b/src/gui/views/gcal-week-view.ui
@@ -1,39 +1,31 @@
<?xml version="1.0"?>
<interface>
<template class="GcalWeekView" parent="GtkBox">
- <property name="visible">True</property>
<property name="orientation">vertical</property>
<style>
<class name="week-view" />
</style>
<child>
<object class="GcalWeekHeader" id="header">
- <property name="visible">True</property>
<signal name="event-activated" handler="on_event_activated" object="GcalWeekView" swapped="yes" />
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled_window">
- <property name="visible">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkViewport">
- <property name="visible">True</property>
<child>
<object class="GtkBox">
- <property name="visible">True</property>
<property name="orientation">horizontal</property>
<child>
- <object class="GtkDrawingArea" id="hours_bar">
- <property name="visible">True</property>
+ <object class="GcalWeekHourBar" id="hours_bar">
<property name="height-request">2568</property>
- <signal name="draw" handler="gcal_week_view_draw_hours" object="GcalWeekView"
swapped="yes" />
</object>
</child>
<child>
<object class="GcalWeekGrid" id="week_grid">
- <property name="visible">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<signal name="event-activated" handler="on_event_activated" object="GcalWeekView"
swapped="yes" />
diff --git a/src/gui/views/meson.build b/src/gui/views/meson.build
index 96c5a037..2306458b 100644
--- a/src/gui/views/meson.build
+++ b/src/gui/views/meson.build
@@ -13,6 +13,8 @@ sources += files(
'gcal-view.c',
'gcal-week-grid.c',
'gcal-week-header.c',
+ 'gcal-week-hour-bar.c',
'gcal-week-view.c',
+ 'gcal-week-view-common.c',
'gcal-year-view.c',
)
diff --git a/src/theme/Adwaita.css b/src/theme/Adwaita.css
index c757f458..fc1872af 100644
--- a/src/theme/Adwaita.css
+++ b/src/theme/Adwaita.css
@@ -386,18 +386,12 @@ label.month-name {
color: alpha(@theme_fg_color, 0.25);
}
-.week-header.week-names, .week-header.week-temperature {
+.week-header.week-temperature {
font-size: 10pt;
font-weight: bold;
color: alpha(@theme_fg_color, 0.55);
}
-.week-header.week-dates {
- font-size: 16pt;
- font-weight: bold;
- color: alpha(@theme_fg_color, 0.70);
-}
-
.week-header.lines {
color: alpha(@theme_fg_color, 0.4);
}
@@ -406,37 +400,24 @@ label.month-name {
color: alpha(@theme_fg_color, 0.6);
}
-.week-header .today {
- color: @theme_selected_bg_color;
-}
-
-.week-view {
- padding: 0px;
-}
-
-.week-view .hours {
+weekhourbar > label {
font-size: 10pt;
- color: alpha(@theme_fg_color, 0.8);
- padding: 8px 12px;
+ padding: 4px 6px;
}
.week-view .lines {
- color: alpha(@theme_fg_color, 0.30);
+ color: alpha(@window_fg_color, 0.30);
}
-weekgrid.now-strip {
- background-color: alpha(@theme_selected_bg_color, 0.8);
+weekgrid > widget.now-strip {
+ background-color: alpha(@accent_bg_color, 0.8);
margin: 0 0 0 1px;
min-height: 2px;
}
weekgrid:selected,
.week-header:selected {
- background-color: alpha(@theme_selected_bg_color, 0.25);
-}
-
-.week-header:selected {
- border: solid 1px alpha(@theme_selected_bg_color, 0.8);
+ background-color: alpha(@accent_bg_color, 0.25);
}
diff --git a/src/utils/gcal-utils.c b/src/utils/gcal-utils.c
index e3b0d6d1..c15da2e4 100644
--- a/src/utils/gcal-utils.c
+++ b/src/utils/gcal-utils.c
@@ -1112,29 +1112,30 @@ is_workday (guint day)
}
GList*
-filter_event_list_by_uid_and_modtype (GList *widgets,
- GcalRecurrenceModType mod,
- const gchar *uid)
+filter_children_by_uid_and_modtype (GtkWidget *widget,
+ GcalRecurrenceModType mod,
+ const gchar *uid)
{
+ GtkWidget *child;
GcalEvent *event;
GList *result;
- GList *l;
event = NULL;
result = NULL;
/* First pass: find the GcalEvent */
- for (l = widgets; l != NULL; l = l->next)
+ for (child = gtk_widget_get_first_child (widget);
+ child;
+ child = gtk_widget_get_next_sibling (child))
{
GcalEventWidget *event_widget;
GcalEvent *ev;
- event_widget = l->data;
-
/* Safeguard against stray widgets */
- if (!GCAL_IS_EVENT_WIDGET (event_widget))
+ if (!GCAL_IS_EVENT_WIDGET (child))
continue;
+ event_widget = GCAL_EVENT_WIDGET (child);
ev = gcal_event_widget_get_event (event_widget);
/*
@@ -1161,17 +1162,18 @@ filter_event_list_by_uid_and_modtype (GList *widgets,
id = e_cal_component_get_id (component);
id_prefix = g_strdup_printf ("%s:%s", gcal_calendar_get_id (calendar), e_cal_component_id_get_uid
(id));
- for (l = widgets; l != NULL; l = l->next)
+ for (child = gtk_widget_get_first_child (widget);
+ child;
+ child = gtk_widget_get_next_sibling (child))
{
GcalEventWidget *event_widget;
GcalEvent *ev;
- event_widget = l->data;
-
/* Safeguard against stray widgets */
- if (!GCAL_IS_EVENT_WIDGET (event_widget))
+ if (!GCAL_IS_EVENT_WIDGET (child))
continue;
+ event_widget = GCAL_EVENT_WIDGET (child);
ev = gcal_event_widget_get_event (event_widget);
if (g_str_equal (gcal_event_get_uid (ev), uid))
diff --git a/src/utils/gcal-utils.h b/src/utils/gcal-utils.h
index d93040cf..bc0eb3b6 100644
--- a/src/utils/gcal-utils.h
+++ b/src/utils/gcal-utils.h
@@ -116,7 +116,7 @@ gboolean ask_recurrence_modification_type (GtkWidget
gboolean is_workday (guint day);
-GList* filter_event_list_by_uid_and_modtype (GList *widgets,
+GList* filter_children_by_uid_and_modtype (GtkWidget *widget,
GcalRecurrenceModType mod,
const gchar *uid);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]