Re: Word wrap in Textview, how?




On Jul 29, 2005, at 11:18 AM, Yu Wang wrote:

I want to have a textview widget behaves like a simple text editor. The desired right margin at column is 80 characters, and text row with its length larger
than 80 chars will be wrapped back to a new line.

What is the right way to do this?

From what i understand, TextView wraps text at the right edge of the view. That is, where the wrap breaks depends on the width of the widget.

If you want the text to wrap at column 80 regardless of how many columns are visible, then, um, you may have to resort to hackery, like this:


#!/usr/bin/perl -w
use strict;
use Glib ':constants';
use Gtk2 -init;
use Gtk2::Pango;

my $window = Gtk2::Window->new;
my $scroller= Gtk2::ScrolledWindow->new;
my $textview = Gtk2::TextView->new;
my $spinner = Gtk2::SpinButton->new
        (Gtk2::Adjustment->new (40, 1, 999, 1, 10, 100), 1, 0);
my $label = Gtk2::Label->new ('Wrap Column');
my $vbox = Gtk2::VBox->new;
my $hbox = Gtk2::HBox->new;

$window->add ($vbox);
$hbox->pack_start ($label, FALSE, FALSE, 0);
$hbox->pack_start ($spinner, FALSE, FALSE, 0);
$vbox->pack_start ($hbox, FALSE, FALSE, 0);
$vbox->add ($scroller);
$scroller->add ($textview);

# force a monospace font, so that wrapping at a column makes sense.
$textview->modify_font (Gtk2::Pango::FontDescription->from_string ('monospace'));

# on which column do we wrap?
$textview->{wrap_column} = 40;

# wrap on chars, not words.
$textview->set_wrap_mode ('char');

# we need to find the pixel size of a character for this to work right.
# we can get the width from font metrics, but i couldn't get the accurate
# height, so we'll just measure a string.
my $layout = $textview->create_pango_layout ('M');
my (undef, $logical_rect) = $layout->get_pixel_extents;
my $char_width = $logical_rect->{width};
my $char_height = $logical_rect->{height};

# request no smaller than this. since we're overriding with the geometry
# hints, below, this basically gives the window an intiial size.
$textview->set_size_request ($textview->{wrap_column}*$char_width,
                 20 * $char_height);

# here's some black magic.
# if the user shrinks the window so that the view is too narrow to show
# wrap_column columns, then we wrap normally.  if it's wider, we want to
# keep the wrap at wrap_column, and show blank white space for the rest.
# so, in size-allocate, pad the view's right-margin with whatever space
# is left over.
$textview->signal_connect (size_allocate => sub {
    my ($widget, $rectangle) = @_;
    my $wrap_width = $char_width * $widget->{wrap_column};
    $textview->set_right_margin (($rectangle->width > $wrap_width)
                     ? ($rectangle->width - $wrap_width)
                     : 0);
});

# some real fanciness here --- only resize the window in increments of the
# character size.  note: normally you'd omit the flags and let them be
# inferred from the hints hash, but in this case we need to set resize-inc
# forcibly, or the increments don't take effect.
$window->set_geometry_hints ($textview, {
    base_width => $char_width,
    min_width => $char_width,
    width_inc => $char_width,
    base_height => $char_height,
    min_height => $char_height,
    height_inc => $char_height,
}, [qw(resize-inc min-size base-size)]);

# update the wrap_column when the user changes it.
$spinner->get_adjustment->signal_connect (value_changed => sub {
    my ($adj) = @_;
    $textview->{wrap_column} = $adj->get_value;
    $textview->queue_resize;
});


# load some text into the buffer.
my $buffer = $textview->get_buffer;
my $text = `ls -la ~`;
$buffer->insert ($buffer->get_start_iter, $text);

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



--
He's so good, you're gonna rock, and if you don't rock, it's your own fault.
  -- kk, describing the perks of having a very good drummer.




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