#ifndef __ELEMENTS_H__
#define __ELEMENTS_H__

#include <enode.h>

/* Element handler functions. */

/* Node rendering function */
typedef void (*RenderFunc) (ENode * node);

/* destruction notice */
typedef void (*DestroyFunc) (ENode * node);

/* parenting function */
typedef void (*ParentFunc) (ENode * parent, ENode * child);

/* attribute is being set */
typedef gint (*SetAttrFunc) (ENode * node, EBuf * attr, EBuf * value);

/* 
 * Called if a set_attr call did not find a valid attr in child, it is
 * propogated to the parent
 */
typedef void (*SetChildAttrFunc) (ENode * parent,
				  ENode * child, EBuf * attr, EBuf * value);

/* attribute get - can be used to set the node value on demand */
typedef void (*GetAttrFunc) (ENode * node, gchar * attr);

typedef void (*SetDataFunc) (ENode * node, EBuf * data);

typedef void (*AppendDataFunc) (ENode * node, EBuf * data);

typedef void (*InsertDataFunc) (ENode * node, unsigned long offset,
				EBuf * data);

typedef void (*DeleteDataFunc) (ENode * node, unsigned long offset,
				unsigned long count);

typedef void (*GetDataFunc) (ENode * node);

/* 
 * In order to avoid cyclic dependancies, this is actually typedef'd in
 * entity.h
 */
/* typedef struct _Element Element; */

struct _Element {
    gchar *tag;

    /* The node which was the dynaloader for this element. */
    ENode *dynaloader_node;

    /* function to render a node */
    RenderFunc render_func;

    /* called on destruction */
    DestroyFunc destroy_func;

    /* to parent a node */
    ParentFunc parent_func;

    /* data_get hook */
    GetDataFunc get_data_func;

    /* Data set function */
    SetDataFunc set_data_func;

    /* data append function */
    AppendDataFunc append_data_func;

    /* Insert peice of data */
    InsertDataFunc insert_data_func;

    /* Delete section of data */
    DeleteDataFunc delete_data_func;

    /* Hash table of attributes */
    GHashTable *attributes;

    /* Attributes this widget will set on behalf of its children */
    GHashTable *child_attributes;

    /* Block child rendererings */
    gint no_render_children;

    /* Documentation */
    gchar *description;
};


typedef struct {
    /* name of attribute, or "*" for catchall */
    gchar *attribute;

    /* called when attrib set */
    SetAttrFunc set_attr_func;

    /* called before attrib retreived */
    GetAttrFunc get_attr_func;

    /* 
     * If registering with element_register_child_attr (), this will be the
     * function called
     */
    SetChildAttrFunc set_child_attr_func;

    /* Breif documentation on what the attribute does */
    gchar *description;

    /* 
     * Type of value stored in attribute, should be one of: - list - integer -
     * precentage - string - boolean - choice - font - etc.. (add it here if
     * you use it.
     */
    gchar *value_desc;

    /* 
     * if a list, a comma seperated list of possiblities. if integer a range of
     * possibilities (eg "1,5", "-1,10", "0,*" denotes 0 to infinity). if
     * boolean, specify "true,false" with default first.
     * 
     * Always list default first.
     */
    gchar *possible_values;

} ElementAttr;

/* register a new element type. */
void element_register (Element * element);

/* register an element attribute.  Can be done at any time. */
void element_register_attrib (Element * element, ElementAttr * element_attrib);

/* register an element attribute for a child of this element type */
void element_register_child_attrib (Element * element,
				    ElementAttr * element_attrib);

/* Get element for type */
Element *element_lookup_element (EBuf * element);

/* return attribute information from a node */
ElementAttr *element_attrib_info_for_node (ENode * node, gchar * attrib);

/* return all attributes available from a node */
GSList *element_supported_attribs_for_node (ENode * node);

/* returns the list of all supported elements - for modulegen. */
GSList *element_list (void);


/* used internally */
void element_render_notify (ENode * node);

void element_parent_notify (ENode * parent, ENode * child);

void element_destroy_notify (ENode * node);

void element_set_data_notify (ENode * node, EBuf * data);

void element_get_data_notify (ENode * node);

void
 element_insert_data_notify (ENode * node, unsigned long offset, EBuf * data);

void
 element_delete_data_notify (ENode * node, unsigned long offset,
			     unsigned long count);

void element_append_data_notify (ENode * node, EBuf * data);

void element_set_attrib_notify (ENode * node, EBuf * attr, EBuf * value);

void element_set_attrib_notify_all (ENode * node);

void element_get_attrib_notify (ENode * node, gchar * attr);

/* used by modulegen */
void element_unregister_all (void);


#endif				/* __ELEMENTS_H__ */


