*
* 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 <https://www.gnu.org/licenses/>.
*
* 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;
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;
}