view release on metacpan or search on metacpan
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
if $self->_is_my_tag($tag);
return 0;
}
##########
# _on_remove_tag - to facilitate undo and redo, record tags removals.
# NOTE: the signal handler recieves a start and end range exactly matching
# what was used in the $buf->remove_tag(...) call, which may be wrong
# if the range includes bits where the tag wasn't applied in the first
# place. All tag removals in code should therefore be done with the
# _remove_tag or _remove_tag_cascade functions within this package
##########
sub _on_remove_tag {
my $self = shift;
my ($buf, $tag, $s, $e) = @_;
$self->_record_undo(UNDO_REMOVE_TAG, $s->get_offset, $e->get_offset, $tag)
if $self->_is_my_tag($tag);
return 0;
}
##########
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
my $start = $iter->copy;
$start->backward_chars(length $str);
$self->_record_undo(UNDO_INSERT_TEXT, $start->get_offset, $iter->get_offset,
$str);
# Ensure correct tags applied to text inserted
$buf->get_tag_table->
foreach(sub {
my ($tag) = @_;
return if not $self->_is_my_tag($tag);
if (exists $self->{Active}{$tag->get_property('name')}) {
$self->_apply_tag_cascade($tag, $start, $iter);
} else {
$self->_remove_tag_cascade($tag, $start, $iter);
}
});
# What if this insert just bridged two paragraphs?!
$self->_normalise_paragraph($start, $iter);
$self->_set_active_from_text;
$self->_commit_record_undo if $commit;
$self->_set_buttons_from_active;
return 0;
}
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
my $self = shift;
return 0 if $self->{Lock}{Buttons}; # Programmatic button change in progress
my ($name) = @_;
my $commit = $self->_start_record_undo;
my $tname = $BUTTONS{$name}{Tag};
my ($s, $e) = $self->_get_current_bounds_for_tag($tname);
if ($self->{Buttons}{$name}->get_active) {
# Switching on
my $tag = $self->_create_tag($self->_full_tag_name($tname),
%{$TAGS{$tname}{Look}});
$self->_apply_tag_cascade($tag, $s, $e);
$self->_normalise_paragraph($s, $e)
if ($tname eq 'asis' or $tname eq 'pre') and not $s->equal($e);
$self->_set_active_from_text if not $s->equal($e);
$self->{Active}{$tag->get_property('name')} = undef;
$self->_set_buttons_from_active;
} else {
# Switching off
my $tag = $self->_full_tag_name($tname);
$self->_remove_tag_cascade($tag, $s, $e);
$self->_set_active_from_text if not $s->equal($e);
delete($self->{Active}{$tag});
$self->_set_buttons_from_active;
}
$self->_commit_record_undo if $commit;
return 0;
}
###########
# _on_multi_toggle_change - a toggle button has been toggled, and it is a
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
return 0 if $self->{Lock}{Buttons};
return 0 if $self->{Buttons}{$bname}->get_inconsistant; # make no changes!
my $commit = $self->_start_record_undo;
my ($s, $e);
my $buf = $self->{Text}->get_buffer;
for my $tag (@{$BUTTONS{$bname}{Tags}}) {
next if not exists $TAGS{$tag->[0]};
($s, $e) = $self->_get_current_bounds_for_tag($tag->[0])
if not defined $s;
last if $s->equal($e);
$self->_remove_tag_cascade($self->_full_tag_name($tag->[0]), $s, $e);
}
my $ftname = $self->_full_tag_name($tname);
my $tag = $self->_create_tag($ftname, %{$TAGS{$tname}{Look}})
if $display ne $BUTTONS{$bname}{Default};
if ($s->equal($e)) {
for my $tag (@{$BUTTONS{$bname}{Tags}}) {
delete($self->{Active}{$self->_full_tag_name($tag->[0])});
}
$self->{Active}{$ftname} = undef;
$self->_set_buttons_from_active;
} else {
$self->_apply_tag_cascade($tag, $s, $e)
if $display ne $BUTTONS{$bname}{Default};
# Update subscript and superscript over this range!
# Maybe meld this into apply_tag_cascade?
if ($tname =~ /^h[1-5]\z/) {
$self->_update_superscript($s, $e, undef, $TAGS{$tname}{Look}{scale});
$self->_update_subscript($s, $e, undef, $TAGS{$tname}{Look}{scale});
} elsif ($tname eq 'h0') {
$self->_update_superscript($s, $e, undef, 1);
$self->_update_subscript($s, $e, undef, 1);
}
$self->{Active}{$ftname} = undef;
$self->_set_buttons_from_active;
}
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
}
}
my $ftname = $self->_full_tag_name('font', $tname);
my $tag = $self->_create_tag($ftname, family => $tname)
if $display ne $BUTTONS{$bname}{Default};
if ($s->equal($e)) {
for my $tag (@{$BUTTONS{$bname}{Tags}}) {
delete($self->{Active}{$self->_full_tag_name('font', $tag)});
}
} elsif ($display ne $BUTTONS{$bname}{Default}) {
$self->_apply_tag_cascade($tag, $s, $e);
}
$self->{Active}{$ftname} = undef;
$self->_set_buttons_from_active;
$self->_commit_record_undo if $commit;
return 0;
}
sub _on_size_change {
my $self = shift;
return 0 if $self->{Lock}{Buttons};
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
my $commit = $self->_start_record_undo;
my $buf = $self->{Text}->get_buffer;
my $tname = $BUTTONS{$name}{Tag};
my ($s, $e) = $self->_get_current_bounds_for_tag($tname);
my $nosel = $s->equal($e);
if (not $nosel) {
$buf->get_tag_table->
foreach(sub {
my ($tag) = @_;
return if not $self->_is_my_tag($tag);
$self->_remove_tag_cascade($tag, $s, $e)
if $self->_short_tag_name($tag) eq $tname;
});
# Update super/subscript tags for this range!
$self->_update_subscript($s, $e, $size);
$self->_update_superscript($s, $e, $size);
}
my $tag = $self->_create_tag($self->_full_tag_name($tname, $size),
size => $size * 1024);
if ($nosel) {
for my $k (keys %{$self->{Active}}) {
delete($self->{Active}{$k})
if $self->_short_tag_name($k) eq $BUTTONS{$name}{Tag};
}
$self->{Active}{$tag->get_property('name')} = undef;
} else {
$self->_apply_tag_cascade($tag, $s, $e);
$self->_set_active_from_text;
}
$self->_set_buttons_from_active;
$self->_commit_record_undo if $commit;
return 0;
}
# Callbacks for specific buttons
sub _sup_sub_scan {
my $self = shift;
my ($s, $e, $type, $force) = @_;
my ($sz, $sc);
for my $tag ($s->get_tags) {
next if not $self->_is_my_tag($tag);
my $name = $self->_short_tag_name($tag);
if ($name eq 'superscript' or $name eq 'subscript') {
$self->_remove_tag_cascade($tag, $s, $e);
next;
}
if (not defined $sz and $name eq 'size') {
($sz) = $self->_tag_args($tag, 1);
} elsif (not defined $sc and $name =~ /^h[1-5]\z/) {
$sc = $TAGS{$name}{Look}{scale};
}
}
$sz = $BUTTONS{Size}{Default} if not defined $sz;
$sc = 1 if not $sc;
my $n = $s->copy;
$n->forward_to_tag_toggle(undef);
$n = $e->copy if $n->compare($e) == 1;
$self->_apply_tag_cascade($self->_create_sub_super_tag($type, $sz, $sc),
$s, $n);
return $n;
}
sub _create_sub_super_tag {
my $self = shift;
my ($type, $size, $scale) = @_;
my $rise = ($type eq 'superscript' ? 0.75 : -0.25);
$rise = int($size * $scale * $rise * 1024);
$self->_create_tag($self->_full_tag_name($type, $size, $scale),
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
sub _superscript_off {
my $self = shift;
my ($s, $e) = @_;
my $buf = $self->{Text}->get_buffer;
$buf->get_tag_table->
foreach(sub {
my ($tag) = @_;
return if (not $self->_is_my_tag($tag) or
$self->_short_tag_name($tag) ne 'superscript');
$self->_remove_tag_cascade($tag, $s, $e);
});
$self->_set_active_from_text;
$self->_set_buttons_from_active;
}
sub _update_superscript {
my $self = shift;
my ($s, $e, $force_size, $force_scale) = @_;
$s = $s->copy;
my $buf = $self->{Text}->get_buffer;
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
sub _subscript_off {
my $self = shift;
my ($s, $e) = @_;
my $buf = $self->{Text}->get_buffer;
$buf->get_tag_table->
foreach(sub {
my ($tag) = @_;
return if (not $self->_is_my_tag($tag) or
$self->_short_tag_name($tag) ne 'subscript');
$self->_remove_tag_cascade($tag, $s, $e);
});
$self->_set_active_from_text;
$self->_set_buttons_from_active;
}
sub _update_subscript {
my $self = shift;
my ($s, $e, $force_size, $force_scale) = @_;
$s = $s->copy;
my $buf = $self->{Text}->get_buffer;
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
($txt, $target) = $self->_get_link_target($txt, $target);
return 0 if not defined $txt; # What about length?!
my $tag = $self->_create_link($target);
if ($s->equal($e)) { # No selection
my $here = $buf->get_iter_at_mark($buf->get_insert);
my $s = $here->get_offset;
$buf->insert($here, $txt);
$s = $buf->get_iter_at_offset($s);
$e = $s->copy;
$e->forward_chars(length($txt));
$self->_apply_tag_cascade($tag, $s, $e);
} else {
my $off = $s->get_offset;
$buf->delete($s, $e); ## GET TAGS OVER THIS RANGE
$s = $buf->get_iter_at_offset($off);
$buf->insert($s, $txt); ## APPLY TAGS OVER THIS RANGE
$s = $buf->get_iter_at_offset($off);
$e = $s->copy;
$e->forward_chars(length($txt));
$self->_apply_tag_cascade($tag, $s, $e);
$buf->select_range($s, $e);
}
}
sub _create_link {
my $self = shift;
my ($target) = @_;
$self->{LinkID} = 0 if not exists $self->{LinkID};
my $tag = $self->_create_tag($self->_full_tag_name('link',
$self->{LinkID}++),
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
$tag->{Target} = $target;
return $tag;
}
sub _link_off {
my $self = shift;
my ($s, $e) = @_;
my $buf = $self->{Text}->get_buffer;
$buf->get_tag_table->foreach(sub {
my ($tag) = @_;
$self->_remove_tag_cascade($tag, $s, $e)
if ($self->_is_my_tag($tag) and
$self->_short_tag_name($tag) eq 'link');
}) if not $s->equal($e);
}
sub _get_link_target {
my $self = shift;
my ($txt, $target) = @_;
my $win = $self;
while (1) {
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
}
$self->_set_active_from_text if not $s->equal($buf->get_end_iter);
} else {
$buf->get_tag_table->foreach(sub {
my ($tag) = @_;
return if not $self->_is_my_tag($tag);
my $name = $self->_short_tag_name($tag);
return
if (not exists $TAGS{$name} or
$TAGS{$name}{Class} eq 'paragraph');
$self->_remove_tag_cascade($tag, $s, $e);
});
$self->_set_active_from_text;
}
$self->_set_buttons_from_active;
}
# Undo and Redo
sub _start_record_undo {
my $self = shift;
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
$opts{justification} = 'left'
if (exists $opts{justification} and $opts{justification} eq 'fill' and
$self->get_property('map-fill-to-left'));
my $tag = $self->{Text}->get_buffer->get_tag_table->lookup($name);
$tag = $self->{Text}->get_buffer->create_tag($name, %opts)
if not defined $tag;
$tag->{WYSIWYG} = undef; # Use this later to store data?
return $tag;
}
sub _apply_tag_cascade {
my $self = shift;
my ($tag, $start, $end) = @_;
my $buf = $self->{Text}->get_buffer;
$tag = $self->{Text}->get_buffer->get_tag_table->lookup($tag)
if not ref($tag);
return if not defined $tag;
my $regname = $self->_short_tag_name($tag);
my $tdef = $TAGS{$regname};
if ($regname eq 'asis') {
# Remove all non-paragraph tags
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
}
sub _apply_tag {
my $self = shift;
my ($tag, $start, $end) = @_;
$tag = $self->{Text}->get_buffer->get_tag_table->lookup($tag)
if not ref $tag;
$self->{Text}->get_buffer->apply_tag($tag, $start, $end) if defined $tag;
}
sub _remove_tag_cascade {
my $self = shift;
my ($tag, $start, $end) = @_;
# ONLY REMOVE THE TAG FROM THE AREAS IT IS APPLIED!
my $buf = $self->{Text}->get_buffer;
$self->_remove_tag($tag, $start, $end);
$tag = $tag->get_property('name') if ref($tag);
delete($self->{Active}{$tag});
return 1;
}
lib/Gtk2/Ex/WYSIWYG.pm view on Meta::CPAN
}
$buf->get_tag_table->foreach(sub {
my ($tag) = @_;
return if not $self->_is_my_tag($tag);
my $name = $self->_short_tag_name($tag);
$self->_remove_tag($tag, $ps, $pe)
if (exists $TAGS{$name} and
$TAGS{$name}{Class} eq 'paragraph');
});
for my $tag (@apply) {
$self->_apply_tag_cascade($tag, $ps, $pe);
}
}
# Bounds fetching
sub _get_current_bounds_for_tag {
my $self = shift;
my ($tname) = @_;
if ($TAGS{$tname}{Class} eq 'paragraph') {
return $self->_get_current_paragraph_bounds;