#ifdef E_TYPEDEFS

#define E_GADCON_CLIENT(x) ((E_Gadcon_Client *)(x))

/* different layout policies - only 1 supported for now */
typedef enum _E_Gadcon_Layout_Policy
{
   E_GADCON_LAYOUT_POLICY_PANEL
} E_Gadcon_Layout_Policy;

typedef enum _E_Gadcon_Orient
{
   /* generic orientations */
   E_GADCON_ORIENT_FLOAT = 0,
   E_GADCON_ORIENT_HORIZ,
   E_GADCON_ORIENT_VERT,
   E_GADCON_ORIENT_LEFT,
   E_GADCON_ORIENT_RIGHT,
   E_GADCON_ORIENT_TOP,
   E_GADCON_ORIENT_BOTTOM,
   E_GADCON_ORIENT_CORNER_TL,
   E_GADCON_ORIENT_CORNER_TR,
   E_GADCON_ORIENT_CORNER_BL,
   E_GADCON_ORIENT_CORNER_BR,
   E_GADCON_ORIENT_CORNER_LT,
   E_GADCON_ORIENT_CORNER_RT,
   E_GADCON_ORIENT_CORNER_LB,
   E_GADCON_ORIENT_CORNER_RB,
   E_GADCON_ORIENT_LAST
} E_Gadcon_Orient;

typedef enum _E_Gadcon_Site
{
   E_GADCON_SITE_UNKNOWN = 0, // when target site is unknown
   /* generic sities */
   E_GADCON_SITE_SHELF,
   E_GADCON_SITE_DESKTOP,
   E_GADCON_SITE_TOOLBAR, // generic toolbar
   E_GADCON_SITE_EFM_TOOLBAR // filemanager window toolbar
} E_Gadcon_Site;

#define E_GADCON_CLIENT_STYLE_PLAIN "plain"
#define E_GADCON_CLIENT_STYLE_INSET "inset"

typedef struct _E_Gadcon              E_Gadcon;
typedef struct _E_Gadcon_Client       E_Gadcon_Client;
typedef struct _E_Event_Gadcon_Client       E_Event_Gadcon_Client_Add;
typedef struct _E_Event_Gadcon_Client       E_Event_Gadcon_Client_Del;
typedef struct _E_Gadcon_Client_Class E_Gadcon_Client_Class;
typedef struct _E_Event_Gadcon_Client_Class E_Event_Gadcon_Client_Class_Add;
typedef struct _E_Event_Gadcon_Client_Class E_Event_Gadcon_Client_Class_Del;
typedef struct _E_Gadcon_Location     E_Gadcon_Location;
typedef struct _E_Event_Gadcon_Populate E_Event_Gadcon_Populate;
typedef void (*E_Gadcon_DND_Cb)(E_Gadcon*, E_Gadcon_Client*);

#else
#ifndef E_GADCON_H
#define E_GADCON_H

#define E_GADCON_TYPE        0xE0b01006
#define E_GADCON_DUMMY_TYPE  0xE0b01016
#define E_GADCON_CLIENT_TYPE 0xE0b01007

E_API extern int E_EVENT_GADCON_CLIENT_ADD;
E_API extern int E_EVENT_GADCON_CLIENT_DEL;
E_API extern int E_EVENT_GADCON_CLIENT_CLASS_ADD;
E_API extern int E_EVENT_GADCON_CLIENT_CLASS_DEL;
E_API extern int E_EVENT_GADCON_POPULATE;

struct _E_Gadcon
{
   E_Object               e_obj_inherit;

   const char            *name;
   int                    id;

   E_Gadcon_Layout_Policy layout_policy;

   struct
   {
      Evas_Object *o_parent;
      const char  *swallow_name;
   } edje;
   Ecore_Evas            *ecore_evas;
   E_Zone                *zone;

   E_Gadcon_Orient        orient;

   Evas                  *evas;
   Evas_Object           *o_container;
   Eina_List             *clients;
   Eina_List             *populate_requests;
   Eina_List             *populated_classes;
   Eina_Hash             *awaiting_classes; /* E_Config_Gadcon_Client */

   struct
   {
      void  (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h);
      void *data;
   } resize_request, min_size_request;
   struct
   {
      Evas_Object *(*func)(void *data, E_Gadcon_Client * gcc, const char *style);
      void        *data;
   } frame_request;
   struct
   {
      void  (*func)(void *data, E_Gadcon_Client *gcc, E_Menu *menu);
      void *data;
   } menu_attach;
   struct
   {
      void  (*func)(void *data, E_Gadcon *gc, const E_Gadcon_Client_Class *cc);
      void *data;
   } populate_class;
   struct
   {
      void  (*func)(void *data, int lock);
      void *data;
   } locked_set;
   struct
   {
      void  (*func)(void *data);
      void *data;
   } urgent_show;

