summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Tk/mega.pod
blob: 76e40e7891f4567d75eb1d71c424defd2280d55e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

## Author: Achim Bohnet <ach@mpe.mpg.de>
##
## Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.
## You can redistribute this document and/or modify it under the
## same terms as Perl itself.
##
## Update for Tk804.025, Steve Lidie, 2004/01/11.

=head1 NAME

Tk::mega - Perl/Tk support for writing widgets in pure Perl

=for category Derived Widgets

=head1 SYNOPSIS

Define the widget's new class name:

S<    >B<package Tk::>I<MyNewWidget>;

For composite widget classes:

S<    >B<use base qw/ Tk::container />; # where B<container> is I<Frame> or I<Toplevel>

For derived widget classes:

S<    >B<use base qw/ Tk::Derived Tk::DerivedWidget /;>

Install the new widget in Tk's namespace and establish class and instance
constructors.

S<    >B<Construct Tk::>I<Widget> I<'MyNewWidget'>;

S<    >B<sub ClassInit> { I<my ($self, $args) = @_; ...> }

S<    >B<sub Populate> { I<my ($self, $args) = @_; ...> }

=head1 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.
I<For mega-widget sample code please run the B<widget> demonstration program and go to the section B<Sample Perl Mega-Widgets>.>

There are two kinds of mega-widgets:

=over 4

=item * 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.

=item * Derived Widgets

A derived widget adds/modifies/removes properties and methods
from a single widget (this widget may itself be a mega-widget).

=back

=head1 MEGA-WIDGET SUPPORT

=head2 Advertise

Give a subwidget a symbolic name.

Usage:

S<    >I<$self>-E<gt>B<Advertise>(B<name>=E<gt>I<$widget>);

Gives a subwidget I<$widget> of the mega-widget I<$self> the
name B<name>.  One can retrieve the reference of an advertised subwidget
with the L<Subwidget|"Subwidget"> method.

B<Comment:> Mega-Widget Writers: Please make sure to document the
advertised widgets that are intended for I<public> use.
If there are none, document this fact, e.g.:

	=head1 ADVERTISED WIDGETS

	None.

=head2 Callback

Invoke a callback specified with an option.

Usage:

S<    >I<$self>-E<gt>B<Callback>(I<-option> ?,I<args> ...?);

B<Callback> executes the L<callback|Tk::callbacks> defined with
I<$self>-E<gt>B<ConfigSpecs>(I<-option>, [B<CALLBACK>, ...]);
If I<args> are given they are passed to the callback. If
I<-option> is not defined it does nothing.

=head2 ClassInit

Initialization of the mega-widget class.

Usage:

S<    >B<sub ClassInit> { I<my ($class, $mw) = @_;> ...  }

B<ClassInit> is called once for I<each> L<MainWindow|Tk::MainWindow>
just before the first widget instance of a class is created in
the widget tree of B<MainWindow>.

B<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 I<$class> is the class name (e.g. B<Tk::MyText>) and I<$mw> is the mainwindow.

Don't forget to call I<$class>-E<gt>B<SUPER::ClassInit($mw)> in
B<ClassInit>.

=head2 Component

Convenience function to create subwidgets.

Usage:

    $cw->Component('Whatever', 'AdvertisedName',
        -delegate => ['method1', 'method2', ...],
        ... more widget options ...,
    );

B<Component> does several things for you with one call:

=over 4

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)

=back

Example:

    $cw->Component('Button', 'quitButton', -command => sub{$mw->'destroy'});

=head2 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 L<Tk::ConfigSpecs> and L<Tk::Derived> for details).

=head2 Construct

Make the new mega-widget known to B<Tk>.

Usage:

S<    >B<Construct> I<baseclass> B<'Name'>;

B<Construct> declares the new widget class so that your mega-widget
works like normal Perl/Tk widgets.

Examples:

S<    >B<Construct Tk::Widget> I<'Whatever'>;
S<    >B<Construct Tk::Menu>   I<'MyItem'>;

First example lets one use I<$widget>-E<gt>B<Whatever> to create
new B<Whatever> widget.

The second example restricts the usage of the B<MyItem> constructor
method to widgets that are derived from B<Menu>:
I<$isamenu>-E<gt>I<MyItem>.

=head2 CreateArgs

Process options before any widget is created:

S<    >B<sub CreateArgs> { I<my ($package, $parent, $args) = @_; ...; return @newargs;> }

