DVUI

tabIndexNextEx

Parameters

#
event_num:?u16
?u16
tabidxs:[]dvui.TabIndex
[]dvui.TabIndex
base_tig:Id
Id
in_focus_group:bool
bool

Source

Implementation

#
pub fn tabIndexNextEx(event_num: ?u16, tabidxs: []dvui.TabIndex, base_tig: Id, in_focus_group: bool) void {
    const cw = currentWindow();
    var widgetId = focusedWidgetId();
    var oldtab: ?u16 = null;
    var tig: Id = base_tig;
    var newId: ?Id = null;
    var ran_off: bool = false;
    var first: bool = true;
    outer: while (true) {
        if (widgetId != null) {
            for (tabidxs) |ti| {
                if (ti.windowId == cw.subwindows.focused_id and ti.widgetId == widgetId.?) {
                    oldtab = ti.tabIndex;
                    tig = ti.tab_index_group;
                    break;
                }
            }
        }

        if (first and !in_focus_group and oldtab == null) {
            if (cw.subwindows.focused()) |sw| {
                if (sw.kb_restart_widget_id) |id| {
                    newId = id;
                    sw.kb_restart_widget_id = null;
                    break :outer;
                }
            }
        }
        first = false;

        if (ran_off and oldtab == null) {
            // We ran off the tab index group, but couldn't find the entry for
            // itself, return null.  This means we are in a focus group where
            // the tab index group we searched for is outside the focus group.
            break :outer;
        }

        ran_off = false;

        // find the first widget with a tabindex greater than oldtab
        // or the first widget with lowest tabindex if oldtab is null
        var newtab: u16 = math.maxInt(u16);
        var isTig: bool = false;
        var foundFocus = false;

        for (tabidxs) |ti| {
            if (ti.windowId == cw.subwindows.focused_id and ti.tab_index_group == tig) {
                if (ti.widgetId == widgetId) {
                    foundFocus = true;
                    continue;
                }

                if (ti.in_focus_group) continue;

                if (foundFocus == true and oldtab != null and ti.tabIndex == oldtab.?) {
                    // found the first widget after current that has the same tabindex
                    newtab = ti.tabIndex;
                    newId = ti.widgetId;
                    isTig = ti.tab_group;
                    break;
                } else if (oldtab == null or ti.tabIndex > oldtab.?) {
                    // tabidxs is ordered by insertion, not tab index, so have to
                    // search all of them to find the lowest that is above oldtab
                    if (newId == null or ti.tabIndex < newtab) {
                        newtab = ti.tabIndex;
                        newId = ti.widgetId;
                        isTig = ti.tab_group;
                    }
                }
            }
        }

        if (newId == null and tig != base_tig) {
            // ran off the end of the tab index group, recur starting at the
            // tab index group itself
            widgetId = tig;
            oldtab = null;
            ran_off = true;
            tig = base_tig;

            continue :outer;
        }

        if (isTig) {
            // we are moving into this tab index group
            widgetId = null;
            oldtab = null;
            tig = newId.?;
            newId = null;

            continue :outer;
        }

        break :outer;
    }

    focusWidget(newId, null, event_num);

    if (newId == null) {
        // intentionally moving to the null focus state, don't try to recover
        if (cw.subwindows.focused()) |sw| {
            sw.kb_restart_widget_id = null;
        }
    }
}