User Manual

Class uiink::Data

Data objects are used to pass information to and from the GUI.

For an overview of the data API, see: http://uiink.com/docs/data_api/

Methods

void Dispose()
Data Append(Ident field)

Create a new Data object in a list.

If this is called inside of a Rebuild() operation, this newly created Data object will not be removed when the rebuild ends.

Examples

var ink = new Ink(0);
ink.LoadGuiBin("gui.bin");
var main = ink.Source("main");

var d = main.Append("entries");
d.SetString("label", "Hello World!");

d = main.Append("entries");
d.SetString("label", "Second item in entries list.");

void Remove()

Remove this Data object from its containing list.

If NotifyOnRemove() has been previously called on this Data object, a DataEvent.EventType.Remove event will be created.

Once the Data object has been removed, methods getting and setting value fields may still be called. However, all methods relating to parent/child relationships become no-ops.

The Data object will be deleted once there are no more references to it.

If you find yourself writing a lot of code to determine which Data objects are no longer needed, the Rebuild() API may be more convenient.

void NotifyOnRemove()

Cause a DataEvent.EventType.Remove event to be created when this Data object is removed.

This can be useful if there are application data structures that need to be cleaned up when the associated Data object is removed.

Examples

var ink = new Ink(0);
ink.LoadGuiBin("gui.bin");
var listener = new Listener(0);
var main = ink.Source("main");
var d = main.Append("entries");
d.NotifyOnRemove();
d.AddListener(listener);

// At some point, `d` or its parent is removed
d.Remove();

// Main loop
ink.Step(0.016f);
var ev = listener.Poll();
AssertEquals(ev.eventType, DataEvent.EventType.Remove);

Data GetParent()

Return the parent of this Data object.

This will return a empty data handle if this Data object has been removed, or if it is the root of a Source Node.

Examples

var main = ink.Source("main");
var d = main.Append("entries");
AssertEquals(d.GetParent(), main);
AssertFalsy(main.GetParent());

Ident GetParentField()

Return the name of the field in the parent in which this Data object is stored.

This matches the name of the field passed to Data::append() when the Data object was created. For Data objects that represent a Source node this will return a null Ident.

Examples

var main = ink.Source("main");
var d = main.Append("entries");
AssertEquals(d.GetParentField(), (Ident) "entries");
AssertFalsy(main.GetParentField());

int GetIndex()

Return the position of this Data object in its containing list.

Indexes are zero-based.

Examples

var main = ink.Source("main");
var first = main.Append("entries");
var second = main.Append("entries");
AssertEquals(first.GetIndex(), 0);
AssertEquals(second.GetIndex(), 1);

Data GetChild(Ident field, int index)

Gets n-th child of list field.

Indexes are zero-based. If 'index' is out of bounds an empty data handle will be returned.

Examples

var main = ink.Source("main");
var first = main.Append("entries");
var second = main.Append("entries");
AssertEquals(main.GetChild("entries", 0), first);
AssertEquals(main.GetChild("entries", 1), second);
AssertFalsy(main.GetChild("entries", 2)); // out of bounds

void Move(int index)

Move this Data object to a new position in its list.

Note that if you find yourself writing a significant amount of code to manage the order of Data objects, consider moving that responsibility to a sort node.

Examples

var main = ink.Source("main");
var d = main.Append("entries");
main.Append("entries");
d.Move(1);
AssertEquals(d.GetIndex(), 1);

void SetVariant(Ident variant)

Set the variant name for this Data object.

This is useful when a single list has multiple kinds of objects in it that need to be mapped to different templates.

For details on how to setup variant templates in Quill, see the documentation page for Template Variants. http://uiink.com/docs/template_variants/

Examples

var main = ink.Source("main");

// First data entry will use the default template.
main.Append("entries");

// The second data entry will use a template specified in Quill for "my variant"
var d = main.Append("entries");
d.SetVariant("my variant");

void Clear(Ident field)

Returns a field to its default state.

If this is a value field, it will be reset to the default for that value type. If this is a list field, all of the entries in the list will be removed.

Examples

var main = ink.Source("main");

main.SetString("label", "Hello World!");
AssertEquals(main.GetString("label"), "Hello World!");
main.Clear("label");
AssertEquals(main.GetString("label"), "");

var d = main.Append("entries");
AssertEquals(main.GetChild("entries", 0), d); // added a single entry
main.Clear("entries");
AssertFalsy(main.GetChild("entries", 0)); // entry has been removed

void ClearAll()

Clear all of the fields on this data object.

This is equivalent to calling Clear() on each field.

Examples

var main = ink.Source("main");

main.SetString("label", "Hello World!");
var d = main.Append("entries");

AssertEquals(main.GetString("label"), "Hello World!");
AssertEquals(main.GetChild("entries", 0), d); // added a single entry

main.ClearAll();

AssertEquals(main.GetString("label"), "");
AssertFalsy(main.GetChild("entries", 0)); // entry has been removed

void Trigger(Ident field)

Initiate a trigger.

This is useful for notifying the GUI of an event that may not have a value associated with, but the GUI may want to acknowledge with an animation.

void Impulse(Ident field)

Initiate an impulse.

