## Custom Controls (since 3.0)

### Introduction

All the IUP controls use the same internal API to implement their functionalities.

Each control, needs to export only one function that register the control so it can be used by IupCreate and other functions. Actually another utility function is exported to simplify the creation of the control.

Internally the control must implement the methods of the IUP class, and create functions that handle attributes.

See the Internal SDK for more details.

### Control Class Registration

The new control must export function to register the control. This function is quite simple and it is just a call to iupRegisterClass. For example:

    void IupXxxOpen(void)
    {
      iupRegisterClass(iupXxxNewClass());
    }

The function iupXxxNewClass is internal to the control and it creates the control class.

### Control Class Implementation

The function that creates the class will (1) initialize a base class, then (2) fill its configuration parameters, (3) set the class methods, (4) register the callbacks and (5) register the attributes. For example:

    Iclass* iupXxxNewClass(void)
    {
      /* (1) - initialize the class */
      Iclass* ic = iupClassNew(NULL);

      /* (2) - configuration parameters */
      ic->name = "xxx";
      ic->format = ""; /* no creation parameters */
      ic->nativetype = IUP_TYPECONTROL;
      ic->childtype = IUP_CHILDNONE;
      ic->is_interactive = 1;
      ic->has_attrib_id = 0;

      /* (3) - class methods */
      ic->New = iupXxxGetClass;
      ic->Create = iXxxCreateMethod;
      ic->Map = iXxxMapMethod;
      ic->Destroy = iXxxDestroyMethod;
      ic->ComputeNaturalSize = iXxxComputeNaturalSizeMethod;
      ...

      /* (4) - callbacks */
      iupClassRegisterCallback(ic, "XXX_CB", "i");
      iupClassRegisterCallback(ic, "MAP_CB", "");
      iupClassRegisterCallback(ic, "HELP_CB", "");
      iupClassRegisterCallback(ic, "GETFOCUS_CB", "");
      iupClassRegisterCallback(ic, "KILLFOCUS_CB", "");
      iupClassRegisterCallback(ic, "ENTERWINDOW_CB", "");
      iupClassRegisterCallback(ic, "LEAVEWINDOW_CB", "");
      iupClassRegisterCallback(ic, "K_ANY", "i");
      ...

      /* (5) - attributes */

      /* Common */
      iupClassRegisterAttribute(ic, "SIZE", iupGetSizeAttrib, iupDlgSetSizeAttrib, NULL, IUP_NOT_MAPPED, IUP_NO_INHERIT);
      iupClassRegisterAttribute(ic, "RASTERSIZE", iupGetRasterSizeAttrib, iupDlgSetRastersizeAttrib, NULL, IUP_NOT_MAPPED, IUP_NO_INHERIT);
      iupClassRegisterAttribute(ic, "WID", iupGetWidAttrib, iupNoSetAttrib, NULL, IUP_MAPPED, IUP_NO_INHERIT);
      iupClassRegisterAttribute(ic, "FONT", NULL, iupdrvSetFontAttrib, IupGetGlobal("DEFAULTFONT"), IUP_NOT_MAPPED, IUP_NO_INHERIT);

      /* Common, but only after Map */
      iupClassRegisterAttribute(ic, "ACTIVE", iupGetActiveAttrib, iupSetActiveAttrib, "YES", IUP_MAPPED, IUP_INHERIT);
      iupClassRegisterAttribute(ic, "VISIBLE", iupGetVisibleAttrib, iupSetVisibleAttrib, "YES", IUP_MAPPED, IUP_NO_INHERIT);
      iupClassRegisterAttribute(ic, "ZORDER", NULL, iupdrvSetZorderAttrib, NULL, IUP_MAPPED, IUP_NO_INHERIT);

      /* only the default value. */
      iupClassRegisterAttribute(ic, "BORDER", NULL, NULL, "YES", IUP_NOT_MAPPED, 0);
      ...

      return ic;
    }

You can use the iupXxxNewClass equivalent function of other controls to initialize a new base class for a new control that inherits the functionalities of the base class. For example:

    Iclass* ic = iupClassNew(iupRegisterFindClass("canvas"));

You can also use the Base Class methods and attribute functions to simplify your iupXxxNewClass.

If the control is a native control then it usually will have separate modules for each driver. The iupXxxNewClass function could call a iupdrvXxxInitClass(ic) function to initialize methods and attributes that are driver dependent.

### Control Creation

All controls can be created using the IupCreate functions. But it is a common practice to have a convenience function to create the control:

    Ihandle* IupXxx(void)
    {
      return IupCreate("xxx");
    }

### Control Exported Functions

The file header with the exported functions should look like this:

    #ifndef __IUPXXX_H
    #define __IUPXXX_H

    #ifdef __cplusplus
    extern "C" {
    #endif

    void IupXxxOpen(void);

    Ihandle* IupXxx(void);

    #ifdef __cplusplus
    }
    #endif

    #endif