Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # $Id: composite.pod 1.2 Wed, 12 Nov 1997 00:30:45 +0100 ach $ |
2 | ||
3 | =head1 NAME | |
4 | ||
5 | Tk::composite - Defining a new composite widget class | |
6 | ||
7 | =for category Derived Widgets | |
8 | ||
9 | =head1 SYNOPSIS | |
10 | ||
11 | package Tk::Whatever; | |
12 | ||
13 | require Tk::Derived; | |
14 | require Tk::Frame; # or Tk::Toplevel | |
15 | @ISA = qw(Tk::Derived Tk::Frame)'; # or Tk::Toplevel | |
16 | ||
17 | Construct Tk::Widget 'Whatever'; | |
18 | ||
19 | sub ClassInit | |
20 | { | |
21 | my ($class,$mw) = @_; | |
22 | ||
23 | #... e.g., class bindings here ... | |
24 | $class->SUPER::ClassInit($mw); | |
25 | } | |
26 | ||
27 | sub Populate | |
28 | { | |
29 | my ($cw,$args) = @_; | |
30 | ||
31 | my $flag = delete $args->{-flag}; | |
32 | if (defined $flag) | |
33 | { | |
34 | # handle -flag => xxx which can only be done at create | |
35 | # time the delete above ensures that new() does not try | |
36 | # and do $cw->configure(-flag => xxx); | |
37 | } | |
38 | ||
39 | $cw->SUPER::Populate($args); | |
40 | ||
41 | $w = $cw->Component(...); | |
42 | ||
43 | $cw->Delegates(...); | |
44 | ||
45 | $cw->ConfigSpecs( | |
46 | '-cursor' => [SELF,'cursor','Cursor',undef], | |
47 | '-something' => [METHOD,dbName,dbClass,'default'], | |
48 | '-text' => [$label,dbName,dbClass,'default'], | |
49 | '-heading' => [{-text=>$head}, | |
50 | heading,Heading,'My Heading'], | |
51 | ); | |
52 | } | |
53 | ||
54 | sub something | |
55 | { | |
56 | my ($cw,$value) = @_; | |
57 | if (@_ > 1) | |
58 | { | |
59 | # set it | |
60 | } | |
61 | return # current value | |
62 | } | |
63 | ||
64 | 1; | |
65 | ||
66 | __END__ | |
67 | ||
68 | # Anything not documented is *private* - your POD is god, so to speak. | |
69 | ||
70 | =head1 NAME | |
71 | ||
72 | Tk::Whatever - a whatever widget | |
73 | ||
74 | =head1 SYNOPSIS | |
75 | ||
76 | use Tk::Whatever; | |
77 | ||
78 | $widget = $parent->Whatever(...); | |
79 | ||
80 | =head1 DESCRIPTION | |
81 | ||
82 | You forgot to document your widget, didn't you? :-) | |
83 | ||
84 | ... | |
85 | ||
86 | =head1 DESCRIPTION | |
87 | ||
88 | The intention behind a composite is to create a higher-level widget, | |
89 | sometimes called a "super-widget" or "meta-widget". Most often, | |
90 | a composite will be | |
91 | built upon other widgets by B<using> them, as opposed to specializing on them. | |
92 | For example, the supplied composite widget B<LabEntry> is I<made of> an | |
93 | B<Entry> and a B<Label>; it is neither a I<kind-of> B<Label> | |
94 | nor is it a I<kind-of> B<Entry>. | |
95 | ||
96 | Most of the work of a composite widget consist in creating subwidgets, | |
97 | arrange to dispatch configure options to the proper subwidgets and manage | |
98 | composite-specific configure options. | |
99 | ||
100 | =head1 GLORY DETAILS | |
101 | ||
102 | Depending on your perl/Tk knowledget this section may be enlighting | |
103 | or confusing. | |
104 | ||
105 | =head2 Composite Widget | |
106 | ||
107 | Since perl/Tk is heavilly using an object-oriented approach, it is no | |
108 | suprise that creating a composite goes through a B<new()> method. | |
109 | However, the composite does not normally define a B<new()> method | |
110 | itself: it is usually sufficient to simply inherit it from | |
111 | B<Tk::Widget>. | |
112 | ||
113 | This is what happens when the composite use | |
114 | ||
115 | @ISA = qw(Tk::Frame); # or Tk::Toplevel | |
116 | ||
117 | to specify its inheritance chain. To complete the initialisation of the | |
118 | widget, it must call the B<Construct> method from class B<Widget>. That | |
119 | method accepts the name of the new class to create, i.e. the package name | |
120 | of your composite widget: | |
121 | ||
122 | Construct Tk::Widget 'Whatever'; | |
123 | ||
124 | Here, B<Whatever> is the package name (aka the widget's B<class>). This | |
125 | will define a constructor method for B<Whatever>, normally named after the | |
126 | widget's class. Instanciating that composite in client code would | |
127 | the look like: | |
128 | ||
129 | $mw = MainWindow->new(); # Creates a top-level main window | |
130 | ||
131 | $cw = $mw->Whatever(); # Creates an instance of the | |
132 | # composite widget Whatever | |
133 | ||
134 | Whenever a composite is instanciated in client code, | |
135 | C<Tk::Widget::new()> will be invoked via the widget's class | |
136 | constructor. That B<new> method will call | |
137 | ||
138 | $cw->InitObject(\%args); | |
139 | ||
140 | where I<%args> is the arguments passed to the widget's constructor. Note | |
141 | that B<InitObject> receives a B<reference> to the hash array | |
142 | containing all arguments. | |
143 | ||
144 | For composite widgets that needs an underlying frame, B<InitObject> | |
145 | will typically be inherited from B<Tk::Frame>, that is, no method of | |
146 | this name will appear in the composite package. For composites that | |
147 | don't need a frame, B<InitObject> will typically be defined in the | |
148 | composite class (package). Compare the B<LabEntry> composite with | |
149 | B<Optionmenu>: the former is B<Frame> based while the latter is B<Widget> | |
150 | based. | |
151 | ||
152 | In B<Frame> based composites, B<Tk::Frame::InitObject()> will call | |
153 | B<Populate()>, which should be defined to create the characteristic | |
154 | subwidgets of the class. | |
155 | ||
156 | B<Widget> based composites don't need an extra B<Populate> layer; they | |
157 | typically have their own B<InitObject> method that will create subwidgets. | |
158 | ||
159 | =head2 Creating Subwidgets | |
160 | ||
161 | Subwidget creation happens usually in B<Populate()> (B<Frame> based) | |
162 | or B<InitObject()> (B<Widget> based). The composite usually calls the | |
163 | subwidget's constructor method either directly, for "private" subwidgets, | |
164 | or indirectly through the B<Component> method for subwidgets that should | |
165 | be advertised to clients. | |
166 | ||
167 | B<Populate> may call B<Delegates> to direct calls to methods | |
168 | of chosen subwidgets. For simple composites, typically most if not all | |
169 | methods are directed | |
170 | to a single subwidget - e.g. B<ScrListbox> directs all methods to the core | |
171 | B<Listbox> so that I<$composite>-E<gt>B<get>(...) calls | |
172 | I<$listbox>-E<gt>B<get>(...). | |
173 | ||
174 | =head2 Further steps for Frame based composites | |
175 | ||
176 | B<Populate> should also call B<ConfigSpecs()> to specify the | |
177 | way that configure-like options should be handled in the composite. | |
178 | Once B<Populate> returns, method B<Tk::Frame::ConfigDefault> | |
179 | walks through the B<ConfigSpecs> entries and populates | |
180 | %$args hash with defaults for options from X resources (F<.Xdefaults>, etc). | |
181 | ||
182 | When B<InitObject()> returns to B<Tk::Widget::new()>, | |
183 | a call to B<$cw>-E<gt>I<configure>(%$args) is made which sets *all* | |
184 | the options. | |
185 | ||
186 | =head1 SEE ALSO | |
187 | ||
188 | L<Tk::ConfigSpecs|Tk::ConfigSpecs> | |
189 | L<Tk::Derived|Tk::Derived> | |
190 | ||
191 | =cut | |
192 |