The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# $Id: composite.pod 1.2 Wed, 12 Nov 1997 00:30:45 +0100 ach $

=head1 NAME

Tk::composite - Defining a new composite widget class

=for category Derived Widgets

=head1 SYNOPSIS

    package Tk::Whatever;

    require Tk::Derived;
    require Tk::Frame;                    # or Tk::Toplevel
    @ISA = qw(Tk::Derived Tk::Frame)';    # or Tk::Toplevel

    Construct Tk::Widget 'Whatever';

    sub ClassInit
    {
     my ($class,$mw) = @_;

     #... e.g., class bindings here ...
     $class->SUPER::ClassInit($mw);
    }

    sub Populate
    {
     my ($cw,$args) = @_;

     my $flag = delete $args->{-flag};
     if (defined $flag)
      {
       # handle -flag => xxx which can only be done at create
       # time the delete above ensures that new() does not try
       # and do  $cw->configure(-flag => xxx);
      }

     $cw->SUPER::Populate($args);

     $w = $cw->Component(...);

     $cw->Delegates(...);

     $cw->ConfigSpecs(
		'-cursor'    => [SELF,'cursor','Cursor',undef],
                '-something' => [METHOD,dbName,dbClass,'default'],
                '-text'      => [$label,dbName,dbClass,'default'],
                '-heading'   => [{-text=>$head},
                                 heading,Heading,'My Heading'],
                );
   }

   sub something
   {
    my ($cw,$value) = @_;
    if (@_ > 1)
     {
      # set it
     }
    return # current value
   }

   1;

   __END__

   # Anything not documented is *private* - your POD is god, so to speak.

   =head1 NAME

   Tk::Whatever - a whatever widget

   =head1 SYNOPSIS

     use Tk::Whatever;

     $widget = $parent->Whatever(...);

   =head1 DESCRIPTION

   You forgot to document your widget, didn't you? :-)

   ...

=head1 DESCRIPTION

The intention behind a composite is to create a higher-level widget,
sometimes called a "super-widget" or "meta-widget".  Most often,
a composite will be
built upon other widgets by B<using> them, as opposed to specializing on them.
For example, the supplied composite widget B<LabEntry> is I<made of> an
B<Entry> and a B<Label>; it is neither a I<kind-of> B<Label>
nor is it a I<kind-of> B<Entry>.

Most of the work of a composite widget consist in creating subwidgets,
arrange to dispatch configure options to the proper subwidgets and manage
composite-specific configure options.

=head1 GLORY DETAILS

Depending on your perl/Tk knowledget this section may be enlighting
or confusing.

=head2 Composite Widget

Since perl/Tk is heavilly using an object-oriented approach, it is no
suprise that creating a composite goes through a B<new()> method.
However, the composite does not normally define a B<new()> method
itself: it is usually sufficient to simply inherit it from
B<Tk::Widget>.

This is what happens when the composite use

    @ISA = qw(Tk::Frame);  # or Tk::Toplevel

to specify its inheritance chain.  To complete the initialisation of the
widget, it must call the B<Construct> method from class B<Widget>.  That
method accepts the name of the new class to create, i.e. the package name
of your composite widget:

    Construct Tk::Widget 'Whatever';

Here, B<Whatever> is the package name (aka the widget's B<class>).  This
will define a constructor method for B<Whatever>, normally named after the
widget's class.  Instanciating that composite in client code would
the look like:

    $mw = MainWindow->new();   # Creates a top-level main window

    $cw = $mw->Whatever();     # Creates an instance of the
                               # composite widget Whatever

Whenever a composite is instanciated in client code,
C<Tk::Widget::new()> will be invoked via the widget's class
constructor.  That B<new> method will call

    $cw->InitObject(\%args);

where I<%args> is the arguments passed to the widget's constructor.  Note
that B<InitObject> receives a B<reference> to the hash array
containing all arguments.

For composite widgets that needs an underlying frame, B<InitObject>
will typically be inherited from B<Tk::Frame>, that is, no method of
this name will appear in the composite package.  For composites that
don't need a frame, B<InitObject> will typically be defined in the
composite class (package).  Compare the B<LabEntry> composite with
B<Optionmenu>: the former is B<Frame> based while the latter is B<Widget>
based.

In B<Frame> based composites, B<Tk::Frame::InitObject()> will call
B<Populate()>, which should be defined to create the characteristic
subwidgets of the class.

B<Widget> based composites don't need an extra B<Populate> layer; they
typically have their own B<InitObject> method that will create subwidgets.

=head2 Creating Subwidgets

Subwidget creation happens usually in B<Populate()> (B<Frame> based)
or B<InitObject()> (B<Widget> based).  The composite usually calls the
subwidget's constructor method either directly, for "private" subwidgets,
or indirectly through the B<Component> method for subwidgets that should
be advertised to clients.

B<Populate> may call B<Delegates> to direct calls to methods
of chosen subwidgets. For simple composites, typically most if not all
methods are directed
to a single subwidget - e.g. B<ScrListbox> directs all methods to the core
B<Listbox> so that I<$composite>-E<gt>B<get>(...) calls
I<$listbox>-E<gt>B<get>(...).

=head2 Further steps for Frame based composites

B<Populate> should also call B<ConfigSpecs()> to specify the
way that configure-like options should be handled in the composite.
Once B<Populate> returns, method B<Tk::Frame::ConfigDefault>
walks through the B<ConfigSpecs> entries and populates
%$args hash with defaults for options from X resources (F<.Xdefaults>, etc).

When  B<InitObject()> returns to B<Tk::Widget::new()>,
a call to B<$cw>-E<gt>I<configure>(%$args) is made which sets *all*
the options.

=head1 SEE ALSO

L<Tk::ConfigSpecs|Tk::ConfigSpecs>
L<Tk::Derived|Tk::Derived>

=cut