[perl-glib-object-introspection] perli11ndoc: add support for links in the results display
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-glib-object-introspection] perli11ndoc: add support for links in the results display
- Date: Tue, 25 Sep 2018 19:39:12 +0000 (UTC)
commit 144225fc9be8972073a4b51349827448be232314
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date: Tue Sep 25 21:36:36 2018 +0200
perli11ndoc: add support for links in the results display
Also, add a delay to the search function to make it stutter less.
bin/perli11ndoc | 194 +++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 164 insertions(+), 30 deletions(-)
---
diff --git a/bin/perli11ndoc b/bin/perli11ndoc
index c42821f..7c56985 100755
--- a/bin/perli11ndoc
+++ b/bin/perli11ndoc
@@ -381,7 +381,7 @@ sub format_namespace {
next unless @$entries;
$text .= "$heading\n\n";
foreach my $entry (@$entries) {
- $text .= ' ' . $entry->{name} . "\n";
+ $text .= sprintf " [%s](%s)\n", $entry->{name}, $entry->{path};
}
$text .= "\n";
}
@@ -832,9 +832,10 @@ sub format_sub_constructors {
$text .= "\nCONSTRUCTORS\n\n";
foreach my $ctor ($ctor_list->get_nodelist) {
my $name = $self->find_attribute ($ctor, 'name');
+ my $path = $ctor->nodePath;
my $flags = $self->format_callable_flags ($ctor,
qw/introspectable version/);
- $text .= " • $name$flags\n";
+ $text .= " • [$name]($path)$flags\n";
}
}
return $text;
@@ -848,10 +849,11 @@ sub format_sub_fields {
$text .= "\nFIELDS\n\n";
foreach my $field ($field_list->get_nodelist) {
my $name = $self->find_attribute ($field, 'name');
+ my $path = $field->nodePath;
my $type_name = $self->find_type_name ($field);
my $full_type_name = $self->format_full_type_name ($type_name);
my $flags = $self->format_field_flags ($field, qw/introspectable/);
- $text .= " • $name: $full_type_name$flags\n";
+ $text .= " • [$name]($path): $full_type_name$flags\n";
}
}
return $text;
@@ -865,9 +867,10 @@ sub format_sub_functions {
$text .= "\n$heading\n\n";
foreach my $function ($function_list->get_nodelist) {
my $name = $self->find_attribute ($function, 'name');
+ my $path = $function->nodePath;
my $flags = $self->format_callable_flags ($function,
qw/introspectable version/);
- $text .= " • $name$flags\n";
+ $text .= " • [$name]($path)$flags\n";
}
}
return $text;
@@ -900,9 +903,10 @@ sub format_sub_methods {
$text .= "\nMETHODS\n\n";
foreach my $method ($method_list->get_nodelist) {
my $name = $self->find_attribute ($method, 'name');
+ my $path = $method->nodePath;
my $flags = $self->format_callable_flags ($method,
qw/introspectable version/);
- $text .= " • $name$flags\n";
+ $text .= " • [$name]($path)$flags\n";
}
}
return $text;
@@ -916,10 +920,11 @@ sub format_sub_properties {
$text .= "\nPROPERTIES\n\n";
foreach my $property ($property_list->get_nodelist) {
my $name = $self->find_attribute ($property, 'name');
+ my $path = $property->nodePath;
my $type_name = $self->find_type_name ($property);
my $full_type_name = $self->format_full_type_name ($type_name);
my $flags = $self->format_property_flags ($property, qw/version/);
- $text .= " • $name: $full_type_name$flags\n";
+ $text .= " • [$name]($path): $full_type_name$flags\n";
}
}
return $text;
@@ -933,8 +938,9 @@ sub format_sub_signals {
$text .= "\nSIGNALS\n\n";
foreach my $signal ($signal_list->get_nodelist) {
my $name = $self->find_attribute ($signal, 'name');
+ my $path = $signal->nodePath;
my $flags = $self->format_signal_flags ($signal, qw/version/);
- $text .= " • $name$flags\n";
+ $text .= " • [$name]($path)$flags\n";
}
}
return $text;
@@ -948,8 +954,9 @@ sub format_sub_virtual_methods {
$text .= "\nVIRTUAL METHODS\n\n";
foreach my $vfunc ($vfunc_list->get_nodelist) {
my $name = $self->find_attribute ($vfunc, 'name');
+ my $path = $vfunc->nodePath;
my $flags = $self->format_virtual_method_flags ($vfunc);
- $text .= " • $name$flags\n";
+ $text .= " • [$name]($path)$flags\n";
}
}
return $text;
@@ -1314,7 +1321,35 @@ sub filter_gir_view {
sub display_results {
my ($self, $results) = @_;
- $self->{result_buffer}->set_text ($results);
+
+ my $b = $self->{result_buffer};
+ $b->delete ($b->get_start_iter (), $b->get_end_iter ());
+
+ my $iter = $b->get_start_iter ();
+ my $insert_part = sub {
+ my ($start, $end) = @_;
+ $b->insert ($iter, substr ($results, $start, $end - $start));
+ };
+
+ my ($prev_match_start, $prev_match_end) = (0, 0);
+ while ($results =~ m/\[([^\n\]]+)\]\(([^\n\)]+)\)/g) {
+ my ($link_text, $link_target) = ($1, $2);
+ my ($match_start, $match_end) = ($-[0], $+[0]);
+
+ if ($match_start != $prev_match_end) {
+ $insert_part->($prev_match_end, $match_start);
+ }
+
+ my $tag = $b->create_tag (undef, foreground => 'blue');
+ $tag->{__target} = $link_target;
+ $b->insert_with_tags ($iter, $link_text, $tag);
+
+ ($prev_match_start, $prev_match_end) = ($match_start, $match_end);
+ }
+ my $end_offset = length ($results);
+ if ($prev_match_end != $end_offset) {
+ $insert_part->($prev_match_end, $end_offset);
+ }
}
sub run {
@@ -1409,7 +1444,7 @@ sub setup_gir_view {
});
$gir_view->get_selection->signal_connect (changed => sub {
- $self->update_results_from_selection
+ $self->go_to_selection
unless $self->{suppress_gir_view_selection_changes};
});
@@ -1431,9 +1466,19 @@ sub setup_path_bar {
sub setup_search_entry {
my ($self) = @_;
+ my $wait_time_ms = 500;
my $search_entry = Gtk3::SearchEntry->new;
$search_entry->signal_connect (search_changed => sub {
- $self->filter_gir_view ($search_entry->get_text);
+ # Use a timeout which is reset when the search text changes so that we do
+ # not filter the view too often.
+ if (defined $search_entry->{__timer_id}) {
+ Glib::Source->remove ($search_entry->{__timer_id});
+ }
+ $search_entry->{__timer_id} = Glib::Timeout->add ($wait_time_ms, sub {
+ $self->filter_gir_view ($search_entry->get_text);
+ $search_entry->{__timer_id} = undef;
+ return Glib::SOURCE_REMOVE ();
+ });
});
$self->{search_entry} = $search_entry;
@@ -1443,9 +1488,66 @@ sub setup_result_view {
my ($self) = @_;
my $result_buffer = Gtk3::TextBuffer->new (undef);
+
my $result_view = Gtk3::TextView->new_with_buffer ($result_buffer);
$result_view->set (editable => FALSE, margin => 2);
+ my $display = $result_view->get_display ();
+ $result_view->{__hand_cursor} = Gtk3::Gdk::Cursor->new_from_name ($display, 'pointer');
+ $result_view->{__regular_cursor} = Gtk3::Gdk::Cursor->new_from_name ($display, 'text');
+
+ my $hovering_over_link = sub {
+ my ($event) = @_;
+ my ($x, $y) = $result_view->window_to_buffer_coords ('widget', $event->x, $event->y);
+ my $iter = $result_view->get_iter_at_location ($x, $y);
+ if (!$iter) {
+ return undef;
+ }
+ my $tags = $iter->get_tags ();
+ foreach my $tag (@$tags) {
+ if (defined $tag->{__target}) {
+ return $tag;
+ }
+ }
+ return undef;
+ };
+
+ $result_view->{__hovering} = FALSE;
+ $result_view->signal_connect (motion_notify_event => sub {
+ my ($result_view, $event) = @_;
+ my $hovering = defined $hovering_over_link->($event);
+ if ($result_view->{__hovering} != $hovering) {
+ $result_view->{__hovering} = $hovering;
+ $result_view->get_window ('text')->set_cursor (
+ $hovering ? $result_view->{__hand_cursor} : $result_view->{__regular_cursor});
+ }
+ return Gtk3::EVENT_PROPAGATE ();
+ });
+
+ my $handle_button = sub {
+ my ($event, $cb) = @_;
+ if ($event->button == Gtk3::Gdk::BUTTON_PRIMARY ()) {
+ my $tag = $hovering_over_link->($event);
+ if (defined $tag) {
+ if (defined $cb) {
+ $cb->($tag);
+ }
+ return Gtk3::EVENT_STOP ();
+ }
+ }
+ return Gtk3::EVENT_PROPAGATE ();
+ };
+ $result_view->signal_connect (button_press_event => sub {
+ my ($result_view, $event) = @_;
+ return $handle_button->($event);
+ });
+ $result_view->signal_connect (button_release_event => sub {
+ my ($result_view, $event) = @_;
+ return $handle_button->($event, sub {
+ $self->go_to_path ($_[0]->{__target});
+ });
+ });
+
$self->{result_buffer} = $result_buffer;
$self->{result_view} = $result_view;
}
@@ -1457,6 +1559,7 @@ sub update_gir_view {
$self->{gir_model}->clear;
$self->{search_entry}->set_text ('');
+ $self->{path_bar}->clear;
my $inserter = sub {
my ($iter, $text, $path, $is_cat, $is_vis) = @_;
@@ -1502,7 +1605,7 @@ sub update_gir_view {
$self->display_results ($self->{parser}->format_namespace);
}
-sub update_results_from_selection {
+sub go_to_selection {
my ($self) = @_;
my $selection = $self->{gir_view}->get_selection;
my ($model, $iter) = $selection->get_selected;
@@ -1510,28 +1613,36 @@ sub update_results_from_selection {
$self->display_results ($self->{parser}->format_namespace);
} elsif (!$model->get ($iter, GIR_VIEW_COL_IS_CATEGORY)) {
my $path = $model->get ($iter, GIR_VIEW_COL_PATH);
- my $name = $self->{parser}->format_node_name_by_path ($path);
- $self->{path_bar}->append ($name, $path); # indirectly calls update_results
+ $self->go_to_path ($path);
}
}
+sub go_to_path {
+ my ($self, $path) = @_;
+ my $name = $self->{parser}->format_node_name_by_path ($path);
+ $self->{path_bar}->append ($name, $path); # indirectly calls update_results
+}
+
sub update_results {
my ($self, $path) = @_;
$self->display_results ($self->{parser}->format_node_by_path ($path));
- # If display and selection are out-of-sync, clear the selection.
- my $selection = $self->{gir_view}->get_selection;
- my ($model, $iter) = $selection->get_selected;
- if (defined $iter) {
- my $sel_path = $model->get ($iter, GIR_VIEW_COL_PATH);
- if ($sel_path ne $path) {
+ # Show and select the correponding tree entry.
+ $self->{gir_model}->foreach (sub {
+ my ($model, $tree_path, $iter) = @_;
+ my $this_path = $model->get ($iter, GIR_VIEW_COL_PATH);
+ if (defined $this_path && $this_path eq $path) {
+ $self->{gir_view}->expand_to_path ($tree_path);
+ $self->{gir_view}->scroll_to_cell ($tree_path, undef, FALSE, 0.0, 0.0);
$self->{suppress_gir_view_selection_changes} = TRUE;
{
- $selection->unselect_all;
+ $self->{gir_view}->get_selection ()->select_path ($tree_path);
}
$self->{suppress_gir_view_selection_changes} = FALSE;
+ return TRUE; # stop
}
- }
+ return FALSE; # continue
+ });
}
sub quit {
@@ -1588,6 +1699,12 @@ sub INIT_INSTANCE {
return $self;
}
+sub clear {
+ my ($self) = @_;
+ $self->{path_label}->clear ();
+ $self->update_buttons ();
+}
+
sub append {
my ($self, $name, $path) = @_;
$self->{path_label}->append ($name, $path);
@@ -1619,20 +1736,35 @@ sub INIT_INSTANCE {
my (undef, $index) = @_;
$self->{current_child} = $index;
$self->update;
- return TRUE; # handled
+ return Gtk3::EVENT_STOP ();
});
$self->set_track_visited_links (FALSE);
+ $self->clear ();
+}
+
+sub clear {
+ my ($self) = @_;
$self->{children} = [];
$self->{current_child} = undef;
$self->{natural_width} = 0;
+ $self->update ();
}
sub append {
my ($self, $name, $path) = @_;
- if (defined $self->{current_child} &&
- $self->{current_child} < $#{$self->{children}}) {
- splice @{$self->{children}}, $self->{current_child}+1;
+ my $cur = $self->{current_child};
+ # If the new entry is equal to the current entry, do nothing.
+ if (defined $cur) {
+ my $child = $self->{children}->[$cur];
+ if ($child->{name} eq $name && $child->{path} eq $path) {
+ return;
+ }
+ }
+ # If the current entry is not the last entry, remove all entries after the
+ # current one before appending the new entry.
+ if (defined $cur && $cur < $#{$self->{children}}) {
+ splice @{$self->{children}}, $cur+1;
}
push @{$self->{children}}, {name => $name, path => $path};
$self->{current_child} = $#{$self->{children}};
@@ -1641,12 +1773,12 @@ sub append {
sub can_go_back {
my ($self) = @_;
- return $self->{current_child} > 0;
+ return defined $self->{current_child} && $self->{current_child} > 0;
}
sub can_go_forward {
my ($self) = @_;
- return $self->{current_child} < $#{$self->{children}};
+ return defined $self->{current_child} && $self->{current_child} < $#{$self->{children}};
}
sub go_back {
@@ -1671,7 +1803,7 @@ sub set_update_func {
sub update {
my ($self) = @_;
$self->set_markup ($self->_format_children);
- if (defined $self->{update_func}) {
+ if (defined $self->{current_child} && defined $self->{update_func}) {
my $child = $self->{children}->[$self->{current_child}];
$self->{update_func}->($child->{name}, $child->{path});
}
@@ -1687,7 +1819,6 @@ sub GET_PREFERRED_WIDTH {
sub SIZE_ALLOCATE {
#say 'SIZE_ALLOCATE';
my ($self, $allocation) = @_;
- #print "$_ => $allocation->{$_}, " for sort keys %$allocation; print "\n";
if ($self->{natural_width} > $allocation->{width}) {
my @selected = ($self->{current_child});
while (1) {
@@ -1715,6 +1846,9 @@ sub SIZE_ALLOCATE {
# Use undef as an indicator for left-out children.
sub _add_omission_markers {
my ($self, @indices) = @_;
+ if (!@indices) {
+ return @indices;
+ }
if ($indices[0] > 0) {
unshift @indices, undef;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]