NAME¶
Tk::mega - Perl/Tk support for writing widgets in pure Perl
SYNOPSIS¶
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).
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,
[
CALLBACK, ...]); If
args are given they are passed to the
callback. If
-option is not defined it does nothing.
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 treatment
Usage:
$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 widget
Usage:
$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 data
Usage:
$hashref =
$self ->
privateData();
$another =
$self
->
privateData(
unique_key|
package);
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 DB class 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 HASH reference. The
HASH reference that is returned depends on the package it was called from,
a different HASH is 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
different HASH and so not cause duplicate name clashes.
But privateData does take an optional argument if you want to force which
HASH is 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?)
KEYWORDS¶
mega, composite, derived, widget
SEE ALSO¶
Tk::composite Tk::ConfigSpecs Tk::option Tk::callbacks Tk::bind