Class rtk.Attribute

Defines an attribute of a widget class.

This class is only needed when creating custom widgets by subclassing rtk.Widget.

Example
local MyWidget = rtk.class('MyWidget', rtk.Widget)
MyWidget.register{
    myattr = rtk.Attribute{
        default=42,
        -- Convert stringified numbers to actual numbers when attr() is called
        calculate=function(self, attr, value, target)
            return tonumber(value)
        end,
        -- Changing myattr affects geometry so require a full reflow when setting.
        reflow=rtk.Widget.REFLOW_FULL,
    }
}

When a subclass registers an rtk.Attribute instance for an attribute that a parent class already registered, then the subclass's fields will overwrite those from the parent, but otherwise will be merged, so there is no need to reimplement fields from the parent class if no changes are needed.

See also rtk.class()

Attribute Constants

rtk.Attribute.NIL

Proxy for nil keys or values, since Lua-native nils can't otherwise be used as table keys. See calculate.

rtk.Attribute.DEFAULT

Special value that can be passed to rtk.Widget:attr() in order to restore the class default value for an attribute.

Class API

Synopsis

Attributes
default any or function

The default value for the attribute when the class is instantiated

type string or nil

Optional type used to coerce values to the given type without the need for an explicit calculate function

calculate table, function or nil

Allows attribute values to be arbitrarily translated as part of the generation of the attribute's calculated value

priority boolean or nil

If true, ensures that the attribute is calculated after all non-priority attributes

reflow reflowconst or nil

Defines the reflow behavior when this attribute is set

redraw boolean or nil

When reflow is set to rtk.Widget.REFLOW_NONE reflow is skipped and a straight redraw is queued instead

replaces table or nil

A table of one or more attribute names that will be set to nil when this attribute is set

animate function or nil

If defined, provides a step function for animating the attribute

get function or nil

An optional custom function to fetch the current calculated value for the attribute

set function or nil

An optional custom function to set the current calculated value for the attribute

Functions
rtk.Reference()

References the rtk.Attribute field from another attribute in the class or its superclasses

Attributes

rtk.Attribute.default any or function

The default value for the attribute when the class is instantiated.

This can also be a function, in which case it is invoked at object instantiation time, not at import time, and so can be used as a means of providing lazy or dynamic defaults. A common use case for this is attributes that default to some value in the current theme: as the current theme isn't known at import time, this needs to be lazy-evaluated.

If it's a function, it will receive 2 arguments:

  1. the instance of the object whose default is being fetched
  2. the attribute name
rtk.Attribute.type string or nil

Optional type used to coerce values to the given type without the need for an explicit calculate function. One of number, string, or boolean. If nil (default), then no automatic coersion is done.

rtk.Attribute.calculate table, function or nil

Allows attribute values to be arbitrarily translated as part of the generation of the attribute's calculated value.

If this is table, then it's a simple LUT mapping input -> output.

If a function, then the function will receive 5 arguments:

  1. the instance of the object whose attribute is being set
  2. the attribute name
  3. the attribute value
  4. the target table for any injected dynamically calculated attributes (e.g. for shorthand attributes such as rtk.Widget.padding, which implicitly generates tpadding, rpadding, etc.)
  5. if true, the attribute is being calculated for purposes of an animation and so must return an animatable, non-nil value

The function must return the calculated version of the value.

Beware side effects

This function will be invoked in each step of an animation against this attribute, so be careful about side effects in this function, especially costly ones. Define a set function instead, unless you really want the side effect(s) to occur within each animation frame.

rtk.Attribute.priority boolean or nil

If true, ensures that the attribute is calculated after all non-priority attributes. This is used for attributes that either override or depend upon other attributes. For example, shorthand attributes like rtk.Widget.padding which overrides tpadding, rpadding, etc. or attributes like rtk.Button.icon which have a dependency on rtk.Button.color for luma-adaptive icon styling.

rtk.Attribute.reflow reflowconst or nil

Defines the reflow behavior when this attribute is set. When nil, rtk.Widget.REFLOW_PARTIAL is used.

rtk.Attribute.redraw boolean or nil

When reflow is set to rtk.Widget.REFLOW_NONE reflow is skipped and a straight redraw is queued instead. If you also want to skip the redraw, set redraw=false. If nil or true then a redraw is queued when the attribute is modified.

rtk.Attribute.replaces table or nil

A table of one or more attribute names that will be set to nil when this attribute is set. Useful when setting the attribute intends to replace other attributes. For example, setting rtk.Widget.padding will clear any previous values for tpadding, rpadding, etc.

rtk.Attribute.animate function or nil

If defined, provides a step function for animating the attribute. The step function receives two arguments: the widget instance being animated, and a table describing the animation. Relevant keys in the animation table are src (originating value), dst (target value the animation moves towards), and pct (the percentage from 0.0 to 1.0 within the animation). The same table will be passed to the step function each time, so it can also be used to hold custom state between invocations.

The animation function must return two values: the new calculated value of that attribute, and the corresponding new exterior value (or "decalculated" value). For example, animating width or height may need to be adjusted by the scale factor in the calculated value, but the exterior value is before scaling. The exterior value must not be nil -- return rtk.Attribute.NIL if needed.

If an attribute does not define an animate function, then calculate() will be called instead (if it exists), and the returned value will be used both as the calculated value during the animation, as well as the exterior value.

rtk.Attribute.get function or nil

An optional custom function to fetch the current calculated value for the attribute.

Normally those interested in calculated attributes will consult the rtk.Widget.calc table but attributes can define custom getters. One use case for this is calculated shorthand metrics. For example, suppose a widget has padding=20 and lpadding=50. The calc.padding value would be {20, 20, 20, 20} because that's the table representation of the padding attribute, but for practical purposes, callers would want a table version of underlying tpadding, rpadding, etc. attributes, or {20, 20, 20, 50} in the previous example. One case of such a caller is rtk.Widget:animate() which needs to know the proper starting value to animate shorthand attributes.

This function receives 3 arguments:

  1. the instance of the object whose attributes are being fetched
  2. the attribute name
  3. the target table holding calculated attributes (rtk.Widget.calc typically)

The function then returns the current calculated value of the attribute.

rtk.Attribute.set function or nil

An optional custom function to set the current calculated value for the attribute.

By default (when not defined), the return value of calculate() is assigned to the attribute's field in the widget's calc table, however if this function is defined, it's invoked instead.

This function is called after calculate(), but immediately before rtk.Widget:_handle_attr() (which is responsible for dispatching rtk.Widget:onattr()). In the context of animations, set() is only called at the end of an animation rather than within each frame (unlike calculate() which is done each frame), and so it can be used to implement costly validation or side effects.

This function receives 5 arguments:

  1. the instance of the object whose attributes are being fetched
  2. the attribute name
  3. the user-defined pre-calculated value for the attribute
  4. the calculated version of the value (as returned by calculate().
  5. the target table holding calculated attributes (rtk.Widget.calc typically)

The function's return value has no significance.

Functions

rtk.Reference(attr)

References the rtk.Attribute field from another attribute in the class or its superclasses.

References are resolved after all attributes are registered, so an attribute can reference a field from another attribute that hasn't been defined yet.

It's also possible to clone an entire attribute, not just one of its fields.

Example
MyWidget.register{
    iconpos=rtk.Attribute{
        default=rtk.Widget.RIGHT,
        -- Clone the calculate field from superclass's halign attribute
        calculate=rtk.Reference('halign'),
    },
    -- Clone the superclass's bg attribute's metadata completely
    color=rtk.Reference('bg'),
}