123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- /*
- * Copyright (c) 2019 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file view stack interface
- */
- #define LOG_MODULE_CUSTOMER
- #include <os_common_api.h>
- #include <ui_manager.h>
- #include <string.h>
- #include <assert.h>
- #include <view_stack.h>
- LOG_MODULE_REGISTER(view_stack, LOG_LEVEL_INF);
- typedef struct {
- /* view cache descripter */
- const view_cache_dsc_t *cache;
- /* view group descripter */
- const view_group_dsc_t *group;
- /* presenter of the view, used only when cache == NULL */
- const void *presenter;
- /* init focused view id */
- uint16_t id;
- /* init focused main view id for view cache */
- uint16_t main_id;
- } view_stack_data_t;
- typedef struct {
- view_stack_data_t data[CONFIG_VIEW_STACK_LEVEL];
- uint8_t num;
- uint8_t inited : 1;
- } view_stack_ctx_t;
- static view_stack_ctx_t view_stack;
- static OS_MUTEX_DEFINE(mutex);
- static int _view_stack_update(const view_stack_data_t *data, bool push_stack);
- static int _view_stack_jump(view_stack_data_t *old_data,
- const view_stack_data_t *new_data);
- int view_stack_init(void)
- {
- int res = 0;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.inited) {
- res = -EALREADY;
- goto out_unlock;
- }
- view_stack.inited = 1;
- out_unlock:
- os_mutex_unlock(&mutex);
- return res;
- }
- void view_stack_deinit(void)
- {
- os_mutex_lock(&mutex, OS_FOREVER);
- view_stack.inited = 0;
- os_mutex_unlock(&mutex);
- view_stack_clean();
- }
- uint8_t view_stack_get_num(void)
- {
- return view_stack.num;
- }
- uint16_t view_stack_get_top(void)
- {
- view_stack_data_t * top;
- uint16_t focused = VIEW_INVALID_ID;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.num == 0) {
- goto out_unlock;
- }
- top = &view_stack.data[view_stack.num - 1];
- if (top->cache) {
- focused = view_cache_get_focus_view();
- } else {
- focused = top->id;
- }
- out_unlock:
- os_mutex_unlock(&mutex);
- return focused;
- }
- const view_cache_dsc_t * view_stack_get_top_cache(void)
- {
- view_stack_data_t * top;
- const view_cache_dsc_t *dsc = NULL;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.num > 0) {
- top = &view_stack.data[view_stack.num - 1];
- dsc = top->cache;
- }
- os_mutex_unlock(&mutex);
- return dsc;
- }
- uint16_t view_stack_level_get_view_id(uint16_t level_id)
- {
- uint16_t focused = VIEW_INVALID_ID;
- os_mutex_lock(&mutex, OS_FOREVER);
- if(level_id < view_stack.num)
- focused = view_stack.data[level_id].id;
- os_mutex_unlock(&mutex);
- return focused;
- }
- void view_stack_clean(void)
- {
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.num > 0) {
- _view_stack_jump(&view_stack.data[view_stack.num - 1], NULL);
- view_stack.num = 0;
- }
- os_mutex_unlock(&mutex);
- }
- int view_stack_pop_home(void)
- {
- int res = -ENODATA;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.num <= 1) {
- goto out_unlock;
- }
- res = _view_stack_jump(&view_stack.data[view_stack.num - 1], &view_stack.data[0]);
- view_stack.num = 1;
- out_unlock:
- os_mutex_unlock(&mutex);
- return res;
- }
- int view_stack_pop(void)
- {
- int res = -ENODATA;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.num <= 1) {
- goto out_unlock;
- }
- res = _view_stack_jump(&view_stack.data[view_stack.num - 1],
- &view_stack.data[view_stack.num - 2]);
- view_stack.num--;
- out_unlock:
- os_mutex_unlock(&mutex);
- return res;
- }
- int view_stack_push_cache(const view_cache_dsc_t *dsc, uint16_t view_id)
- {
- return view_stack_push_cache2(dsc, view_id, VIEW_INVALID_ID);
- }
- int view_stack_push_cache2(const view_cache_dsc_t *dsc,
- uint16_t focus_view_id, uint16_t main_view_id)
- {
- view_stack_data_t data = {
- .cache = dsc,
- .group = NULL,
- .presenter = NULL,
- .id = focus_view_id,
- .main_id = main_view_id,
- };
- return _view_stack_update(&data, true);
- }
- int view_stack_push_group(const view_group_dsc_t *dsc)
- {
- view_stack_data_t data = {
- .cache = NULL,
- .group = dsc,
- .presenter = NULL,
- .id = dsc->vlist[dsc->idx],
- };
- return _view_stack_update(&data, true);
- }
- int view_stack_push_view(uint16_t view_id, const void *presenter)
- {
- view_stack_data_t data = {
- .cache = NULL,
- .group = NULL,
- .presenter = presenter,
- .id = view_id,
- };
- return _view_stack_update(&data, true);
- }
- int view_stack_jump_cache(const view_cache_dsc_t *dsc, uint16_t view_id)
- {
- return view_stack_jump_cache2(dsc, view_id, VIEW_INVALID_ID);
- }
- int view_stack_jump_cache2(const view_cache_dsc_t *dsc,
- uint16_t focus_view_id, uint16_t main_view_id)
- {
- view_stack_data_t data = {
- .cache = dsc,
- .group = NULL,
- .presenter = NULL,
- .id = focus_view_id,
- .main_id = main_view_id,
- };
- return _view_stack_update(&data, false);
- }
- int view_stack_jump_group(const view_group_dsc_t *dsc)
- {
- view_stack_data_t data = {
- .cache = NULL,
- .group = dsc,
- .presenter = NULL,
- .id = dsc->vlist[dsc->idx],
- };
- return _view_stack_update(&data, false);
- }
- int view_stack_jump_view(uint16_t view_id, const void *presenter)
- {
- view_stack_data_t data = {
- .cache = NULL,
- .group = NULL,
- .presenter = presenter,
- .id = view_id,
- };
- return _view_stack_update(&data, false);
- }
- void view_stack_dump(void)
- {
- uint8_t i;
- int8_t idx;
- os_mutex_lock(&mutex, OS_FOREVER);
- os_printk("view stack:\n", view_stack.num);
- for (idx = view_stack.num - 1; idx >= 0; idx--) {
- if (view_stack.data[idx].cache) {
- os_printk("[%d] cache:\n", idx);
- os_printk("\t main(%u):", view_stack.data[idx].cache->num);
- for (i = 0; i < view_stack.data[idx].cache->num; i++) {
- os_printk(" %u", view_stack.data[idx].cache->vlist[i]);
- }
- os_printk("\n\t cross: %u %u\n", view_stack.data[idx].cache->cross_vlist[0],
- view_stack.data[idx].cache->cross_vlist[1]);
- } else if (view_stack.data[idx].group) {
- os_printk("[%d] group:", idx, view_stack.data[idx].group->num);
- for (i = 0; i < view_stack.data[idx].group->num; i++) {
- os_printk(" %u", i, view_stack.data[idx].group->vlist[i]);
- }
- os_printk("\n");
- } else {
- os_printk("[%d] view: %u\n", idx, view_stack.data[idx].id);
- }
- }
- os_printk("\n");
- os_mutex_unlock(&mutex);
- }
- static int _view_stack_update(const view_stack_data_t *data, bool push_stack)
- {
- view_stack_data_t *old_data = NULL;
- int res = 0;
- int new_idx;
- os_mutex_lock(&mutex, OS_FOREVER);
- if (view_stack.inited == 0) {
- res = -ESRCH;
- goto out_unlock;
- }
- if ((view_stack.num >= ARRAY_SIZE(view_stack.data)) && push_stack) {
- res = -ENOSPC;
- goto out_unlock;
- }
- if (view_stack.num > 0) {
- old_data = &view_stack.data[view_stack.num - 1];
- } else {
- push_stack = true;
- }
- res = _view_stack_jump(old_data, data);
- if (!res) {
- if (push_stack) {
- new_idx = view_stack.num ++;
- } else {
- new_idx = view_stack.num - 1;
- }
- memcpy(&view_stack.data[new_idx], data, sizeof(*data));
- }
- assert(res == 0);
- out_unlock:
- os_mutex_unlock(&mutex);
- return res;
- }
- static bool _view_group_has_view(const view_group_dsc_t *group, uint8_t view_id)
- {
- int i;
- for (i = group->num - 1; i >= 0; i--) {
- if (view_id == group->vlist[i])
- return true;
- }
- return false;
- }
- static void _view_group_scroll_cb(uint16_t view_id, uint8_t msg_id)
- {
- view_stack_data_t * data;
- if (msg_id != MSG_VIEW_SCROLL_END) {
- return;
- }
- os_mutex_lock(&mutex, OS_FOREVER);
- data = &view_stack.data[view_stack.num - 1];
- if (view_stack.num < 1 || data->group == NULL) {
- goto out_unlock;
- }
- if (data->group->scroll_cb)
- data->group->scroll_cb(view_id);
- out_unlock:
- os_mutex_unlock(&mutex);
- }
- static void _view_group_monitor_cb(uint16_t view_id, uint8_t msg_id, void *msg_data)
- {
- view_stack_data_t * data;
- os_mutex_lock(&mutex, OS_FOREVER);
- data = &view_stack.data[view_stack.num - 1];
- if (view_stack.num < 1 || data->group == NULL) {
- goto out_unlock;
- }
- if (_view_group_has_view(data->group, view_id) == false) {
- goto out_unlock;
- }
- if (msg_id == MSG_VIEW_FOCUS || msg_id == MSG_VIEW_DEFOCUS) {
- bool focused = (msg_id == MSG_VIEW_FOCUS);
- if (data->group->focus_cb)
- data->group->focus_cb(view_id, focused);
- if (focused)
- data->id = view_id;
- }
- out_unlock:
- os_mutex_unlock(&mutex);
- }
- static int _view_stack_jump(view_stack_data_t *old_data,
- const view_stack_data_t *new_data)
- {
- uint16_t old_view = VIEW_INVALID_ID;
- uint16_t new_view = VIEW_INVALID_ID;
- int8_t i;
- int res = 0;
- if (old_data) {
- if (old_data->cache) {
- old_view = view_cache_get_focus_view();
- old_data->id = old_view;
- old_data->main_id = view_cache_get_focus_main_view();
- if(!view_cache_deinit())
- {
- os_mutex_unlock(&mutex);
- view_cache_wait_last_focus_cb();
- os_mutex_lock(&mutex, OS_FOREVER);
- }
- } else if (old_data->group) {
- ui_manager_set_monitor_callback(NULL);
- if (old_data->group->scroll_cb)
- ui_manager_set_scroll_callback(NULL);
- old_view = old_data->id;
- for (i = old_data->group->num - 1; i >= 0; i--) {
- if (old_data->group->vlist[i] != old_view)
- ui_view_delete(old_data->group->vlist[i]);
- }
- /* delete the focused view at last to avoid unexpected focus changes */
- ui_view_delete(old_view);
- } else {
- old_view = old_data->id;
- ui_view_delete(old_data->id);
- }
- }
- if (new_data) {
- if (new_data->cache) {
- res = view_cache_init2(new_data->cache, new_data->id, new_data->main_id);
- } else if (new_data->group) {
- uint8_t idx = new_data->group->idx;
- ui_manager_set_monitor_callback(_view_group_monitor_cb);
- if (new_data->group->scroll_cb)
- ui_manager_set_scroll_callback(_view_group_scroll_cb);
- for (i = new_data->group->num - 1; i >= 0; i--) {
- if (new_data->group->vlist[i] == new_data->id) {
- idx = i;
- break;
- }
- }
- ui_view_create(new_data->group->vlist[idx],
- new_data->group->plist ? new_data->group->plist[idx] : NULL,
- UI_CREATE_FLAG_SHOW);
- for (i = new_data->group->num - 1; i >= 0; i--) {
- if (i != idx) {
- ui_view_create(new_data->group->vlist[i],
- new_data->group->plist ? new_data->group->plist[i] : NULL,
- 0);
- }
- }
- /* trigger first scroll_cb to notify app */
- if (new_data->group->scroll_cb)
- new_data->group->scroll_cb(new_data->group->vlist[idx]);
- } else {
- res = ui_view_create(new_data->id, new_data->presenter, UI_CREATE_FLAG_SHOW);
- }
- new_view = new_data->id;
- }
- SYS_LOG_INF("view_stack: jump %d -> %d (res=%d)", old_view, new_view, res);
- return res;
- }
|