[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Gtk2::Entry with Pango markup



On Tue, Nov 25, 2008 at 2:20 PM, zentara <zentara1 sbcglobal net> wrote:
>
> This is just a buggy prototype of what you might do.
> Manually take control of the Entry and analyze it key-by-key,
> probably with a regex for good xpath syntax,
> and set the appropriate markup and entry text.

I tried using a 'key-press-event' callback and it didn't work.

I think that the problem is related to the cursor blinking. I took a
look at the internals of libsexy which provides a derived GtkEntry
that supports Pango markup. Their widget overrides both the default
'changed' and 'expose-event' action. I was missing the 'expose-event',
once i overrided it I realized that this event is fired constantly
(probably due to the cursor blinking).

The Pango markup seems to be forgotten between the 'expose-events'
that's probably why I could only see it as soon as I start to delete
some characters (while keeping the string invalid).


Here's a working version of a Gtk2::Entry with support for Pango
markup. This particular example wans to receive only ASCII letters any
other character will be marked as invalid though Pango markup.


#!/usr/bin/perl

=head1 NAME

gtk-entry-with-markup.pl - Applies Pango markup to a Gtk2::Entry

=head1 DESCRIPTION

This sample program shows how to apply Pango markup to a Gtk2::Entry. This
particular example considers ASCII letters as being the only valid characters,
any other character will be underlined in red but still accepted by the widget.

=cut

use strict;
use warnings;

use Glib qw(TRUE FALSE);
use Gtk2 '-init';
use Data::Dumper;

my $MARKUP = "";
my %ENTITIES = qw(
	< &lt;
	> &gt;
	& &amp;
);


exit main();


sub main {

	my $window = Gtk2::Window->new();
	my $entry = Gtk2::Entry->new();

	my $vbox = new Gtk2::VBox(FALSE, 0);
	$vbox->pack_start($entry, FALSE, FALSE, FALSE);
	$vbox->set_focus_child($entry);
	$window->add($vbox);


	$entry->signal_connect(changed => \&on_change);
	$entry->signal_connect(expose_event => \&on_expose);

	$window->signal_connect(delete_event => sub { Gtk2->main_quit(); });
	
	$window->show_all();
	Gtk2->main();

	return 0;
}


#
# Each time that the text is changed we validate it. If there's an error within
# the text we use Pango markup to highlight it. The markup seems to be quite
# volatile and will not be always displayed. This is probably due to the
# Gtk2::Entry's cursor which is always blinking. This causes the expose event to
# be fired constantly and the markup seems to be gone. In order to fix this the
# markup has to be saved in a permanent location (a global variable).
#
# This function accepts only letters as input. Any other character will be
# marked as being erroneous.
#
sub on_change {
	my ($widget) = @_;

	my $string = $widget->get_text;

	# Validate the entry's text (accepting only letters)
	$string =~ s/([^a-z]+)/apply_pango_makup($1)/egi;
	$MARKUP = $string;
	$widget->get_layout->set_markup($MARKUP);

	if ($widget->realized) {
		my $size = $widget->allocation;
		my $rectangle = Gtk2::Gdk::Rectangle->new(0, 0, $size->width, $size->height);
		$widget->window->invalidate_rect($rectangle, TRUE);
	}
}


# Set the markup string again, it tends to disappear. This is probably due to
# the blinking cursor. Each blink seems to fire the expose event and the Pango
# markup is gone.
sub on_expose {
	my ($widget, $event) = @_;
	$widget->get_layout->set_markup($MARKUP);
	return FALSE;
}


#
# Applies Pango markup to the given text. The text has the conflicting XML
# characters encoded with entities first.
#
sub apply_pango_makup {
	my ($text) = @_;

	# Escape the XML entities - MUST be done before applying the Pango markup
	$text =~ s/([<&>])/$ENTITIES{$1}/eg;

	# Apply the Pango markup to the escaped text
	return qq(<span underline="error" underline_color="red">$text</span>);
}

-- 
Emmanuel Rodriguez


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]