/* bz-progress-bar.c * * Copyright 2025 Adam Masciola * * 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-progress-bar.h" struct _BzProgressBar { AdwBin parent_instance; double fraction; AdwAnimation *animation; /* Template widgets */ GtkProgressBar *bar; }; G_DEFINE_FINAL_TYPE (BzProgressBar, bz_progress_bar, ADW_TYPE_BIN) enum { PROP_0, PROP_FRACTION, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_progress_bar_dispose (GObject *object) { BzProgressBar *self = BZ_PROGRESS_BAR (object); g_clear_object (&self->animation); G_OBJECT_CLASS (bz_progress_bar_parent_class)->dispose (object); } static void bz_progress_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzProgressBar *self = BZ_PROGRESS_BAR (object); switch (prop_id) { case PROP_FRACTION: g_value_set_double (value, bz_progress_bar_get_fraction (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_progress_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzProgressBar *self = BZ_PROGRESS_BAR (object); switch (prop_id) { case PROP_FRACTION: bz_progress_bar_set_fraction (self, g_value_get_double (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_progress_bar_class_init (BzProgressBarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_progress_bar_dispose; object_class->get_property = bz_progress_bar_get_property; object_class->set_property = bz_progress_bar_set_property; props[PROP_FRACTION] = g_param_spec_double ( "fraction", NULL, NULL, 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-progress-bar.ui"); gtk_widget_class_bind_template_child (widget_class, BzProgressBar, bar); } static void bz_progress_bar_init (BzProgressBar *self) { AdwAnimationTarget *target = NULL; AdwSpringParams *spring = NULL; gtk_widget_init_template (GTK_WIDGET (self)); target = adw_property_animation_target_new (G_OBJECT (self->bar), "fraction"); spring = adw_spring_params_new (1.0, 0.5, 200.0); self->animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, spring, target); adw_spring_animation_set_epsilon ( ADW_SPRING_ANIMATION (self->animation), 0.00025); } GtkWidget * bz_progress_bar_new (void) { return g_object_new (BZ_TYPE_PROGRESS_BAR, NULL); } void bz_progress_bar_set_fraction (BzProgressBar *self, double fraction) { double last = 0.0; double current = 0.0; g_return_if_fail (BZ_IS_PROGRESS_BAR (self)); last = self->fraction; self->fraction = CLAMP (fraction, 0.0, 1.0); current = gtk_progress_bar_get_fraction (self->bar); if (self->fraction < last || G_APPROX_VALUE (last, self->fraction, 0.001)) { adw_animation_reset (self->animation); gtk_progress_bar_set_fraction (self->bar, self->fraction); } else { adw_spring_animation_set_value_from ( ADW_SPRING_ANIMATION (self->animation), current); adw_spring_animation_set_value_to ( ADW_SPRING_ANIMATION (self->animation), self->fraction); adw_spring_animation_set_initial_velocity ( ADW_SPRING_ANIMATION (self->animation), adw_spring_animation_get_velocity ( ADW_SPRING_ANIMATION (self->animation))); adw_animation_play (self->animation); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FRACTION]); } double bz_progress_bar_get_fraction (BzProgressBar *self) { g_return_val_if_fail (BZ_IS_PROGRESS_BAR (self), 0.0); return self->fraction; }