views/month: Show overflow popover when requested

Basically, all that we used to do, but written in a different
way for the new month view.
This commit is contained in:
Georges Basile Stavracas Neto
2023-08-11 15:13:44 -03:00
parent 15032b6d05
commit 176f8f28a8
+142
View File
@@ -24,6 +24,8 @@
#include "config.h"
#include "gcal-context.h"
#include "gcal-debug.h"
#include "gcal-month-cell.h"
#include "gcal-month-popover.h"
#include "gcal-month-view.h"
#include "gcal-month-view-row.h"
#include "gcal-range-tree.h"
@@ -53,6 +55,12 @@ struct _GcalMonthView
GPtrArray *week_rows;
GHashTable *events;
struct {
GtkWidget *popover;
GcalMonthViewRow *row;
GtkWidget *relative_to;
} overflow;
/* Ranges from [0.0, 1.0] */
gdouble row_offset;
AdwAnimation *row_offset_animation;
@@ -89,6 +97,78 @@ enum
* Auxiliary methods
*/
static void
allocate_overflow_popover (GcalMonthView *self,
gint width,
gint height,
gint baseline)
{
graphene_point_t origin, end;
GtkAllocation popover_allocation;
GtkAllocation allocation;
gint popover_min_width;
gint popover_nat_width;
gint popover_height;
gint popover_width;
gint header_height;
g_assert (self->overflow.relative_to != NULL);
header_height = gtk_widget_get_height (self->header);
if (!gtk_widget_compute_point (self->overflow.relative_to,
GTK_WIDGET (self),
&GRAPHENE_POINT_INIT (0, 0),
&origin))
g_assert_not_reached ();
if (!gtk_widget_compute_point (self->overflow.relative_to,
GTK_WIDGET (self),
&GRAPHENE_POINT_INIT (gtk_widget_get_width (self->overflow.relative_to),
gtk_widget_get_height (self->overflow.relative_to)),
&end))
g_assert_not_reached ();
allocation = (GtkAllocation) {
.x = origin.x,
.y = origin.y,
.width = end.x - origin.x,
.height = end.y - origin.y,
};
gtk_widget_measure (GTK_WIDGET (self->overflow.popover),
GTK_ORIENTATION_HORIZONTAL,
-1,
&popover_min_width,
&popover_nat_width,
NULL, NULL);
gtk_widget_measure (GTK_WIDGET (self->overflow.popover),
GTK_ORIENTATION_VERTICAL,
-1,
NULL,
&popover_height,
NULL, NULL);
popover_width = CLAMP (popover_nat_width, popover_min_width, allocation.width * 1.5);
popover_height = CLAMP (popover_height, allocation.height * 1.5, height);
popover_allocation = (GtkAllocation) {
.x = MAX (0, allocation.x - (popover_width - allocation.width) / 2.0),
.y = MAX (header_height, allocation.y - (popover_height - allocation.height) / 2.0),
.width = popover_width,
.height = popover_height,
};
if (popover_allocation.x + popover_allocation.width > width)
popover_allocation.x -= (popover_allocation.x + popover_allocation.width - width);
if (popover_allocation.y + popover_allocation.height > height)
popover_allocation.y -= (popover_allocation.y + popover_allocation.height - height);
gtk_widget_size_allocate (self->overflow.popover, &popover_allocation, baseline);
}
static void
update_header_labels (GcalMonthView *self)
{
@@ -171,6 +251,22 @@ add_cached_events_to_row (GcalMonthView *self,
}
}
static inline void
maybe_popdown_overflow_popover (GcalMonthView *self)
{
uint32_t row_index;
gboolean found;
if (!self->overflow.row)
return;
found = g_ptr_array_find (self->week_rows, self->overflow.row, &row_index);
g_assert (found);
if (floor (row_index / (gdouble) N_ROWS_PER_PAGE) != floor (N_PAGES / 2.0))
gcal_month_popover_popdown (GCAL_MONTH_POPOVER (self->overflow.popover));
}
static void
move_bottom_row_to_top (GcalMonthView *self)
{
@@ -320,6 +416,7 @@ update_week_ranges (GcalMonthView *self,
}
}
maybe_popdown_overflow_popover (self);
dump_row_ranges (self);
}
@@ -397,6 +494,7 @@ offset_and_shuffle_rows (GcalMonthView *self,
self->row_offset = fmod (self->row_offset, 0.5) + 0.5;
}
maybe_popdown_overflow_popover (self);
update_active_date (self);
dump_row_ranges (self);
}
@@ -539,6 +637,7 @@ on_discrete_scroll_controller_scroll_cb (GtkEventControllerScroll *scroll_contro
}
gtk_widget_remove_css_class (GTK_WIDGET (self), "scrolling");
maybe_popdown_overflow_popover (self);
cancel_row_offset_animation (self);
cancel_deceleration (self);
update_active_date (self);
@@ -642,6 +741,34 @@ on_scroll_controller_decelerate_cb (GtkEventControllerScroll *scroll_controller,
GCAL_EXIT;
}
static void
on_month_row_show_overflow_cb (GcalMonthViewRow *row,
GcalMonthCell *cell,
GcalMonthView *self)
{
GcalMonthPopover *popover;
GCAL_ENTRY;
popover = GCAL_MONTH_POPOVER (self->overflow.popover);
self->overflow.row = row;
self->overflow.relative_to = GTK_WIDGET (cell);
gcal_month_popover_set_date (popover, gcal_month_cell_get_date (cell));
gcal_month_popover_popup (popover);
GCAL_EXIT;
}
static void
on_month_popover_event_activated_cb (GcalMonthPopover *month_popover,
GcalEventWidget *event_widget,
GcalMonthViewRow *self)
{
gcal_view_event_activated (GCAL_VIEW (self), event_widget);
}
/*
* GcalTimelineSubscriber iface
@@ -1007,6 +1134,10 @@ gcal_month_view_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (row, &row_allocation, baseline);
}
/* Overflow popover */
if (gtk_widget_should_layout (self->overflow.popover))
allocate_overflow_popover (self, width, height, baseline);
}
static void
@@ -1034,6 +1165,9 @@ gcal_month_view_snapshot (GtkWidget *widget,
/* Snapshot header */
gtk_widget_snapshot_child (widget, self->header, snapshot);
/* Overflow popover */
gtk_widget_snapshot_child (widget, self->overflow.popover, snapshot);
}
@@ -1179,12 +1313,20 @@ gcal_month_view_init (GcalMonthView *self)
{
GtkWidget *row = gcal_month_view_row_new ();
g_signal_connect (row, "event-activated", G_CALLBACK (on_event_widget_activated_cb), self);
g_signal_connect (row, "show-overflow", G_CALLBACK (on_month_row_show_overflow_cb), self);
gtk_widget_set_parent (row, GTK_WIDGET (self));
g_ptr_array_add (self->week_rows, row);
}
gtk_widget_insert_after (self->header, GTK_WIDGET (self), NULL);
/* Overflow popover */
self->overflow.popover = gcal_month_popover_new ();
g_object_bind_property (self, "context", self->overflow.popover, "context", G_BINDING_DEFAULT);
g_signal_connect (self->overflow.popover, "event-activated", G_CALLBACK (on_month_popover_event_activated_cb), self);
gtk_widget_set_parent (self->overflow.popover, GTK_WIDGET (self));
now = g_date_time_new_now_local ();
gcal_view_set_date (GCAL_VIEW (self), now);
}