Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | |
2 | ## Author: Achim Bohnet <ach@mpe.mpg.de> | |
3 | ## | |
4 | ## Copyright (c) 1997-1998 Achim Bohnet. All rights reserved. | |
5 | ## You can redistribute this document and/or modify it under the | |
6 | ## same terms as Perl itself. | |
7 | ||
8 | =head1 NAME | |
9 | ||
10 | Tk::mega - perl/Tk support to write widgets in perl | |
11 | ||
12 | =for category Derived Widgets | |
13 | ||
14 | =head1 SYNOPSIS | |
15 | ||
16 | S< >B<package Tk::>I<Whatever>; | |
17 | ||
18 | S< >B<Construct Tk::>I<ValidFor> I<'Whatever'>; | |
19 | ||
20 | S< >B<sub ClassInit> { I<my ($mega, $args) = @_; ...> } | |
21 | ||
22 | For composite widget classes: | |
23 | ||
24 | S< >B<sub Populate> { I<my ($composite, $args) = @_; ...> } | |
25 | ||
26 | For derived widget classes: | |
27 | ||
28 | S< >B<sub InitObject> { I<my ($derived, $args) = @_; ...> } | |
29 | ||
30 | =head1 DESCRIPTION | |
31 | ||
32 | The goal of the mega widget support of perl/Tk is to make it | |
33 | easy to write mega widgets that obey the same protocol and | |
34 | interface that the Tk core widgets support. There are two | |
35 | kinds of mega widgets: | |
36 | ||
37 | =over 4 | |
38 | ||
39 | =item * Composite Widgets | |
40 | ||
41 | A composite widget is composed with one or more existing widgets. | |
42 | The composite widget looks to the user like a simple single widget. | |
43 | A well known example is the file selection box. | |
44 | ||
45 | =item * Derived Widgets | |
46 | ||
47 | A derived widget adds/modifies/removes properties and methods | |
48 | from a single widget (this widget may itself be a mega widget). | |
49 | ||
50 | =back | |
51 | ||
52 | =head1 MEGA WIDGET SUPPORT | |
53 | ||
54 | =head2 Advertise | |
55 | ||
56 | Give a subwidget a symbolic name. | |
57 | ||
58 | Usage: | |
59 | ||
60 | S< >I<$cw>-E<gt>B<Advertise>(B<name>=E<gt>I<$widget>); | |
61 | ||
62 | Gives a subwidget I<$widget> of the composite widget I<$cw> the | |
63 | name B<name>. One can retrieve the reference of an advertised subwidget | |
64 | with the L<Subwidget|"Subwidget"> method. | |
65 | ||
66 | B<Comment:> Mega Widget Writers: Please make sure to document the | |
67 | advertised widgets that are intended for I<public> use. | |
68 | If there are none, document this fact, e.g.: | |
69 | ||
70 | =head1 ADVERTISED WIDGETS | |
71 | ||
72 | None. | |
73 | ||
74 | =head2 Callback | |
75 | ||
76 | Invoke a callback specified with an option. | |
77 | ||
78 | Usage: | |
79 | ||
80 | S< >I<$mega>-E<gt>B<Callback>(I<-option> ?,I<args> ...?); | |
81 | ||
82 | B<Callback> executes the L<callback|Tk::callbacks> defined with | |
83 | I<$mega>-E<gt>B<ConfigSpecs>(I<-option>, [B<CALLBACK>, ...]); | |
84 | If I<args> are given they are passed to the callback. If | |
85 | I<-option> is not defined it does nothing. | |
86 | ||
87 | =head2 ClassInit | |
88 | ||
89 | Initialization of the mega widget class. | |
90 | ||
91 | Usage: | |
92 | ||
93 | S< >B<sub ClassInit> { I<my ($class, $mw) = @_;> ... } | |
94 | ||
95 | B<ClassInit> is called once for I<each> L<MainWindow|Tk::MainWindow> | |
96 | just before the first widget instance of a class is created in | |
97 | the widget tree of B<MainWindow>. | |
98 | ||
99 | B<ClassInit> is often used to define bindings and/or other | |
100 | resources shared by all instances, e.g., images. | |
101 | ||
102 | Examples: | |
103 | ||
104 | $mw->bind($class,"<Tab>", sub { my $w = shift; $w->Insert("\t"); $w->focus; $w->break}); | |
105 | $mw->bind($class,"<Return>", ['Insert',"\n"]); | |
106 | $mw->bind($class,"<Delete>",'Delete'); | |
107 | ||
108 | Notice that I<$class> is the class name (e.g. B<Tk::MyText>) and I<$mw> is the mainwindow. | |
109 | ||
110 | Don't forget to call I<$class>-E<gt>B<SUPER::ClassInit($mw)> in | |
111 | B<ClassInit>. | |
112 | ||
113 | =head2 Component | |
114 | ||
115 | Convenience function to create subwidgets. | |
116 | ||
117 | Usage: | |
118 | ||
119 | $cw->Component('Whatever', 'AdvertisedName', | |
120 | -delegate => ['method1', 'method2', ...], | |
121 | ... Whatever widget options ..., | |
122 | ); | |
123 | ||
124 | B<Component> does several things for you with one call: | |
125 | ||
126 | =over 4 | |
127 | ||
128 | o Creates the widget | |
129 | ||
130 | o Advertises it with a given name (overridden by 'Name' option) | |
131 | ||
132 | o Delegates a set of methods to this widget (optional) | |
133 | ||
134 | =back | |
135 | ||
136 | Example: | |
137 | ||
138 | $cw->Component('Button', 'quitButton', -command => sub{$mw->'destroy'}); | |
139 | ||
140 | =head2 ConfigSpecs | |
141 | ||
142 | Defines options and their treatment | |
143 | ||
144 | Usage: | |
145 | ||
146 | $cw->ConfigSpecs( | |
147 | -option => [ where, dbname, dbclass, default], | |
148 | ..., | |
149 | DEFAULT => [where], | |
150 | ); | |
151 | ||
152 | Defines the options of a mega widget and what actions | |
153 | are triggered by configure/cget of an option | |
154 | (see L<Tk::ConfigSpecs> and L<Tk::Derived> for details). | |
155 | ||
156 | =head2 Construct | |
157 | ||
158 | Make the new mega widget known to B<Tk>. | |
159 | ||
160 | Usage: | |
161 | ||
162 | S< >B<Construct> I<baseclass> B<'Name'>; | |
163 | ||
164 | B<Construct> declares the new widget class so that your mega widget | |
165 | works like normal Perl/Tk widgets. | |
166 | ||
167 | Examples: | |
168 | ||
169 | S< >B<Construct Tk::Widget> I<'Whatever'>; | |
170 | S< >B<Construct Tk::Menu> I<'MyItem'>; | |
171 | ||
172 | First example lets one use I<$widget>-E<gt>B<Whatever> to create | |
173 | new B<Whatever> widget. | |
174 | ||
175 | The second example restricts the usage of the B<MyItem> constructor | |
176 | method to widgets that are derived from B<Menu>: | |
177 | I<$isamenu>-E<gt>I<MyItem>. | |
178 | ||
179 | =head2 CreateArgs | |
180 | ||
181 | Mess with options before any widget is created | |
182 | ||
183 | S< >B<sub CreateArgs> { I<my ($package, $parent, $args) = @_; ...; return @newargs;> } | |
184 | ||
185 | I<$package> is the package of the mega widget (e.g., B<Tk::MyText>, | |
186 | I<$parent> the parent of the widget to be created and $args the hash | |
187 | reference to the options specified in the widget constructor call. | |
188 | ||
189 | Don't forget to call I<$package>-E<gt>B<SUPER::CreateArgs>(I<$parent>, I<$args>) in | |
190 | B<CreateArgs>. | |
191 | ||
192 | =head2 Delegates | |
193 | ||
194 | Redirect a method of the mega widget to a subwidget of | |
195 | the composite widget | |
196 | ||
197 | Usage: | |
198 | ||
199 | $cw->Delegates( | |
200 | 'method1' => $subwidget1, | |
201 | 'method2' => 'advertived_name', | |
202 | ..., | |
203 | 'Construct' => $subwidget2, | |
204 | 'DEFAULT' => $subwidget3, | |
205 | ); | |
206 | ||
207 | The B<'Construct'> delegation has a special meaning. After | |
208 | 'Construct' is delegated all Widget constructors are redirected. | |
209 | E.g. after | |
210 | ||
211 | S< >I<$mega>-E<gt>B<Delegates>(B<'Construct'>=E<gt>I<$subframe>); | |
212 | ||
213 | a I<$mega>-E<gt>B<Button> does really a I<$subframe>-E<gt>B<Button> | |
214 | so the created button is a child of I<$subframe> and not I<$mega>. | |
215 | ||
216 | B<Comment:> Delegates works only with methods that I<$cw> does | |
217 | not have itself. | |
218 | ||
219 | =head2 InitObject | |
220 | ||
221 | Defines construction and interface of derived widgets. | |
222 | ||
223 | Usage: | |
224 | ||
225 | sub InitObject { | |
226 | my ($derived, $args) = @_; | |
227 | ... | |
228 | } | |
229 | ||
230 | where I<$derived> is the widget reference of the already created | |
231 | baseclass widget and I<$args> is the reference to a hash of | |
232 | I<-option-value> pairs. | |
233 | ||
234 | B<InitObject> is almost identical to L<Populate|"Populate"> method. | |
235 | B<Populate> does some more 'magic' things useful for mega widgets | |
236 | with several widgets. | |
237 | ||
238 | Don't forget to call I<$derived>-E<gt>B<SUPER::InitObject>(I<$args>) in | |
239 | B<InitObject>. | |
240 | ||
241 | =head2 OnDestroy | |
242 | ||
243 | Define callback invoked when widget is destroyed. | |
244 | ||
245 | Usage: | |
246 | ||
247 | S< >I<$widget>-E<gt>B<OnDestroy>(I<callback>); | |
248 | ||
249 | B<OnDestroy> installs a L<callback|Tk::callbacks> that's called | |
250 | when a widget is going to to be destroyed. Useful | |
251 | for special cleanup actions. It differs from a normal B<destroy> | |
252 | in that all the widget's data structures are still intact. | |
253 | ||
254 | B<Comment:> This method could be used with any widgets not just | |
255 | for mega widgets. It's listed here because of it's usefulness. | |
256 | ||
257 | =head2 Populate | |
258 | ||
259 | Defines construction and interface of the composite | |
260 | widget. | |
261 | ||
262 | Usage: | |
263 | ||
264 | sub Populate { | |
265 | my ($mega, $args) = @_; | |
266 | ... | |
267 | } | |
268 | ||
269 | where I<$mega> is the widget reference of the already created baseclass | |
270 | widget and I<$args> is the | |
271 | reference to a hash of I<-option-value> pairs. | |
272 | ||
273 | Most the other support function are normally used inside the B<Populate> | |
274 | subroutine. | |
275 | ||
276 | Don't forget to call I<$cw>-E<gt>B<SUPER::Populate>(I<$args>) in | |
277 | B<Populate>. | |
278 | ||
279 | =head2 privateData | |
280 | ||
281 | Set/get a private hash of a widget to storage | |
282 | composite internal data | |
283 | ||
284 | Usage: | |
285 | ||
286 | S< >I<$hashref> = I<$mega>-E<gt>B<privateData>(); | |
287 | ||
288 | S< >I<$another> = I<$mega>-E<gt>B<privateData>(I<unique_key>|I<package>); | |
289 | ||
290 | =head2 Subwidget | |
291 | ||
292 | Get the widget reference of an advertised subwidget. | |
293 | ||
294 | S< >I<$subwidget> = I<$cw>-E<gt>B<Subwidget>(I<name>); | |
295 | ||
296 | S< >I<@subwidget> = I<$cw>-E<gt>B<Subwidget>(I<name> ?,...?); | |
297 | ||
298 | Returns the widget reference(s) of the subwidget known under the | |
299 | name I<name>. See L<Advertise|"Advertise"> method how to define | |
300 | I<name> for a subwidget. | |
301 | ||
302 | B<Comment:> Mega Widget Users: Use B<Subwidget> to get I<only> | |
303 | documented subwidgets. | |
304 | ||
305 | =head1 PITFALLS | |
306 | ||
307 | =over 4 | |
308 | ||
309 | =item * Resource DB class name | |
310 | ||
311 | Some of the standard options use a resource date base class | |
312 | that is not equal to the resource database name. E.g., | |
313 | ||
314 | Switch: Name: Class: | |
315 | ||
316 | -padx padX Pad | |
317 | -activerelief activeRelief Relief | |
318 | -activebackground activeBackground Foreground | |
319 | -status undef undef | |
320 | ||
321 | One should do the same when one defines one of these | |
322 | options via B<ConfigSpecs>. | |
323 | ||
324 | =item * Method delegation | |
325 | ||
326 | Redirecting methods to a subwidget with B<Delegate> | |
327 | can only work if the base widget itself does have a | |
328 | method with this name. Therefore one can't ``I<delegate>'' | |
329 | any of the methods listed in L<Tk::Widget|Tk::Widget>. | |
330 | A common problematic method is B<bind>. In this case | |
331 | one as to explicitely redirect the method. | |
332 | ||
333 | sub bind | |
334 | { | |
335 | my $mega = shift; | |
336 | my $to = $mega->privateData->{'my_bind_target'}; | |
337 | $to->bind(@_); | |
338 | } | |
339 | ||
340 | =item * privateData | |
341 | ||
342 | Graham Barr wrote: ... It is probably | |
343 | more private than most people think. Not all calls to privateData will | |
344 | return that same HASH reference. The HASH reference that is returned | |
345 | depends on the package it was called from, a different HASH is returned | |
346 | for each package. This allows a widget to hold private data, but then | |
347 | if it is sub-classed the sub-class will get a different HASH and so not | |
348 | cause duplicate name clashes. | |
349 | ||
350 | But privateData does take an optional argument if you want to | |
351 | force which HASH is returned. | |
352 | ||
353 | =item * Scrolled and Composite | |
354 | ||
355 | B<Scrolled>(I<Kind>,...) constructor can not be used with B<Composite>. | |
356 | One has to use $cw->B<Composite>(B<Scrl>I<Kind> =E<gt> B<'name'>, ...); | |
357 | ||
358 | =back | |
359 | ||
360 | =head1 MISSING | |
361 | ||
362 | Of course perl/Tk does not define support function for | |
363 | all necessities. Here's a short list of things you have to | |
364 | handle yourself: | |
365 | ||
366 | =over 4 | |
367 | ||
368 | =item * | |
369 | ||
370 | no support to define construction-time only options. | |
371 | ||
372 | =item * | |
373 | ||
374 | no support to remove an option that is known to the | |
375 | base widget. | |
376 | ||
377 | =item * | |
378 | ||
379 | it's hard to define B<undef> as fallback for an widget | |
380 | option that is not already B<undef>. | |
381 | ||
382 | =item * | |
383 | ||
384 | Frame in perl/Tk carries magic and overhead not needed | |
385 | for composite widget class definition. | |
386 | ||
387 | =item * | |
388 | ||
389 | No support methods for bindings that are shared between all | |
390 | widgets of a composite widget (makes sense at all?) | |
391 | ||
392 | =back | |
393 | ||
394 | =head1 KEYWORDS | |
395 | ||
396 | mega, composite, derived, widget | |
397 | ||
398 | =head1 SEE ALSO | |
399 | ||
400 | L<Tk::composite|Tk::composite> | |
401 | L<Tk::ConfigSpecs|Tk::ConfigSpecs> | |
402 | L<Tk::option|Tk::option> | |
403 | L<Tk::callbacks|Tk::callbacks> | |
404 | L<Tk::bind|Tk::bind> | |
405 | ||
406 | =cut | |
407 |