I<$package> is the package of the mega-widget (e.g., B<Tk::MyText>,
I<$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 I<$package>-E<gt>B<SUPER::CreateArgs>(I<$parent>, I<$args>) in
B<CreateArgs>.

=head2 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 B<'Construct'> delegation has a special meaning.  After
'Construct' is delegated all Widget constructors are redirected.
E.g. after

S<    >I<$self>-E<gt>B<Delegates>(B<'Construct'>=E<gt>I<$subframe>);

a I<$self>-E<gt>B<Button> does really a I<$subframe>-E<gt>B<Button>
so the created button is a child of I<$subframe> and not I<$self>.

B<Comment:> Delegates works only with methods that I<$cw> does
not have itself.

=head2 InitObject

I<Note: this method should not, in general, be used, as it has been
superceeded by B<Populate> and specifying B<Tk::Derived> as one of the base
classes.>

Defines construction and interface of derived widgets.

Usage:

    sub InitObject {
	my ($derived, $args) = @_;
	...
    }

where I<$derived> is the widget reference of the already created
baseclass widget and I<$args> is the reference to a hash of
I<-option-value> pairs.

B<InitObject> is almost identical to L<Populate|"Populate"> method.
B<Populate> does some more 'magic' things useful for mega-widgets
with several widgets.

Don't forget to call I<$derived>-E<gt>B<SUPER::InitObject>(I<$args>) in
B<InitObject>.

=head2 OnDestroy

Define a callback invoked when the mega-widget is destroyed.

Usage:

S<    >I<$widget>-E<gt>B<OnDestroy>(I<callback>);

B<OnDestroy> installs a L<callback|Tk::callbacks> that's called
when a widget is going to to be destroyed.  Useful
for special cleanup actions.  It differs from a normal B<destroy>
in that all the widget's data structures are still intact.

B<Comment:> This method could be used with any widgets not just
for mega-widgets.  It's listed here because of it's usefulness.

=head2 Populate

Defines construction and interface of the composite
widget.

Usage:

    sub Populate {
	my ($self, $args) = @_;
	...
    }

where I<$self> is the widget reference of the already created baseclass
widget and I<$args> is the
reference to a hash of I<-option-value> pairs.

Most the other support function are normally used inside the B<Populate>
subroutine.

Don't forget to call I<$cw>-E<gt>B<SUPER::Populate>(I<$args>) in
B<Populate>.

=head2 privateData

Set/get a private hash of a widget to storage
composite internal data

Usage:

S<    >I<$hashref> = I<$self>-E<gt>B<privateData>();

S<    >I<$another> = I<$self>-E<gt>B<privateData>(I<unique_key>|I<package>);

=head2 Subwidget

Get the widget reference of an advertised subwidget.

S<    >I<@subwidget> = I<$cw>-E<gt>B<Subwidget>();

S<    >I<$subwidget> = I<$cw>-E<gt>B<Subwidget>(I<name>);

S<    >I<@subwidget> = I<$cw>-E<gt>B<Subwidget>(I<name> ?,...?);

Returns the widget reference(s) of the subwidget known under the given
name(s). Without arguments, return all known subwidgets of I<$cw>. See
L<Advertise|"Advertise"> method how to define I<name> for a subwidget.

B<Comment:> Mega-Widget Users: Use B<Subwidget> to get I<only>
documented subwidgets.

=head1 PITFALLS

=over 4

=item * 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 B<ConfigSpecs>.

=item * Method delegation

Redirecting methods to a subwidget with B<Delegate>
can only work if the base widget itself does have a
method with this name.  Therefore one can't ``I<delegate>''
any of the methods listed in L<Tk::Widget|Tk::Widget>.
A common problematic method is B<bind>.  In this case
one as to explicitely redirect the method.

  sub bind {
      my $self = shift;
      my $to = $self->privateData->{'my_bind_target'};
      $to->bind(@_);
  }

=item * 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.

=item * Scrolled and Composite

B<Scrolled>(I<Kind>,...) constructor can not be used with B<Composite>.
One has to use $cw->B<Composite>(B<Scrl>I<Kind> =E<gt> B<'name'>, ...);

=back

=head1 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:

=over 4

=item *

No support to define construction-time only options.

=item *

No support to remove an option that is known to the
base widget.

=item *

It's hard to define B<undef> as fallback for an widget
option that is not already B<undef>.

=item *

Frame in Perl/Tk carries magic and overhead not needed
for composite widget class definition.

=item *

No support methods for bindings that are shared between all
widgets of a composite widget (makes sense at all?)

=back

=head1 KEYWORDS

mega, composite, derived, widget

=head1 SEE ALSO

L<Tk::composite|Tk::composite>
L<Tk::ConfigSpecs|Tk::ConfigSpecs>
L<Tk::option|Tk::option>
L<Tk::callbacks|Tk::callbacks>
L<Tk::bind|Tk::bind>

=cut