Subject: | Megawidget method delegation ignores overrides |
Tkx has some problems when delegating method calls from one megawidget
to another megawidget.
I'm trying to create a Tkx equivalent for Perl/Tk's Scrolled megawidget.
The basic design is a frame-based megawidget that embeds a widget of a
user-defined type. I want to delegate all method calls to that subwidget
so I override the _mpath() method to do so. For a built-in text widget
everything appears to work properly. e.g. I can call the insert() method
on my megawidget and the text is added to the subwidget. When I embed a
Tkx::ROText widget the text is *not* added. It appears that Tkx is
calling the Tcl insert method (which has been stubbed to do nothing)
instead of the Perl method. The key bit of code appears to be line 165
of Tkx.pm:
return scalar(Tkx::i::call($self->_mpath($i[0]), @i, @_));
This is as close as I get to my insert method. I never make it to the
overridden definition in Tkx::ROText. I need to call the method in
$i[0] on the Perl widget named $self->_mpath but there's no reference,
just a name. Is there any way to get the object reference from the name?
I've noticed that Tkx has no equivilent of Perl/Tk's Advertise() and
Subwidget() methods.
In my particular case the problem is partially due to the tricks I play
to make the widget readonly (renaming the Tcl widget and stubbing the
insert and delete methods for the original name) but the core problem
remains. For example, if I add a "blurb" method to Tkx::ROText I can't
call it via Scrolled:
bad option "blurb": must be bbox, cget, compare...
Here's a fairly small example that demonstrates the problem; hopefully
RT doesn't mangle it too badly...
use strict;
use warnings;
package Tkx::Scrolled;
use Tkx;
use base qw(Tkx::widget Tkx::MegaConfig);
__PACKAGE__->_Mega('tkx_Scrolled');
sub _Populate {
my $class = shift;
my $widget = shift;
my $path = shift;
my $type = shift;
my %opt = @_;
my $self = $class->new($path)->_parent->new_frame(-name => $path);
$self->_class($class);
my $new_thing = "new_$type";
my $w = $self->$new_thing(-name => 'scrolled', %opt);
$w->g_pack();
return $self;
}
sub _mpath { $_[0] . '.scrolled' }
package main;
use Tkx;
use Tkx::ROText;
my $mw = Tkx::widget->new('.');
my $text = $mw->new_tkx_Scrolled('tkx_ROText'); # 'text' works fine
$text->g_pack();
$text->insert('end', 'Fee Fie Fo Fum');
Tkx::MainLoop();