The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=head1 NAME

NewClass - adding a new class to wxPerl

=head1 CHECKLIST

=over 4

=item * Are there constants or events that need to be wrapped?

see L</"CONSTANTS"> and L</"EVENTS">.

=item * Is the class is derived from wxObject, from wxEvtHandler or from
another class?

see L</"CHOOSING A TYPEMAP">.

=item * Are class instances destroyed by wxWidgets or should they be
garbage collected like normal Perl objects?

see L</"DESTRUCTORS AND THREADS">.

=item * Does the class have overloaded methods?

see L</"OVERLOADING">.

=item * Does the class have virtual methods that should be overridable
from Perl?

see L</"VIRTUAL METHODS">.

=back

=head1 SKELETON

Add a new file F<XS/NewClass.xsp> and update the F<MANIFEST>.  Choose
a relevant F<.xs> file in the top level directory (eg. F<Controls.xs>)
and add this line:

    INCLUDE_COMMAND: $^X -MExtUtils::XSpp::Cmd -e xspp -- -t typemap.xsp XS/NewClass.xsp

A skeleton for F<NewClass.xsp>:

    %module{Wx};

    #include <wx/newclass.h> // use the relevant wxWidgets header(s)

    %name{Wx::NewClass} class wxNewClass : public wxSomeBaseClass
    {
        # constructors see the CONSTRUCTORS section
        wxNewClass( wxWindow* some_window, const wxString& str );

        # destructors
        ~wxNewClass();

        # methods
        wxString GetString() const;
        void SetString( const wxString& str );
    };

Add the typemap definition to F<typemap.tmpl>.  See L</"CHOOSING A
TYPEMAP">.

If adding a class related to one of the wxPerl submodules
(C<Wx::RichText>, C<Wx::Html>, ...) add the F<.xsp> file to the
relevant subdirectory and modify the F<.xs> and F<typemap> files in
that subdirectory.

=head1 CHOOSING A TYPEMAP

There are five typemaps that should work for most wxWidgets objects:

=over 4

=item * C<O_NON_WXOBJECT>

for all classes that do not derive from C<wxObject> AND do not need to
be garbage collected.

=item * C<O_NON_WXOBJECT_THR>

for all classes that do not derive from C<wxObject> AND need to be
garbage collected (see L</"DESTRUCTORS AND THREADS">).

=item * C<O_WXOBJECT>

for all classes that derive from C<wxObject> AND do not need to be
garbage collected.

=item * C<O_WXOBJECT_THR>

for all classes derived from C<wxObject> AND need to be garbage
collected (see L</"DESTRUCTORS AND THREADS">).

=item * C<O_WXEVTHANDLER>

for all classes that derive from C<wxEvtHandler>.  See also
L</"CONSTRUCTORS">.

=back

=head1 CONSTRUCTORS

For C<O_WXEVTHANDLER> typemaps, there is some additional code that
needs to be added to the constructor:

    wxNewClass( wxWindow* some_window, const wxString& str )
        %code{% RETVAL = new wxNewClass( some_window, str );
                wxPli_create_evthandler( aTHX_ RETVAL, CLASS );
                %};

=head1 DESTRUCTORS AND THREADS

For many classes not derived from C<wxEvtHandler> you need to add a
destructor to free the C++ object when the Perl object is garbage
collected.  At the XS++ level this means adding

    ~wxNewClass();

to the class definition, but there is a catch: the Perl threading
model.

Without going into details, this is needed for Perl threads compatibility:

=over 4

=item * Use the correct typemap

choose either C<O_NON_WXOBJECT_THR> or C<O_WXOBJECT_THR>.

=item * Implement a C<CLONE> method

add this code inside the class declaration:

    %{
    static void
    wxNewClass::CLONE()
      CODE:
        wxPli_thread_sv_clone( aTHX_ CLASS, (wxPliCloneSV)wxPli_detach_object );
    %}

=item * Fix the destructor.

modify the destructor like this:

    ~wxNewClass()
        %code%{  wxPli_thread_sv_unregister( aTHX_ "Wx::NewClass", THIS, ST(0) );
                 delete THIS;
                 %};

=back

=head1 VIRTUAL METHODS

The wrapping of virtual functions whose arguments are simple C++ types
(integrals, bool, floating point) and common wxWidgets types
(wxString) should be automatic: at the top of the file, load the
plugin that handles virtual methods

    %loadplugin{build::Wx::XSP::Virtual};

and decorate virtual/pure virtual methods using the C<%Virtual> directive

    // pure virtual
    virtual wxString GetTitle() const = 0 %Virtual{pure};

    // virtual, not pure
    virtual int GetBestFittingWidth(unsigned int idx) const %Virtual;

If the class contains pure virtual methods, it will be marked as
abstract, and it will have no constructors.

For abstract classes, XS++ will create an additional Perl-level class,
called C<< Wx::Pl<classname> >>; in order to override the virtual
methods, you must derive from this class, and not from
C<< Wx::<classname> >>.

TODO allow changing the default behaviour for abstract/concrete classes

TODO allow overriding the class name

TODO allow specifying custom code

TODO handle multiple return values

TODO customized type mapping

=cut