   E_Config_Dialog   *config_dialog;
   unsigned char      editing : 1;
   Ecore_X_Window     dnd_win, xdnd_win;
   E_Shelf           *shelf;
   E_Toolbar         *toolbar;
   E_Gadcon_Location *location;

   E_Drop_Handler    *drop_handler;
   E_Gadcon_Client *drag_gcc, *new_gcc;
   E_Gadcon_DND_Cb dnd_enter_cb, dnd_leave_cb, dnd_move_cb, dnd_drop_cb;

   E_Config_Gadcon   *cf;

   unsigned char      instant_edit : 1;
   unsigned char      dummy : 1;
   Eina_Bool          custom : 1;
   Eina_Bool          cfg_delete : 1;
};

#define GADCON_CLIENT_CLASS_VERSION 3
/* Version 3 add the *client_class param to icon(),label(),id_new(), id_del() */
/*           and the *orient param to orient() */
struct _E_Gadcon_Client_Class
{
   int         version;
   /* All members below are part of version 1 */
   const char *name;
   struct
   {
      E_Gadcon_Client *(*init)(E_Gadcon * gc, const char *name, const char *id, const char *style);
      void             (*shutdown)(E_Gadcon_Client *gcc);
      void             (*orient)(E_Gadcon_Client *gcc, E_Gadcon_Orient orient);
      const char      *(*label)(const E_Gadcon_Client_Class *client_class);
      Evas_Object     *(*icon)(const E_Gadcon_Client_Class *client_class, Evas * evas);
      /* All members below are part of version 2 */
      /* Create new id, so that the gadcon client can refer to a config set inside the module */
      const char      *(*id_new)(const E_Gadcon_Client_Class *client_class);
      /* Del an id when a gadcon client is removed from the system */
      void             (*id_del)(const E_Gadcon_Client_Class *client_class, const char *id);
      /* All members below are part of version 3 */
      Eina_Bool        (*is_site)(E_Gadcon_Site site);
   } func;
   const char *default_style;
};

struct _E_Gadcon_Client
{
   E_Object                     e_obj_inherit;
   E_Gadcon                    *gadcon;
   const char                  *name;
   int                          id;
   Evas_Object                 *o_base;
   Evas_Object                 *o_box;
   Evas_Object                 *o_frame;
   Evas_Object                 *o_control;
   Evas_Object                 *o_event;
   const E_Gadcon_Client_Class *client_class;
   void                        *data;

   struct
   {
      int    pos, size, res; //gadcon
      double pos_x, pos_y, size_w, size_h;     //gadman
   } config;

   struct
   {
      int seq, flags;   /* goes to save */
      int state, resist;
      int prev_pos, prev_size;
      int want_save : 1;
   } state_info;

   struct
   {
      int w, h;
   } pad, min, max, aspect;

   Ecore_Timer            *scroll_timer;
   Ecore_Timer            *instant_edit_timer;
   Ecore_Animator         *scroll_animator;
   double                  scroll_pos, scroll_wanted;

   struct
   {
      void *data;
      void  (*func)(void *data);
   } scroll_cb;

   E_Menu                 *menu;
   const char             *style;
   unsigned char           autoscroll : 1;
   unsigned char           resizable : 1;
   unsigned char           moving : 1;
   unsigned char           resizing : 1;
   unsigned char           autoscroll_set : 1;
   unsigned char           autoscroll_disabled : 1;
   Evas_Coord              dx, dy;

   struct
   {
      int x, y;
      E_Drag *drag;
   } drag;

   unsigned char           hidden : 1;

   E_Config_Gadcon_Client *cf;
};

struct _E_Event_Gadcon_Client_Class
{
   const E_Gadcon_Client_Class *cc;
};

struct _E_Event_Gadcon_Client
{
   E_Gadcon_Client *gcc;
};

struct _E_Event_Gadcon_Populate
{
   E_Gadcon *gc;
};

/* defines usable gadget placements such as Desktop, Shelf #, etc */
/* next fields are mandatory (not NULL): name, add_gadget.func, remove_gadget.func */
struct _E_Gadcon_Location
{
   /* location name */
   const char   *name;
   /* icon related to location, such as "preferences-desktop-shelf" for shelves, "preferences-desktop" for menus */
   const char   *icon_name;
   E_Gadcon_Site site;
   /* adds gadcon client to location. Returns nonzero on success */
   struct
   {
      int   (*func)(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc);
      void *data;
   } gadget_add;
   /* removes existing gadcon client from location */
   struct
   {
      void  (*func)(void *data, E_Gadcon_Client *gcc);
      void *data;
   } gadget_remove;
};

