Data API

Data is passed from code to the UI through 'data objects'. Since most application code is through these data objects, we use 'inkd' as a shorthand for 'ink data object'.

Root objects#

The most common way to provide data to the UI is through a Global Source Node.

To get a reference to a global source node:

inkd ink_global_source(struct ink* ink, ink_ident name);
Data Ink::global_source(ink_ident name);
ink: ink context object. if null, the first context object created is used
name: Matches the 'Source Name' option of the Global Source Node.

Value Fields#

Values can be set on fields with setter functions:

void inkd_float    (inkd, ink_ident field, float value);
void inkd_int      (inkd, ink_ident field, int value);
void inkd_bool     (inkd, ink_ident field, char value);
void inkd_string   (inkd, ink_ident field, ink_str value);
void inkd_ident    (inkd, ink_ident field, ink_ident value);
void inkd_image    (inkd, ink_ident field, struct ink_image* value);
void inkd_color    (inkd, ink_ident field, uint32_t value);
void inkd_charp    (inkd, ink_ident field, const char* value);
    void Data::set_float   (ink_ident field, float value);
    void Data::set_int     (ink_ident field, int value);
    void Data::set_bool    (ink_ident field, bool value);
    void Data::set_string  (ink_ident field, const std::string& value);
    void Data::set_string  (ink_ident field, const char* value);
    void Data::set_ident   (ink_ident field, ink_ident value);
    void Data::set_image   (ink_ident field, ink_image* value);
    void Data::set_color   (ink_ident field, uint32_t value);

The value can be read back with corresponding getter functions:

float              inkd_get_float  (inkd, ink_ident field);
int                inkd_get_int    (inkd, ink_ident field);
char               inkd_get_bool   (inkd, ink_ident field);
ink_str            inkd_get_string (inkd, ink_ident field);
ink_ident          inkd_get_ident  (inkd, ink_ident field);
struct ink_image*  inkd_get_image  (inkd, ink_ident field);
uint32_t           inkd_get_color  (inkd, ink_ident field);
const char*        inkd_get_charp  (inkd, ink_ident field);
    float       Data::get_float(ink_ident field);
    int         Data::get_int(ink_ident field);
    bool        Data::get_bool(ink_ident field);
    String      Data::get_string(ink_ident field);
    std::string Data::get_std_string(ink_ident field);
    const char* Data::get_c_string(ink_ident field);
    ink_image*  Data::get_image(ink_ident field);
    uint32_t    Data::get_color(ink_ident field);

Note that inkd_charp and ink_get_charp are convenience functions that wrap inkd_string/inkd_get_string, allowing you to read and write strings without dealing with the ink_str API. The ink_str versions are mostly useful for optimizing heap allocations.


Lists allow you to build nested data structures. Lists are not referenced directly, instead they are referenced by the inkd and the field name.

To create a new data object in a list use inkd_append

inkd inkd_append(inkd parent, ink_ident field)
Data Data::append(ink_ident field);
parent: the data object that holds the list
field: the name of the list in the parent data object
return value: new inkd that was added to the end of the list

To remove an inkd from a list:

void inkd_remove(inkd child)
void Data::remove()
child: the inkd that should be removed from its parent's list

To remove all contents of a list:

void inkd_clear(inkd d, ink_ident field);
void Data::clear(ink_ident field);

To rearrange children in a list:

void inkd_move(inkd child, int new_index);
void Data::move(int new_index);

To get a reference to an existing child in a list by index:

inkd inkd_get_child(inkd parent, ink_ident field, int index);
Data Data::get_child(ink_ident field, int index);

To get the index of a child in its parent's list:

int inkd_get_index(inkd child);
int Data::get_index();

To get the parent of a child:

inkd inkd_get_parent(inkd child);
Data Data::get_parent();

Lists need not be homogeneous. If the entries in a list vary significantly in their presentation and data, consider using template variants.

To specify which template variant an inkd should be mapped to:

void inkd_variant(inkd d, ink_ident variant);
void Data::set_variant(ink_ident variant);

Data Events#

enum ink_data_event_type {

struct ink_data_event {
    enum ink_data_event_type type;

    ink_ident source_name;

    struct ink_data* source_data;

    // Valid for CHANGE, IMPULSE, REMOVE
    struct ink_data* data;

    // Valid for CHANGE, IMPULSE
    ink_ident field;

    // Valid for IMPULSE, but may still be null
    const struct ink_event_info* event_info;

enum ink_data_event_type
ink_data_event_poll(struct ink* ink, struct ink_data_event* out);

// Blocks until an event is available.
enum ink_data_event_type
ink_data_event_wait(struct ink* ink, struct ink_data_event* out);