Tk::mega (3)
Leading comments
Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) Standard preamble: ========================================================================
NAME
Tk::mega - Perl/Tk support for writing widgets in pure PerlSYNOPSIS
Define the widget's new class name:package Tk::MyNewWidget;
For composite widget classes:
use base qw/ Tk::container /; # where container is Frame or Toplevel
For derived widget classes:
use base qw/ Tk::Derived Tk::DerivedWidget /;
Install the new widget in Tk's namespace and establish class and instance constructors.
Construct Tk::Widget 'MyNewWidget';
sub ClassInit { my ($self, $args) = @_; ... }
sub Populate { my ($self, $args) = @_; ... }
DESCRIPTION
The goal of the mega-widget support of Perl/Tk is to make it easy to write mega-widgets that obey the same protocol and interface that the Tk core widgets support. For mega-widget sample code please run the widget demonstration program and go to the section Sample Perl Mega-Widgets.There are two kinds of mega-widgets:
- *
-
Composite Widgets
A composite widget is composed with one or more existing widgets. The composite widget looks to the user like a simple single widget. A well known example is the file selection box.
- *
-
Derived Widgets
A derived widget adds/modifies/removes properties and methods from a single widget (this widget may itself be a mega-widget).
MEGA-WIDGET SUPPORT
Advertise
Give a subwidget a symbolic name.Usage:
$self->Advertise(name=>$widget);
Gives a subwidget $widget of the mega-widget $self the name name. One can retrieve the reference of an advertised subwidget with the Subwidget method.
Comment: Mega-Widget Writers: Please make sure to document the advertised widgets that are intended for public use. If there are none, document this fact, e.g.:
=head1 ADVERTISED WIDGETS None.
Callback
Invoke a callback specified with an option.Usage:
$self->Callback(-option ?,args ...?);
Callback executes the callback defined with $self->ConfigSpecs(-option, [
ClassInit
Initialization of the mega-widget class.Usage:
sub ClassInit { my ($class, $mw) = @_; ... }
ClassInit is called once for each MainWindow just before the first widget instance of a class is created in the widget tree of MainWindow.
ClassInit is often used to define bindings and/or other resources shared by all instances, e.g., images.
Examples:
$mw->bind($class,"<Tab>", sub { my $w = shift; $w->Insert("\t"); $w->focus; $w->break}); $mw->bind($class,"<Return>", ['Insert',"\n"]); $mw->bind($class,"<Delete>",'Delete');
Notice that $class is the class name (e.g. Tk::MyText) and $mw is the mainwindow.
Don't forget to call $class->SUPER::ClassInit($mw) in ClassInit.
Component
Convenience function to create subwidgets.Usage:
$cw->Component('Whatever', 'AdvertisedName', -delegate => ['method1', 'method2', ...], ... more widget options ..., );
Component does several things for you with one call:
-
o Creates the widget
o Advertises it with a given name (overridden by 'Name' option)
o Delegates a set of methods to this widget (optional)
Example:
$cw->Component('Button', 'quitButton', -command => sub{$mw->'destroy'});
ConfigSpecs
Defines options and their treatmentUsage:
$cw->ConfigSpecs( -option => [ where, dbname, dbclass, default], ..., DEFAULT => [where], );
Defines the options of a mega-widget and what actions are triggered by configure/cget of an option (see Tk::ConfigSpecs and Tk::Derived for details).
Construct
Make the new mega-widget known to Tk.Usage:
Construct baseclass 'Name';
Construct declares the new widget class so that your mega-widget works like normal Perl/Tk widgets.
Examples:
Construct Tk::Widget 'Whatever'; Construct Tk::Menu 'MyItem';
First example lets one use $widget->Whatever to create new Whatever widget.
The second example restricts the usage of the MyItem constructor method to widgets that are derived from Menu: $isamenu->MyItem.
CreateArgs
Process options before any widget is created:sub CreateArgs { my ($package, $parent, $args) = @_; ...; return @newargs; }
$package is the package of the mega-widget (e.g., Tk::MyText, $parent the parent of the widget to be created and $args the hash reference to the options specified in the widget constructor call.
Don't forget to call $package->SUPER::CreateArgs($parent, $args) in CreateArgs.
Delegates
Redirect a method of the mega-widget to a subwidget of the composite widgetUsage:
$cw->Delegates( 'method1' => $subwidget1, 'method2' => 'advertived_name', ..., 'Construct' => $subwidget2, 'DEFAULT' => $subwidget3, );
The 'Construct' delegation has a special meaning. After 'Construct' is delegated all Widget constructors are redirected. E.g. after
$self->Delegates('Construct'=>$subframe);
a $self->Button does really a $subframe->Button so the created button is a child of $subframe and not $self.
Comment: Delegates works only with methods that $cw does not have itself.
InitObject
Note: this method should not, in general, be used, as it has been superceeded by Populate and specifying Tk::Derived as one of the base classes.Defines construction and interface of derived widgets.
Usage:
sub InitObject { my ($derived, $args) = @_; ... }
where $derived is the widget reference of the already created baseclass widget and $args is the reference to a hash of -option-value pairs.
InitObject is almost identical to Populate method. Populate does some more 'magic' things useful for mega-widgets with several widgets.
Don't forget to call $derived->SUPER::InitObject($args) in InitObject.
OnDestroy
Define a callback invoked when the mega-widget is destroyed.Usage:
$widget->OnDestroy(callback);
OnDestroy installs a callback that's called when a widget is going to to be destroyed. Useful for special cleanup actions. It differs from a normal destroy in that all the widget's data structures are still intact.
Comment: This method could be used with any widgets not just for mega-widgets. It's listed here because of it's usefulness.
Populate
Defines construction and interface of the composite widget.Usage:
sub Populate { my ($self, $args) = @_; ... }
where $self is the widget reference of the already created baseclass widget and $args is the reference to a hash of -option-value pairs.
Most the other support function are normally used inside the Populate subroutine.
Don't forget to call $cw->SUPER::Populate($args) in Populate.
privateData
Set/get a private hash of a widget to storage composite internal dataUsage:
$hashref = $self->privateData();
$another = $self->privateData(unique_key|package);
Subwidget
Get the widget reference of an advertised subwidget.@subwidget = $cw->Subwidget();
$subwidget = $cw->Subwidget(name);
@subwidget = $cw->Subwidget(name ?,...?);
Returns the widget reference(s) of the subwidget known under the given name(s). Without arguments, return all known subwidgets of $cw. See Advertise method how to define name for a subwidget.
Comment: Mega-Widget Users: Use Subwidget to get only documented subwidgets.
PITFALLS
- *
-
Resource DBclass name
Some of the standard options use a resource date base class that is not equal to the resource database name. E.g.,
Switch: Name: Class: -padx padX Pad -activerelief activeRelief Relief -activebackground activeBackground Foreground -status undef undef
One should do the same when one defines one of these options via ConfigSpecs.
- *
-
Method delegation
Redirecting methods to a subwidget with Delegate can only work if the base widget itself does have a method with this name. Therefore one can't ``delegate'' any of the methods listed in Tk::Widget. A common problematic method is bind. In this case one as to explicitly redirect the method.
sub bind { my $self = shift; my $to = $self->privateData->{'my_bind_target'}; $to->bind(@_); }
- *
-
privateData
Graham Barr wrote: ... It is probably more private than most people think. Not all calls to privateData will return that same
HASHreference. TheHASHreference that is returned depends on the package it was called from, a differentHASHis returned for each package. This allows a widget to hold private data, but then if it is sub-classed the sub-class will get a differentHASHand so not cause duplicate name clashes.But privateData does take an optional argument if you want to force which
HASHis returned. - *
-
Scrolled and Composite
Scrolled(Kind,...) constructor can not be used with Composite. One has to use $cw->Composite(ScrlKind => 'name', ...);
MISSING
Of course Perl/Tk does not define support function for all necessities. Here's a short list of things you have to handle yourself:- *
- No support to define construction-time only options.
- *
- No support to remove an option that is known to the base widget.
- *
- It's hard to define undef as fallback for an widget option that is not already undef.
- *
- Frame in Perl/Tk carries magic and overhead not needed for composite widget class definition.
- *
- No support methods for bindings that are shared between all widgets of a composite widget (makes sense at all?)