EINTERN int                  e_gadcon_init(void);
EINTERN int                  e_gadcon_shutdown(void);
E_API void                    e_gadcon_provider_register(const E_Gadcon_Client_Class *cc);
E_API void                    e_gadcon_provider_unregister(const E_Gadcon_Client_Class *cc);
E_API Eina_List              *e_gadcon_provider_list(void);
E_API E_Gadcon               *e_gadcon_dummy_new(int id);
E_API void                    e_gadcon_drop_handler_add(E_Gadcon *gc, E_Gadcon_DND_Cb enter, E_Gadcon_DND_Cb leave, E_Gadcon_DND_Cb move, E_Gadcon_DND_Cb drop, int x, int y, int w, int h);
E_API void                    e_gadcon_config_del(E_Gadcon *gc);
E_API E_Gadcon               *e_gadcon_swallowed_new(const char *name, int id, Evas_Object *obj, const char *swallow_name);
E_API void                    e_gadcon_custom_new(E_Gadcon *gc);
E_API void                    e_gadcon_custom_del(E_Gadcon *gc);
E_API void                    e_gadcon_custom_populate_request(E_Gadcon *gc);
E_API void                    e_gadcon_swallowed_min_size_set(E_Gadcon *gc, Evas_Coord w, Evas_Coord h);
E_API void                    e_gadcon_min_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data);
E_API void                    e_gadcon_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data);
E_API void e_gadcon_frame_request_callback_set(E_Gadcon * gc, Evas_Object * (*func)(void *data, E_Gadcon_Client * gcc, const char *style), void *data);
E_API void                    e_gadcon_populate_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, const E_Gadcon_Client_Class *cc), void *data);
E_API void                    e_gadcon_layout_policy_set(E_Gadcon *gc, E_Gadcon_Layout_Policy layout_policy);
E_API Eina_Bool               e_gadcon_populate(E_Gadcon *gc);
E_API void                    e_gadcon_unpopulate(E_Gadcon *gc);
E_API void                    e_gadcon_repopulate(E_Gadcon *gc);
E_API void                    e_gadcon_populate_class(E_Gadcon *gc, const E_Gadcon_Client_Class *cc);
E_API void                    e_gadcon_orient(E_Gadcon *gc, E_Gadcon_Orient orient);
E_API void                    e_gadcon_edit_begin(E_Gadcon *gc);
E_API void                    e_gadcon_edit_end(E_Gadcon *gc);
E_API void                    e_gadcon_all_edit_begin(void);
E_API void                    e_gadcon_all_edit_end(void);
E_API void                    e_gadcon_zone_set(E_Gadcon *gc, E_Zone *zone);
E_API E_Zone                 *e_gadcon_zone_get(E_Gadcon *gc);
E_API void                    e_gadcon_ecore_evas_set(E_Gadcon *gc, Ecore_Evas *ee);
E_API int                     e_gadcon_canvas_zone_geometry_get(E_Gadcon *gc, int *x, int *y, int *w, int *h);
E_API void                    e_gadcon_util_menu_attach_func_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon_Client *gcc, E_Menu *menu), void *data);
E_API void                    e_gadcon_util_lock_func_set(E_Gadcon *gc, void (*func)(void *data, int lock), void *data);
E_API void                    e_gadcon_util_urgent_show_func_set(E_Gadcon *gc, void (*func)(void *data), void *data);
E_API void                    e_gadcon_dnd_window_set(E_Gadcon *gc, Ecore_X_Window win);
E_API Ecore_X_Window          e_gadcon_dnd_window_get(E_Gadcon *gc);
E_API void                    e_gadcon_xdnd_window_set(E_Gadcon *gc, Ecore_X_Window win);
E_API Ecore_X_Window          e_gadcon_xdnd_window_get(E_Gadcon *gc);
E_API void                    e_gadcon_shelf_set(E_Gadcon *gc, E_Shelf *shelf);
E_API E_Shelf                *e_gadcon_shelf_get(E_Gadcon *gc);
E_API void                    e_gadcon_toolbar_set(E_Gadcon *gc, E_Toolbar *toolbar);
E_API E_Toolbar              *e_gadcon_toolbar_get(E_Gadcon *gc);
E_API E_Gadcon_Client      *e_gadcon_client_find(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc);
E_API E_Config_Gadcon_Client *e_gadcon_client_config_new(E_Gadcon *gc, const char *name);
E_API void                    e_gadcon_client_config_del(E_Config_Gadcon *cf_gc, E_Config_Gadcon_Client *cf_gcc);
E_API E_Gadcon_Client        *e_gadcon_client_new(E_Gadcon *gc, const char *name, const char *id, const char *style, Evas_Object *base_obj);
E_API void                    e_gadcon_client_edit_begin(E_Gadcon_Client *gcc);
E_API void                    e_gadcon_client_edit_end(E_Gadcon_Client *gcc);
E_API void                    e_gadcon_client_queue(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc);
E_API void                    e_gadcon_client_show(E_Gadcon_Client *gcc);
E_API void                    e_gadcon_client_hide(E_Gadcon_Client *gcc);
E_API void                    e_gadcon_client_size_request(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h);
E_API void                    e_gadcon_client_min_size_set(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h);
E_API void                    e_gadcon_client_aspect_set(E_Gadcon_Client *gcc, int w, int h);
E_API void                    e_gadcon_client_autoscroll_toggle_disabled_set(E_Gadcon_Client *gcc, Eina_Bool disable);
E_API void                    e_gadcon_client_autoscroll_set(E_Gadcon_Client *gcc, int autoscroll);
E_API void                    e_gadcon_client_autoscroll_update(E_Gadcon_Client *gcc, int mx, int my);
E_API void                    e_gadcon_client_autoscroll_cb_set(E_Gadcon_Client *gcc, void (*func)(void *data), void *data);
E_API void                    e_gadcon_client_resizable_set(E_Gadcon_Client *gcc, int resizable);
E_API int                     e_gadcon_client_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h);
E_API int                     e_gadcon_client_viewport_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h);
E_API E_Zone                 *e_gadcon_client_zone_get(E_Gadcon_Client *gcc);
E_API E_Menu                *e_gadcon_client_menu_set(E_Gadcon_Client *gcc, E_Menu *m);
E_API E_Menu                 *e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu_gadget, int flags);
E_API void                    e_gadcon_client_util_menu_attach(E_Gadcon_Client *gcc);
E_API void                    e_gadcon_locked_set(E_Gadcon *gc, int lock);
E_API void                    e_gadcon_urgent_show(E_Gadcon *gc);
E_API void                    e_gadcon_name_set(E_Gadcon *gc, const char *name);

