diff --git a/src/libsysprof-gtk/meson.build b/src/libsysprof-gtk/meson.build index 3c3a9fa4..bdaf36d0 100644 --- a/src/libsysprof-gtk/meson.build +++ b/src/libsysprof-gtk/meson.build @@ -7,6 +7,7 @@ libsysprof_gtk_private_sources = [ 'sysprof-css.c', 'sysprof-progress-cell.c', 'sysprof-symbol-label.c', + 'sysprof-time-label.c', ] libsysprof_gtk_public_headers = [ diff --git a/src/libsysprof-gtk/sysprof-time-label-private.h b/src/libsysprof-gtk/sysprof-time-label-private.h new file mode 100644 index 00000000..19989491 --- /dev/null +++ b/src/libsysprof-gtk/sysprof-time-label-private.h @@ -0,0 +1,39 @@ +/* sysprof-time-label.h + * + * Copyright 2023 Christian Hergert + * + * 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 + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define SYSPROF_TYPE_TIME_LABEL (sysprof_time_label_get_type()) + +G_DECLARE_FINAL_TYPE (SysprofTimeLabel, sysprof_time_label, SYSPROF, TIME_LABEL, GtkWidget) + +GtkWidget *sysprof_time_label_new (void); +gint64 sysprof_time_label_get_duration (SysprofTimeLabel *self); +void sysprof_time_label_set_duration (SysprofTimeLabel *self, + gint64 duration); +gint64 sysprof_time_label_get_time_offset (SysprofTimeLabel *self); +void sysprof_time_label_set_time_offset (SysprofTimeLabel *self, + gint64 time_offset); + +G_END_DECLS diff --git a/src/libsysprof-gtk/sysprof-time-label.c b/src/libsysprof-gtk/sysprof-time-label.c new file mode 100644 index 00000000..56760ada --- /dev/null +++ b/src/libsysprof-gtk/sysprof-time-label.c @@ -0,0 +1,213 @@ +/* sysprof-time-label.c + * + * Copyright 2023 Christian Hergert + * + * 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 + +#include "sysprof-time-label-private.h" + +struct _SysprofTimeLabel +{ + GtkWidget parent_instance; + GtkLabel *label; + gint64 t; + guint mode : 1; +}; + +enum { + PROP_0, + PROP_TIME_OFFSET, + PROP_DURATION, + N_PROPS +}; + +enum { + MODE_TIME_OFFSET, + MODE_DURATION, +}; + +G_DEFINE_FINAL_TYPE (SysprofTimeLabel, sysprof_time_label, GTK_TYPE_WIDGET) + +static GParamSpec *properties [N_PROPS]; + +static void +sysprof_time_label_dispose (GObject *object) +{ + SysprofTimeLabel *self = (SysprofTimeLabel *)object; + + if (self->label) + { + gtk_widget_unparent (GTK_WIDGET (self->label)); + self->label = NULL; + } + + G_OBJECT_CLASS (sysprof_time_label_parent_class)->dispose (object); +} + +static void +sysprof_time_label_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SysprofTimeLabel *self = SYSPROF_TIME_LABEL (object); + + switch (prop_id) + { + case PROP_DURATION: + g_value_set_int64 (value, sysprof_time_label_get_duration (self)); + break; + + case PROP_TIME_OFFSET: + g_value_set_int64 (value, sysprof_time_label_get_time_offset (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_time_label_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SysprofTimeLabel *self = SYSPROF_TIME_LABEL (object); + + switch (prop_id) + { + case PROP_DURATION: + sysprof_time_label_set_duration (self, g_value_get_int64 (value)); + break; + + case PROP_TIME_OFFSET: + sysprof_time_label_set_time_offset (self, g_value_get_int64 (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_time_label_class_init (SysprofTimeLabelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = sysprof_time_label_dispose; + object_class->get_property = sysprof_time_label_get_property; + object_class->set_property = sysprof_time_label_set_property; + + properties [PROP_DURATION] = + g_param_spec_int64 ("duration", NULL, NULL, + G_MININT64, G_MAXINT64, 0, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + properties [PROP_TIME_OFFSET] = + g_param_spec_int64 ("time-offset", NULL, NULL, + G_MININT64, G_MAXINT64, 0, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); + + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); + gtk_widget_class_set_css_name (widget_class, "timelabel"); +} + +static void +sysprof_time_label_init (SysprofTimeLabel *self) +{ + self->label = g_object_new (GTK_TYPE_LABEL, + "xalign", 1.f, + NULL); + gtk_widget_set_parent (GTK_WIDGET (self->label), GTK_WIDGET (self)); +} + +static void +sysprof_time_label_set_internal (SysprofTimeLabel *self, + gint64 t, + guint mode) +{ + g_return_if_fail (SYSPROF_IS_TIME_LABEL (self)); + + if (mode == self->mode && t == self->t) + return; + + self->mode = mode; + self->t = t; + + if (mode == MODE_DURATION) + { + char str[32]; + + if (t == 0) + str[0] = 0; + else if (t < SYSPROF_NSEC_PER_SEC/1000) + g_snprintf (str, sizeof str, "%.3lfμs", t/1000.); + else if (t < SYSPROF_NSEC_PER_SEC/1000000) + g_snprintf (str, sizeof str, "%.3lfms", t/1000000.); + else + g_snprintf (str, sizeof str, "%.3lfs", t/(double)SYSPROF_NSEC_PER_SEC); + + gtk_label_set_label (self->label, str); + } + else + { + char str[32]; + g_snprintf (str, sizeof str, "%0.3lfs", t/(double)SYSPROF_NSEC_PER_SEC); + gtk_label_set_label (self->label, str); + } + + g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DURATION]); + g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TIME_OFFSET]); +} + +gint64 +sysprof_time_label_get_duration (SysprofTimeLabel *self) +{ + if (self->mode == MODE_DURATION) + return self->t; + return 0; +} + +void +sysprof_time_label_set_duration (SysprofTimeLabel *self, + gint64 duration) +{ + sysprof_time_label_set_internal (self, duration, MODE_DURATION); +} + +gint64 +sysprof_time_label_get_time_offset (SysprofTimeLabel *self) +{ + if (self->mode == MODE_TIME_OFFSET) + return self->t; + return 0; +} + +void +sysprof_time_label_set_time_offset (SysprofTimeLabel *self, + gint64 time_offset) +{ + sysprof_time_label_set_internal (self, time_offset, MODE_TIME_OFFSET); +}