One of the users of my Tkx::ROText widget ran into a problem binding it.
use Tkx;
use Tkx::ROText;
my $mw = Tkx::widget->new(".");
my $text = $mw->new_tkx_ROText(-state=>'normal');
$text->g_pack();
Tkx::bind($text, '<Enter>', sub { warn "<Enter>\n" });
Tkx::bind($text, '<Return>', sub { warn "<Return>\n" });
Tkx::MainLoop();
The <Enter> binding works, but the <Return> binding doesn't. The
problem is that Tkx::ROText is really a frame that embeds a text
widget. IIRC the reason for this was that only frames support the
-class option in their constructor and therefore all Tkx mega-widgets
should be frame-based. (Decided via a discussion on this list some
time ago.) It's not really surprising that the <Return> binding
doesn't work because it's attached to the frame but the event happens
inside the text widget -- the frame never sees it.
The work-around is to bind directly to the inner text widget.
Tkx::bind($text . '.text', '<Return>', sub { warn "<Return>\n" });
I have a few problems with this. First, the inner text widget isn't
publicized, so doing it violates encapsulation. (Tangent: Tkx doesn't
provide an equivalent to Perl/Tk's Advertise() and Subwidget()
methods. The best I could do is publically document it.) Second,
binding to the sub-widget forces you to use Tkx::bind() instead of
$text->g_bind(). The forms should be equivalent. Finally, I don't want
users to have to do anything special. Binding should "just work"
without surprises.
Is there a way to make this "just work" in Tkx? Since there's no way
to make the frame see events that happen inside the text widget I'd
have to delegate the binding to the inner text widget. I could try
overriding the g_bind() method in my class but that wouldn't work for
the Tkx::bind() form. Even if it did, all Tkx mega-widgets would have
to do the same thing. A single-point solution within Tkx itself would
be preferable. For this particular case, the cleanest solution would
be for Tkx to call _mpath() on the object being bound to resolve the
delegation, but I don't know how well that would hold universally. It
would also be an abuse of the method's purpose, though I suppose it
could either be documented to do so or Tkx could add a _bpath() method
for that specific purpose.
-mjc