diff --git a/src/libsysprof-gtk/sysprof-tracks-view.c b/src/libsysprof-gtk/sysprof-tracks-view.c index d0e44bda..5d25475a 100644 --- a/src/libsysprof-gtk/sysprof-tracks-view.c +++ b/src/libsysprof-gtk/sysprof-tracks-view.c @@ -31,8 +31,10 @@ struct _SysprofTracksView SysprofSession *session; + GtkBox *box; GtkWidget *top_left; GtkListView *list_view; + GtkButton *zoom; double motion_x; double motion_y; @@ -119,6 +121,8 @@ sysprof_tracks_view_drag_begin_cb (SysprofTracksView *self, self->drag_offset_x = 0; self->drag_offset_y = 0; + gtk_widget_set_visible (GTK_WIDGET (self->zoom), FALSE); + self->in_drag_selection = TRUE; gtk_widget_queue_draw (GTK_WIDGET (self)); @@ -315,13 +319,70 @@ G_GNUC_END_IGNORE_DEPRECATIONS gtk_widget_get_height (GTK_WIDGET (self)))); } +static void +sysprof_tracks_view_measure (GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline) +{ + SysprofTracksView *self = (SysprofTracksView *)widget; + + g_assert (SYSPROF_IS_TRACKS_VIEW (self)); + + gtk_widget_measure (GTK_WIDGET (self->box), + orientation, + for_size, + minimum, + natural, + minimum_baseline, + natural_baseline); +} + +static void +sysprof_tracks_view_size_allocate (GtkWidget *widget, + int width, + int height, + int baseline) +{ + SysprofTracksView *self = (SysprofTracksView *)widget; + graphene_rect_t area; + graphene_rect_t selection; + + g_assert (SYSPROF_IS_TRACKS_VIEW (self)); + + gtk_widget_size_allocate (GTK_WIDGET (self->box), + &(GtkAllocation) {0, 0, width, height}, + baseline); + + if (get_selected_area (self, &area, &selection)) + { + graphene_point_t middle; + GtkRequisition min_req; + GtkRequisition nat_req; + + gtk_widget_get_preferred_size (GTK_WIDGET (self->zoom), &min_req, &nat_req); + graphene_rect_get_center (&selection, &middle); + + gtk_widget_size_allocate (GTK_WIDGET (self->zoom), + &(GtkAllocation) { + middle.x - (min_req.width/2), + middle.y - (min_req.height/2), + min_req.width, + min_req.height + }, -1); + } +} + static void sysprof_tracks_view_dispose (GObject *object) { SysprofTracksView *self = (SysprofTracksView *)object; GtkWidget *child; - g_clear_object (&self->session); + sysprof_tracks_view_set_session (self, NULL); gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_TRACKS_VIEW); @@ -380,6 +441,8 @@ sysprof_tracks_view_class_init (SysprofTracksViewClass *klass) object_class->set_property = sysprof_tracks_view_set_property; widget_class->snapshot = sysprof_tracks_view_snapshot; + widget_class->measure = sysprof_tracks_view_measure; + widget_class->size_allocate = sysprof_tracks_view_size_allocate; properties[PROP_SESSION] = g_param_spec_object ("session", NULL, NULL, @@ -389,11 +452,12 @@ sysprof_tracks_view_class_init (SysprofTracksViewClass *klass) g_object_class_install_properties (object_class, N_PROPS, properties); gtk_widget_class_set_template_from_resource (widget_class, "/libsysprof-gtk/sysprof-tracks-view.ui"); - gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); gtk_widget_class_set_css_name (widget_class, "tracks"); + gtk_widget_class_bind_template_child (widget_class, SysprofTracksView, box); gtk_widget_class_bind_template_child (widget_class, SysprofTracksView, list_view); gtk_widget_class_bind_template_child (widget_class, SysprofTracksView, top_left); + gtk_widget_class_bind_template_child (widget_class, SysprofTracksView, zoom); gtk_widget_class_bind_template_callback (widget_class, sysprof_tracks_view_motion_enter_cb); gtk_widget_class_bind_template_callback (widget_class, sysprof_tracks_view_motion_leave_cb); @@ -446,6 +510,26 @@ sysprof_tracks_view_create_model_func (gpointer item, return sysprof_track_list_subtracks (item); } +static void +sysprof_tracks_view_notify_selected_time_cb (SysprofTracksView *self, + GParamSpec *pspec, + SysprofSession *session) +{ + const SysprofTimeSpan *visible; + const SysprofTimeSpan *selected; + gboolean button_visible; + + g_assert (SYSPROF_IS_TRACKS_VIEW (self)); + g_assert (SYSPROF_IS_SESSION (session)); + + visible = sysprof_session_get_visible_time (session); + selected = sysprof_session_get_selected_time (session); + + button_visible = memcmp (visible, selected, sizeof *visible) != 0; + + gtk_widget_set_visible (GTK_WIDGET (self->zoom), button_visible); +} + void sysprof_tracks_view_set_session (SysprofTracksView *self, SysprofSession *session) @@ -458,6 +542,9 @@ sysprof_tracks_view_set_session (SysprofTracksView *self, if (self->session) { + g_signal_handlers_disconnect_by_func (self->session, + G_CALLBACK (sysprof_tracks_view_notify_selected_time_cb), + self); gtk_list_view_set_model (self->list_view, NULL); g_clear_object (&self->session); } @@ -479,6 +566,12 @@ sysprof_tracks_view_set_session (SysprofTracksView *self, no = gtk_no_selection_new (g_object_ref (G_LIST_MODEL (tree_list_model))); gtk_list_view_set_model (self->list_view, GTK_SELECTION_MODEL (no)); + + g_signal_connect_object (session, + "notify::selected-time", + G_CALLBACK (sysprof_tracks_view_notify_selected_time_cb), + self, + G_CONNECT_SWAPPED); } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]); diff --git a/src/libsysprof-gtk/sysprof-tracks-view.ui b/src/libsysprof-gtk/sysprof-tracks-view.ui index 71224539..2c4d3669 100644 --- a/src/libsysprof-gtk/sysprof-tracks-view.ui +++ b/src/libsysprof-gtk/sysprof-tracks-view.ui @@ -16,7 +16,7 @@ - + vertical @@ -140,5 +140,17 @@ + + + zoom-to-selection + zoom-in-symbolic + center + center + false + + +