Re: Creating new widgets
- From: "Matthew Braid" <ptkperl mdb id au>
- To: gtk-perl-list gnome org
- Cc: muppet <scott asofyet org>
- Subject: Re: Creating new widgets
- Date: Fri, 13 Oct 2006 11:34:02 +1000
Hi again,
Thanks for that - it's got me on the right track (I think :) ) but I have run into a couple of problems.
As I mentioned before I want the MEF to have the ability to have rows of entries, comboboxes and comboentries. This is defined by the column_types property which is a string of E's (for Entry), C's (for Comboboxes) and c's (for comboentries), which is a creation-time-only setter. So someone could do:
my $mef = My::MEF->new(column_types => 'EEC');
and get a MEF in which each row contains two entries and a combobox. Obviously I haven't gotten to the 'how to set the combobox's models etc' yet, but one step at a time :)
Now, the problem I've hit here is that the column_types property seems to be set _after_ INIT_INSTANCE is called, which means when I'm building the first row (which must always be shown - at the moment I don't enforce that but I will) I don't know what to build.
One workaround I've found is to remove the initial add_row from INIT_INSTANCE and instead put it in the set function for the column_types property. This seems just a tad hacky to me, but does seem to work.
Anyway, below is my code so far. If there are any obvious wrongnesses I'd appreciate pointers :)
MB
use strict;
package My::MEF;
use Glib::Object::Subclass
Gtk2::VBox::,
signals => {row_deleted => {}, # TBC
row_added => {}, # TBC
row_changed => {}}, # TBC
properties =>
[{pspec => (Glib::ParamSpec->
string('column_types', 'Column Types',
('The column types as a string of E, C and c. Each ' .
'character represents an (E)ntry, (C)ombobox or ' .
'(e)ntrycombo. Default is a single entry (E).'),
'E', [qw(readable writable construct-only)])),
set => sub {
my $self = shift;
my ($newval) = @_;
die "Invalid column_types" if $newval !~ /^[ECc]+\z/;
$self->{column_types} = $newval;
$self->add_row if not defined $self->{num_rows};
},
}];
sub INIT_INSTANCE {
my $self = shift;
# Build the initial line
# $self->add_row(undef); MOVED TO column_types set ^
}
#sub GET_PROPERTY {
#}
#sub SET_PROPERTY {
#}
#sub FINALIZE_INSTANCE {
#}
sub add_row {
my $self = shift;
my ($previous) = @_;
my $hbox = Gtk2::HBox->new;
my $entry = Gtk2::Entry->new;
my $add = Gtk2::Button->new("V");
my $del = Gtk2::Button->new("X");
my @ents = $self->_build_entries;
for my $ent (@ents) {
$hbox->pack_start($ent, 1, 1, 0);
}
$hbox->pack_start($add, 0, 0, 0);
$hbox->pack_start($del, 0, 0, 0);
$add->signal_connect(clicked => sub {
my $row = $_[0]->get_parent;
$self->add_row($row);
});
$del->signal_connect(clicked => sub {
my $row = $_[0]->get_parent;
my $box = $row->get_parent;
$box->remove($row);
--$self->{num_rows};
});
my $i = 0;
if (defined $previous) {
for my $c ($self->get_children) {
if ($c == $previous) {
last;
} else {
$i++;
}
}
}
$self->pack_start ($hbox, 0, 0, 0);
$self->reorder_child ($hbox, $i + 1);
$hbox->show_all;
++$self->{num_rows};
return \ ents;
}
sub _build_entries {
my $self = shift;
my @ents;
for my $etype (split //, $self->{column_types}) {
if ($etype eq 'E') {
push @ents, Gtk2::Entry->new;
} elsif ($etype eq 'C') {
# TBC
} elsif ($etype eq 'c') {
#TBC
}
}
return @ents;
}
1;
__END__
On 10/11/06, muppet <scott asofyet org
> wrote:
On Oct 11, 2006, at 1:42 AM, Matthew Braid wrote:
> There's also the possibility of doing the same thing inside a
> ListView with editable cells for the
> entires. But from what I've seen there are problems with combobox/
> entries in listviews, and I haven't seen a cell renderer for buttons.
You'd have to write a CellRendererButton. It's actually not very
hard. Entries are easy (CellRendererText), and as of later versions
of gtk+, so are comboboxes (CellRendererCombo).
> Can anyone point me in the right direction? I can work around this
> but I've found this MEF widget quite handy in the past.
If you're not willing to use a TreeView, then it sounds to me like a
job for boxes and the handy method Gtk2::Container::remove.
Here's a short procedural example. I'll leave turning it into a
flexible and reusable class as an exercise for you. (Things you
could do with it as a class: emit signals when rows are added and
removed, decouple the created widget from the add_row() method so you
can create things other than just entries, etc, etc.)
#!/usr/bin/perl -w
use strict;
use Gtk2 -init;
my $window = Gtk2::Window->new;
$window->signal_connect (destroy => sub { Gtk2->main_quit });
sub add_row {
my ($vbox, $previous) = @_;
my $hbox = Gtk2::HBox->new;
my $entry = Gtk2::Entry->new;
my $add = Gtk2::Button->new ("V");
my $del = Gtk2::Button->new ("X");
$hbox->pack_start ($entry, 1, 1, 0);
$hbox->pack_start ($add, 0, 0, 0);
$hbox->pack_start ($del, 0, 0, 0);
$add->signal_connect (clicked => sub {
my $row = $_[0]->get_parent;
my $box = $row->get_parent;
add_row ($box, $row);
});
$del->signal_connect (clicked => sub {
my $row = $_[0]->get_parent;
my $box = $row->get_parent;
$box->remove ($row);
});
my $i = 0;
if (defined $previous) {
foreach my $c ($vbox->get_children) {
if ($c == $previous) {
last;
} else {
$i++;
}
}
}
$vbox->pack_start ($hbox, 0, 0, 0);
$vbox->reorder_child ($hbox, $i+1);
$hbox->show_all;
return $entry;
}
my $box = Gtk2::VBox->new;
add_row ($box, undef);
$window->add ($box);
$window->show_all;
Gtk2->main;
__END__
--
Without treatment, a common cold will last about seven days.
With treatment, it will last about a week.
-- conventional wisdom
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]