This is useful when an Instanced Source Node has an impulse as an input. (... which is to say, it isn't often useful, but when you need it you need it.)

Query Query(Ident listField)

Find an existing child that matches a Query, or create a new one if it doesn't exist.

See the Query API overview for more information.

This method is a convenience function for writing queries on a single line. You may call Query::Query() directly with for the same result.

Examples

var ink = new Ink(0);
ink.LoadGuiBin("gui.bin");
var main = ink.Source("main");
Data d = main.Query("entries").MatchString("label", "Hello World!").Get();
AssertEquals(d.GetString("label"), "Hello World!");

void Rebuild(Action action, Ident listField=default()

Remove any Data objects that aren't touched during the duration of a function call.

This is useful for structuring code in a manner that is similar to using an immediate mode API.

When the rebuild ends, all child Data objects will be removed unless:

If the optional parameter 'listField' is given, only child Data objects in that particular list field will be impacted. Otherwise, all fields are impacted.

For an overview of this feature with pretty pictures, see: http://uiink.com/articles/data-driven-immediate-mode-ui/

Examples

var main = ink.Source("main");
main.Rebuild(() => {
    var d = main.Append("entries");
    d.SetString("label", "Hello World!");
});
AssertEquals(main.GetChild("entries", 0).GetString("label"), "Hello World!");
main.Rebuild(() => {
    var d = main.Query("entries").MatchString("label", "Hello World!").MaybeGet();
});
AssertTruthy(main.GetChild("entries", 0)); // entry was retained
main.Rebuild(() => {
    // don't touch the entry this time
});
AssertFalsy(main.GetChild("entries", 0)); // entry was removed

void AddListener(Listener listener)

Attaches a Listener to this data. If you are only interested in Change or Impulse events, using OnChange() is an alternative option.

Examples

var listener = new Listener(Listener.Flags.ALL_CHANGES);
var main = ink.Source("main");
var d = main.Append("entries");
d.AddListener(listener);
d.SetString("label", "Hello World!");

ink.Step(0.016f);
var ev = listener.Poll();
AssertEquals(ev.eventType, DataEvent.EventType.Change);

delegate void Changed(DataEvent ev)
void OnFieldChange(Ident fieldName, Changed onEvent)

Set a callback for when a field has an event.

When a value is changed, an impulse/trigger is fired from the GUI, or this data object is removed, the given callback will be called. The callback is not triggered by value changes using the data API. Adding a listener sets NotifyOnRemove.

Examples

var appRoot = new Ink().Source("app");
appRoot.OnFieldChange("message", (ev) => {
    Console.WriteLine("message changed by user to:", appRoot.GetString("message"));
});

void OnChange(Changed onEvent)

Set a callback for when any field on this data object has an event.

Like OnFieldChange but the callback is triggered when any field on this data object has an event. Adding a listener sets NotifyOnRemove.

Examples

var appRoot = new Ink().Source("app");
appRoot.OnChange((ev) => {
    if (ev.eventType == DataEvent.EventType.Change) {
        if (ev.field == "message") {
            Console.WriteLine("message changed by user to:", appRoot.GetString("message"));
        } else if (ev.field == "other field") {
            Console.WriteLine("some other field changed");
        }
    }
});

void ClearOnChange()

Removes all callbacks added with OnChange() and OnFieldChange().

void SetTag(Ident tagName, Object tagValue)

Store an arbitrary C# Object in the Data object.

This value is only accessible from the programming API. It is not used by the ink runtime itself.

Setting a tag implicitly calls NotifyOnRemove. (The C# binding calls NotifyOnRemove to clean up object references. This may not be the case for other language bindings.)

Note that each language binding has its own namespace for tags, (with the exception of C and C++.) A tag set in one language will not conflict with a tag set in another language binding.

Examples

var main = ink.Source("main");
var d = main.Append("entries");
d.SetTag("mytag", 1);

Object GetTag(Ident tagName)

Retrieve an Object previously set with SetTag.

If SetTag has not been called with this tag name, null will be returned.

Examples

var main = ink.Source("main");
var d = main.Append("entries");
d.SetTag("mytag", 1);
AssertEquals(d.GetTag("mytag"), 1);

void SetTagNative(Ident tagName, IntPtr tagValue)

Store a void pointer in the Data object.

This value is only accessible from the programming API. It is not used by the ink runtime itself.

If this value points to an object that should be cleaned up when the Data object is removed, consider creating a Listener and calling NotifyOnRemove.

Tag names that begin with double underscores are reserved for language bindings.

Native tag names do not collide with tags set using SetTag.

IntPtr GetTagNative(Ident tagName)

Retrieve a void pointer previously set with SetTagNative.

If SetTagNative has not been called with this tag name, null will be returned.

Data FindByTagNative(Ident field, Ident tagName, IntPtr tagValue)

Find a child of this Data object that has a given tag value.

void SetFloat(Ident field, float v)
void SetInt(Ident field, int v)
void SetBool(Ident field, bool v)
void SetIdent(Ident field, Ident v)
void SetColor(Ident field, UInt32 v)
void SetString(Ident field, string v)
void SetImage(Ident field, Image v)
float GetFloat(Ident field)
int GetInt(Ident field)
bool GetBool(Ident field)
Ident GetIdent(Ident field)
UInt32 GetColor(Ident field)
string GetString(Ident field)
Image GetImage(Ident field)
override bool Equals(object obj)
override int GetHashCode()

Static Methods

static implicit operator bool(Data d)