views/week: Store and restore zoom level

Closes https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/916
This commit is contained in:
Georges Basile Stavracas Neto
2023-03-16 12:26:28 +00:00
parent a9e4a5ae12
commit 189c809271
3 changed files with 206 additions and 152 deletions
+5
View File
@@ -21,5 +21,10 @@
<summary>Weather Service Configuration</summary>
<description>Whether weather reports are shown, automatic locations are used and a location-name</description>
</key>
<key name="week-view-zoom-level" type="d">
<default>1.0</default>
<summary>Zoom level of the week grid</summary>
<description>The current zoom level of the week grid</description>
</key>
</schema>
</schemalist>
+199 -152
View File
@@ -63,7 +63,9 @@ struct _GcalWeekView
gdouble zoom_level;
};
static void schedule_position_scroll (GcalWeekView *self);
static void stack_visible_child_changed_cb (AdwViewStack *stack,
GParamSpec *pspec,
GcalWeekView *self);
static void gcal_view_interface_init (GcalViewInterface *iface);
@@ -89,157 +91,6 @@ G_DEFINE_TYPE_WITH_CODE (GcalWeekView, gcal_week_view, GTK_TYPE_BOX,
#define MIN_ZOOM_LEVEL 0.334
#define MAX_ZOOM_LEVEL 3.0
/* Callbacks */
static void
on_event_activated (GcalWeekView *self,
GtkWidget *widget)
{
gcal_view_event_activated (GCAL_VIEW (self), GCAL_EVENT_WIDGET (widget));
}
static void
begin_zoom (GcalWeekView *self,
gdouble view_center_y)
{
GtkAdjustment *vadjustment;
gdouble center, height;
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolled_window));
center = gtk_adjustment_get_value (vadjustment) + view_center_y - gtk_adjustment_get_lower (vadjustment);
height = gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_lower (vadjustment);
self->gesture_zoom_center = center / height;
self->initial_zoom_level = self->zoom_level;
}
static void
apply_zoom (GcalWeekView *self,
gdouble view_center_y,
gdouble scale)
{
GtkAdjustment *vadjustment;
gdouble height;
self->zoom_level = CLAMP (self->initial_zoom_level + (scale - 1.0),
MIN_ZOOM_LEVEL,
MAX_ZOOM_LEVEL);
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolled_window));
height = HEIGHT_DEFAULT * self->zoom_level;
gtk_widget_set_size_request (self->content, -1, height);
gtk_adjustment_set_lower (vadjustment, 0);
gtk_adjustment_set_upper (vadjustment, height);
gtk_adjustment_set_value (vadjustment, (self->gesture_zoom_center * height) - view_center_y);
}
static void
on_motion_controller_enter_cb (GcalWeekView *self,
gdouble x,
gdouble y,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = TRUE;
self->pointer_position_y = y;
}
static void
on_motion_controller_motion_cb (GcalWeekView *self,
gdouble x,
gdouble y,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = TRUE;
self->pointer_position_y = y;
}
static void
on_motion_controller_leave_cb (GcalWeekView *self,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = FALSE;
}
static void
on_scroll_controller_scroll_begin_cb (GcalWeekView *self,
GtkEventControllerScroll *controller)
{
gdouble view_center_y;
self->scroll_scale = 1.0;
if (self->pointer_position_valid)
view_center_y = self->pointer_position_y;
else
view_center_y = gtk_widget_get_allocated_height (self->scrolled_window) / 2.0;
begin_zoom (self, view_center_y);
}
static gboolean
on_scroll_controller_scroll_cb (GcalWeekView *self,
gdouble dx,
gdouble dy,
GtkEventControllerScroll *controller)
{
gdouble scale, view_center_y;
if (!(gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (controller)) & GDK_CONTROL_MASK))
return FALSE;
scale = dy / 100.0 + self->scroll_scale;
if (self->pointer_position_valid)
view_center_y = self->pointer_position_y;
else
view_center_y = gtk_widget_get_allocated_height (self->scrolled_window) / 2.0;
begin_zoom (self, view_center_y);
apply_zoom (self, view_center_y, scale);
return TRUE;
}
static void
on_zoom_gesture_scale_changed_cb (GcalWeekView *self,
gdouble scale,
GtkGestureZoom *gesture)
{
gdouble view_center_x, view_center_y;
gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture), &view_center_x, &view_center_y);
apply_zoom (self, view_center_y, scale);
}
static void
on_zoom_gesture_begin_cb (GcalWeekView *self,
GdkEventSequence *sequence,
GtkGesture *gesture)
{
gdouble view_center_x, view_center_y;
gtk_gesture_get_bounding_box_center (gesture, &view_center_x, &view_center_y);
begin_zoom (self, view_center_y);
}
static void
stack_visible_child_changed_cb (AdwViewStack *stack,
GParamSpec *pspec,
GcalWeekView *self)
{
if (adw_view_stack_get_visible_child (stack) != (GtkWidget*) self)
return;
schedule_position_scroll (self);
g_clear_signal_handler (&self->stack_page_changed_id, stack);
}
/* Auxiliary methods */
static gboolean
update_grid_scroll_position (GcalWeekView *self)
@@ -316,6 +167,199 @@ schedule_position_scroll (GcalWeekView *self)
self);
}
static void
begin_zoom (GcalWeekView *self,
gdouble view_center_y)
{
GtkAdjustment *vadjustment;
gdouble center, height;
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolled_window));
center = gtk_adjustment_get_value (vadjustment) + view_center_y - gtk_adjustment_get_lower (vadjustment);
height = gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_lower (vadjustment);
self->gesture_zoom_center = center / height;
self->initial_zoom_level = self->zoom_level;
}
static void
apply_zoom (GcalWeekView *self,
gdouble view_center_y,
gdouble scale)
{
GtkAdjustment *vadjustment;
gdouble height;
self->zoom_level = CLAMP (self->initial_zoom_level + (scale - 1.0),
MIN_ZOOM_LEVEL,
MAX_ZOOM_LEVEL);
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolled_window));
height = HEIGHT_DEFAULT * self->zoom_level;
gtk_widget_set_size_request (self->content, -1, height);
gtk_adjustment_set_lower (vadjustment, 0);
gtk_adjustment_set_upper (vadjustment, height);
gtk_adjustment_set_value (vadjustment, (self->gesture_zoom_center * height) - view_center_y);
}
static void
save_zoom_level (GcalWeekView *self)
{
GSettings *settings;
g_assert (self->context != NULL);
settings = gcal_context_get_settings (self->context);
g_settings_set_double (settings, "week-view-zoom-level", self->zoom_level);
}
static void
restore_zoom_level (GcalWeekView *self)
{
GSettings *settings;
g_assert (self->context != NULL);
settings = gcal_context_get_settings (self->context);
self->zoom_level = g_settings_get_double (settings, "week-view-zoom-level");
begin_zoom (self, 0);
apply_zoom (self, 0, 1.0);
}
/* Callbacks */
static void
on_event_activated (GcalWeekView *self,
GtkWidget *widget)
{
gcal_view_event_activated (GCAL_VIEW (self), GCAL_EVENT_WIDGET (widget));
}
static void
on_motion_controller_enter_cb (GcalWeekView *self,
gdouble x,
gdouble y,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = TRUE;
self->pointer_position_y = y;
}
static void
on_motion_controller_motion_cb (GcalWeekView *self,
gdouble x,
gdouble y,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = TRUE;
self->pointer_position_y = y;
}
static void
on_motion_controller_leave_cb (GcalWeekView *self,
GtkEventControllerMotion *controller)
{
self->pointer_position_valid = FALSE;
}
static void
on_scroll_controller_scroll_begin_cb (GcalWeekView *self,
GtkEventControllerScroll *controller)
{
gdouble view_center_y;
self->scroll_scale = 1.0;
if (self->pointer_position_valid)
view_center_y = self->pointer_position_y;
else
view_center_y = gtk_widget_get_allocated_height (self->scrolled_window) / 2.0;
begin_zoom (self, view_center_y);
}
static gboolean
on_scroll_controller_scroll_cb (GcalWeekView *self,
gdouble dx,
gdouble dy,
GtkEventControllerScroll *controller)
{
gdouble scale, view_center_y;
if (!(gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (controller)) & GDK_CONTROL_MASK))
return FALSE;
scale = dy / 100.0 + self->scroll_scale;
if (self->pointer_position_valid)
view_center_y = self->pointer_position_y;
else
view_center_y = gtk_widget_get_allocated_height (self->scrolled_window) / 2.0;
begin_zoom (self, view_center_y);
apply_zoom (self, view_center_y, scale);
return TRUE;
}
static void
on_scroll_controller_scroll_end_cb (GtkEventControllerScroll *controller,
GcalWeekView *self)
{
save_zoom_level (self);
}
static void
on_zoom_gesture_scale_changed_cb (GcalWeekView *self,
gdouble scale,
GtkGestureZoom *gesture)
{
gdouble view_center_x, view_center_y;
gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture), &view_center_x, &view_center_y);
apply_zoom (self, view_center_y, scale);
}
static void
on_zoom_gesture_begin_cb (GcalWeekView *self,
GdkEventSequence *sequence,
GtkGesture *gesture)
{
gdouble view_center_x, view_center_y;
gtk_gesture_get_bounding_box_center (gesture, &view_center_x, &view_center_y);
begin_zoom (self, view_center_y);
}
static void
on_zoom_gesture_end_cb (GtkGesture *gesture,
GdkEventSequence *sequence,
GcalWeekView *self)
{
save_zoom_level (self);
}
static void
stack_visible_child_changed_cb (AdwViewStack *stack,
GParamSpec *pspec,
GcalWeekView *self)
{
if (adw_view_stack_get_visible_child (stack) != (GtkWidget*) self)
return;
schedule_position_scroll (self);
g_clear_signal_handler (&self->stack_page_changed_id, stack);
}
/* GcalView implementation */
static GDateTime*
gcal_week_view_get_date (GcalView *view)
@@ -516,6 +560,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);
gcal_week_hour_bar_set_context (self->hours_bar, self->context);
restore_zoom_level (self);
break;
default:
@@ -582,8 +627,10 @@ gcal_week_view_class_init (GcalWeekViewClass *klass)
gtk_widget_class_bind_template_callback (widget_class, on_motion_controller_leave_cb);
gtk_widget_class_bind_template_callback (widget_class, on_scroll_controller_scroll_begin_cb);
gtk_widget_class_bind_template_callback (widget_class, on_scroll_controller_scroll_cb);
gtk_widget_class_bind_template_callback (widget_class, on_scroll_controller_scroll_end_cb);
gtk_widget_class_bind_template_callback (widget_class, on_zoom_gesture_scale_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_zoom_gesture_begin_cb);
gtk_widget_class_bind_template_callback (widget_class, on_zoom_gesture_end_cb);
gtk_widget_class_set_css_name (widget_class, "calendar-view");
}
+2
View File
@@ -20,6 +20,7 @@
<object class="GtkGestureZoom">
<signal name="scale-changed" handler="on_zoom_gesture_scale_changed_cb" object="GcalWeekView" swapped="yes" />
<signal name="begin" handler="on_zoom_gesture_begin_cb" object="GcalWeekView" swapped="yes" />
<signal name="end" handler="on_zoom_gesture_end_cb" object="GcalWeekView" swapped="no" />
</object>
</child>
@@ -30,6 +31,7 @@
<property name="flags">vertical|kinetic</property>
<signal name="scroll-begin" handler="on_scroll_controller_scroll_begin_cb" object="GcalWeekView" swapped="yes" />
<signal name="scroll" handler="on_scroll_controller_scroll_cb" object="GcalWeekView" swapped="yes" />
<signal name="scroll-end" handler="on_scroll_controller_scroll_end_cb" object="GcalWeekView" swapped="no" />
</object>
</child>