/* site helpers */

E_API Eina_Bool               e_gadcon_site_is_shelf(E_Gadcon_Site site);
E_API Eina_Bool               e_gadcon_site_is_desktop(E_Gadcon_Site site);
E_API Eina_Bool               e_gadcon_site_is_efm_toolbar(E_Gadcon_Site site);

E_API Eina_Bool               e_gadcon_site_is_any_toolbar(E_Gadcon_Site site); // all toolbar sities
E_API Eina_Bool               e_gadcon_site_is_not_toolbar(E_Gadcon_Site site); // all non-toolbar sities

/* location helpers */

E_API E_Gadcon_Location *
                             e_gadcon_location_new(const char *name, E_Gadcon_Site site,
                      int (*add_func)(void *data, E_Gadcon_Client *, const E_Gadcon_Client_Class *cc),
                      void *add_data,
                      void (*remove_func)(void *data, E_Gadcon_Client *cc),
                      void *remove_data);
E_API void                    e_gadcon_location_free(E_Gadcon_Location *loc);
E_API void                    e_gadcon_location_register(E_Gadcon_Location *loc);
E_API void                    e_gadcon_location_unregister(E_Gadcon_Location *loc);
E_API void                    e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name);
E_API void                    e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu);
E_API void                    e_gadcon_drag_finished_cb(E_Drag *drag, int dropped);
E_API void                    e_gadcon_client_drag_set(E_Gadcon_Client *gcc);

E_API Eina_Bool              e_gadcon_client_visible_get(const E_Gadcon_Client *gcc, const E_Desk *desk);

#define GADCON_CLIENT_CONFIG_GET(_type, _items, _gc_class, _id)                             \
  if (!_id)                                                                                 \
    {                                                                                       \
       char *_buf;                                                                          \
       int _num = 0;                                                                        \
       _type *_ci;                                                                          \
       if (_items)                                                                          \
         {                                                                                  \
            const char *_p;                                                                 \
            _ci = eina_list_last(_items)->data;                                             \
            _p = strrchr(_ci->id, '.');                                                     \
            if (_p) _num = atoi(_p + 1) + 1;                                                \
         }                                                                                  \
       _buf = alloca(sizeof (char) * ((_gc_class.name ? strlen(_gc_class.name) : 6) + 11)); \
       sprintf(_buf, "%s.%d", _gc_class.name, _num);                                        \
       _id = _buf;                                                                          \
    }                                                                                       \
  else                                                                                      \
    {                                                                                       \
       Eina_List *l;                                                                        \
       _type *_ci;                                                                          \
       EINA_LIST_FOREACH(_items, l, _ci)                                                   \
         if ((_ci->id) && (!strcmp(_ci->id, _id))) return _ci;                              \
    }

#endif
#endif
