Gtk2-Ex-ErrorTextDialog
view release on metacpan or search on metacpan
lib/Gtk2/Ex/TextView/FollowAppend.pm view on Meta::CPAN
use Glib::Object::Subclass
'Gtk2::TextView',
signals => { size_allocate => \&_do_size_allocate,
# notify => \&_do_notify,
destroy => \&_do_destroy,
};
sub new_with_buffer {
my ($class, $textbuf) = @_;
return $class->Glib::Object::new (buffer => $textbuf);
}
# "notify" is done as a connect to self rather than a class handler.
# A long-standing glib bug causes a $self->signal_chain_from_overridden to
# go to the wrong handler, when a notify is invoked from under another
# handler, or something like that. Very annoying.
sub INIT_INSTANCE {
my ($self) = @_;
$self->signal_connect (notify => \&_do_notify);
}
# 'destroy' class closure
sub _do_destroy {
my ($self) = @_;
### FollowAppend _do_destroy(): "$self"
# The GtkObjectFlags GTK_IN_DESTRUCTION might do this, if it was exposed
# at the perl level. Except gtk_object_dispose() looks like the flag
# might be set solely while 'destroy' runs, but any notifies during
# finalize should suppress get_buffer() below too. Except can finalize
# emit notify anyway?
#
$self->{'destroyed'} = 1;
$self->signal_chain_from_overridden ();
}
# 'notify' class closure
sub _do_notify {
my ($self, $pspec) = @_;
### FollowAppend _do_notify(): $pspec->get_name
# my $invocation_hint = $self->signal_get_invocation_hint;
# require Data::Dumper;
# print Data::Dumper->Indent(1)->Dump([$invocation_hint],
# ['invocation_hint']);
# $self->signal_chain_from_overridden ($pspec);
# After 'destroy' runs it's important not to call ->get_buffer() since
# that func creates a new TextBuffer in place of what
# gtk_text_view_destroy() just destroyed and set to NULL. If a textbuf is
# re-created like that it leads to a fatal error in
# gtk_text_view_finalize().
#
if (! $self->{'destroyed'} && $pspec->get_name eq 'buffer') {
require Glib::Ex::SignalIds;
require Scalar::Util;
my $textbuf = $self->get_buffer;
Scalar::Util::weaken (my $weak_self = $self);
my $ref_weak_self = \$weak_self;
$self->{'textbuf_ids'} = $textbuf && Glib::Ex::SignalIds->new
($textbuf,
$textbuf->signal_connect_after ('insert-text',
\&_do_textbuf_insert,
$ref_weak_self),
$textbuf->signal_connect_after ('insert-pixbuf',
\&_do_textbuf_insert_pixbuf_or_anchor,
$ref_weak_self),
$textbuf->signal_connect_after ('insert-child-anchor',
\&_do_textbuf_insert_pixbuf_or_anchor,
$ref_weak_self));
}
}
# 'size-allocate' class closure
sub _do_size_allocate {
my ($self, $alloc) = @_;
### FollowAppend size_allocate: $alloc->x.",".$alloc->y." ".$alloc->width."x".$alloc->height
my $want_follow = _want_follow ($self);
### $want_follow
$self->signal_chain_from_overridden ($alloc);
if ($want_follow) {
### _do_size_allocate() scroll_to_mark
$self->scroll_to_mark ($self->get_buffer->get_insert, 0, 0, 0,0);
}
}
# 'insert-pixbuf' and 'insert-child-anchor' signal handler on textbuf
sub _do_textbuf_insert_pixbuf_or_anchor {
my ($textbuf, $iter, $pixbuf_or_anchor, $ref_weak_self) = @_;
_do_textbuf_insert ($textbuf, $iter, undef, 1, $ref_weak_self);
}
# 'insert-text' signal handler on textbuf,
# plus fakery from 'insert-pixbuf' and 'insert-child-anchor' above
sub _do_textbuf_insert {
my ($textbuf, $iter, $text, $textlen, $ref_weak_self) = @_;
my $self = $$ref_weak_self || return;
### FollowAppend _do_textbuf_insert() iter: $iter->get_offset
### $textlen
### $text
if ($iter->is_end
&& _want_follow ($self,
$textbuf->get_iter_at_offset
($iter->get_offset - $textlen))) {
### _do_textbuf_insert() scroll_to_mark
$self->scroll_to_mark ($textbuf->get_insert, 0, 0, 0,0);
}
}
sub _want_follow {
my ($self, $insert_iter) = @_;
my $textbuf = $self->get_buffer;
my $cursor_iter = $textbuf->get_iter_at_mark ($textbuf->get_insert);
( run in 1.178 second using v1.01-cache-2.11-cpan-39bf76dae61 )