Forcing TreeView column widths while still allowing user resizing



Hi all,

I'm writing an application that is similar to a mail client. There are
multiple 'boxes', and each box shares a common TreeView. Each box
should behave as if it has separate treeviews - when a box is selected
it sets its stored state back to the TreeView like contents,
selection, viewable position etc etc.

One thing I have yet to get working is column widths. Columns MUST be
user-resizable, and I'd like to force the TreeView to _not_ autoresize
while its loading data but to instead keep its columns fixed to the
size stored in the box's state, but then once loading is complete
allow the user to resize at will.

This for some reason is not straightforward.

I've built a quick test harness for testing. The following code will
build a treeview and a command entry. Commands can be entered and once
RUN is hit those commands are then eval'd so you can see the effects
of different code:

---START TEST HARNESS

use strict;
use Gtk2 '-init';
my $mw = Gtk2::Window->new;
my $tbl = Gtk2::Table->new(2, 2, 0);
my $lst = Gtk2::TreeView->new;
my $ent = Gtk2::Entry->new;
my $but = Gtk2::Button->new('RUN');
my $mod = Gtk2::ListStore->new('Glib::String', 'Glib::String', 'Glib::String');
my @col = (['One', 0], ['Two', 1], ['Three', 2]);
$mw->add($tbl);
$tbl->attach($lst, 0, 2, 0, 1, [qw/fill expand/], [qw/fill expand/], 0, 0);
$tbl->attach($ent, 0, 1, 1, 2, [qw/fill expand/], [], 0, 0);
$tbl->attach($but, 1, 2, 1, 2, [], [], 0, 0);
$but->signal_connect(clicked => sub {
                       my $com = $ent->get_text;
                       eval { eval $com };
                       print "ERROR IS $ \n" if $@;
                       0;
                     });
$mw->signal_connect('delete-event' => sub { exit });
$lst->set_model($mod);
for my $col (@col) {
  my ($title, $textcol) = @$col;
  my $rend = Gtk2::CellRendererText->new;
  $rend->set('family', 'Monospace', 'size-points', 9);
  $col = Gtk2::TreeViewColumn->new_with_attributes($title, $rend);
  $col->set(clickable => 1, reorderable => 1,
            resizable => 1, spacing => 0);
  $col->set_sort_column_id($textcol);
  $col->add_attribute($rend, 'text', $textcol);
  $lst->append_column($col);
}
$mw->show_all;
Gtk2->main;

---END TEST HARNESS

OK, so far I've tried two methods.

Method A involves setting the min and max widths for each column to
the stored width, adding data and then resetting the min/max width to
10/2048 respectively like so: (NOTE: the 'updates' with
Gtk2->main_iteration are necessary for this to work - without them its
like I never set the min/max to the stored value at all)

---START METHOD 1

$mod->clear;
for my $c (@col) {
  $c->set_min_width(20);
  $c->set_max_width(20);
  Gtk2->main_iteration while Gtk2->events_pending;
}
$mod->set($mod->append, 0, 'AAAAAAAAAAAAAAAAAAAAAA',
                        1, 'BBBBBBBBBBBBBBBBBBBBBB',
                        2, 'CCCCCCCCCCCCCCCCCCCCCC');
Gtk2->main_iteration while Gtk2->events_pending;
for my $c (@col) {
  $c->set_min_width(10);
  $c->set_max_width(2048);
  Gtk2->main_iteration while Gtk2->events_pending;
}

---END METHOD 1

Entering that into the entry in the test harness and hitting RUN shows
that the columns (except the last one, which expands to fill the
window) are indeed staying at 20 pixels wide. This appears to have
worked - until you try to resize column One or Two. Suddenly both
column One and column Two auto-resize, and if you were resizing column
Two it shrinks to 10 pixels because the mouse is now far left of its
left hand side. Sigh.

So I gave method 2 a try: setting the columns to fixed-width mode,
loading the data and then setting the columns back to autosize mode:

---START METHOD 2

$mod->clear;
for my $c (@col) {
  $c->set_fixed_width(20);
  $c->set_sizing('fixed');
  Gtk2->main_iteration while Gtk2->events_pending;
}
$mod->set($mod->append, 0, 'AAAAAAAAAAAAAAAAAAAAAA',
                        1, 'BBBBBBBBBBBBBBBBBBBBBB',
                        2, 'CCCCCCCCCCCCCCCCCCCCCC');
  Gtk2->main_iteration while Gtk2->events_pending;
for my $c (@col) {
  $c->set_sizing('autosize');
  Gtk2->main_iteration while Gtk2->events_pending;
}

---END METHOD 2

(I should also point out that $mod->clear seems to completely destroy
any sizing information in the columns).

This obviously doesn't work at all - I'm assuming the
$c->set_sizing('autosize') doesn't just set the flag, but also tells
the view to autosize all its columns _right now_.

What I _did_ notice though is that if the user ever does resize a
column the view stops auto-sizing that column. So I'm wondering, is
there a way to tell the view to allow the user to resize the columns,
but to not autosize itself (or to pretend that the user has manually
fiddled with the column)? I note that columns have 3 resize modes -
fixed, autosize and grow-only. Should there be a 'none' or 'user' mode
as well?!

It might also be important to add that the real application loads its
data 'in the background' using an idle timer - it loads some data
(possibly doing the main_iteration while events_pending thing) then
waits for the next idle time to load more. In other words, there may
or may not be calls to Gtk2->main_iteration during the data load. Not
sure if this throws a monkey wrench into things, but there you go.

TIA,
MB



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