From b9392b04a0c8ac03f9bfd0aa9991dc7f8121b9ee Mon Sep 17 00:00:00 2001 From: lixianjing Date: Tue, 5 Nov 2019 16:18:27 +0800 Subject: [PATCH] support map key --- docs/README.md | 1 + docs/changes.md | 3 ++- src/base/enums.c | 16 +----------- src/base/widget.c | 39 +++++++++++++++++++++++++++++ src/tkc/utils.c | 58 +++++++++++++++++++++++++++++++++++++++++++- src/tkc/utils.h | 6 +++++ tests/utils_test.cc | 47 +++++++++++++++++++++++++++++++++++ tests/widget_test.cc | 47 +++++++++++++++++++++++++++++++++++ 8 files changed, 200 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index c27dfe9e9..8c1d4c6ae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -30,6 +30,7 @@ * [内存耗尽处理流程](out_of_memory.md) * [如何开启按键音](how_to_enable_key_touch_sound.md) * [实时切换主题](theme_switch.md) +* [键值映射](map_key.md) ### 2.HowTos * [AWTK 调试技巧](debug_tips.md) diff --git a/docs/changes.md b/docs/changes.md index 71a57a15d..b22760edc 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -5,7 +5,8 @@ * 修复native window resize时没有更新system info中lcd大小的问题(感谢朝泽提供补丁)。 * 修复文档中的错误(感谢朝泽提供补丁)。 * 完善旋转的处理(感谢智明提供补丁)。 - + * 增加键值映射功能,请参考[map\_key.md](map_key.md) + * 2019/11/04 * 完善字体和文字绘制。 diff --git a/src/base/enums.c b/src/base/enums.c index 093f1857c..374c8dcc1 100755 --- a/src/base/enums.c +++ b/src/base/enums.c @@ -378,27 +378,13 @@ const key_type_value_t* easing_type_find_by_value(uint32_t value) { return find_item_by_value(easing_type_name_value, ARRAY_SIZE(easing_type_name_value), value); } -static const char* key_name_fix(char fixed_name[TK_NAME_LEN + 1], const char* name) { - uint32_t len = strlen(name); - tk_strncpy(fixed_name, name, TK_NAME_LEN); - - if (len > 1) { - uint32_t i = 0; - for (i = 0; i < len; i++) { - fixed_name[i] = toupper(fixed_name[i]); - } - } - - return fixed_name; -} - const key_type_value_t* keys_type_find(const char* name) { char fixed_name[TK_NAME_LEN + 1]; return_value_if_fail(name != NULL, NULL); memset(fixed_name, 0x00, sizeof(fixed_name)); return find_item(keys_type_name_value, ARRAY_SIZE(keys_type_name_value), - key_name_fix(fixed_name, name)); + tk_normalize_key_name(name, fixed_name)); } const key_type_value_t* keys_type_find_by_value(uint32_t value) { diff --git a/src/base/widget.c b/src/base/widget.c index 50de5c294..4047b98d7 100644 --- a/src/base/widget.c +++ b/src/base/widget.c @@ -1633,6 +1633,43 @@ ret_t widget_dispatch_to_target(widget_t* widget, event_t* e) { return ret; } +static ret_t widget_map_key(widget_t* widget, key_event_t* e) { + value_t v; + const key_type_value_t* kv = NULL; + + if (widget->custom_props != NULL) { + kv = keys_type_find_by_value(e->key); + if (kv != NULL) { + const char* to = NULL; + char from[TK_NAME_LEN + 1] = {0}; + char fixed_name[TK_NAME_LEN + 1]; + + tk_snprintf(from, sizeof(from), "map_key:%s", kv->name); + if (object_get_prop(widget->custom_props, from, &v) == RET_OK) { + to = value_str(&v); + } else if (strlen(kv->name) > 1) { + tk_strcpy(fixed_name, kv->name); + tk_str_tolower(fixed_name); + tk_snprintf(from, sizeof(from), "map_key:%s", fixed_name); + if (object_get_prop(widget->custom_props, from, &v) == RET_OK) { + to = value_str(&v); + } + } + + if (to != NULL) { + return_value_if_fail(to != NULL, RET_FAIL); + kv = keys_type_find(to); + if (kv != NULL) { + e->key = kv->value; + log_debug("map key %s to %s\n", from, to); + } + } + } + } + + return RET_OK; +} + ret_t widget_dispatch_to_key_target(widget_t* widget, event_t* e) { ret_t ret = RET_OK; return_value_if_fail(widget != NULL && e != NULL, RET_BAD_PARAMS); @@ -1739,6 +1776,7 @@ ret_t widget_on_keydown(widget_t* widget, key_event_t* e) { ret_t ret = RET_OK; return_value_if_fail(widget != NULL && e != NULL, RET_BAD_PARAMS); + widget_map_key(widget, e); widget->can_not_destroy++; ret = widget_on_keydown_impl(widget, e); if (widget->feedback) { @@ -1807,6 +1845,7 @@ ret_t widget_on_keyup(widget_t* widget, key_event_t* e) { ret_t ret = RET_OK; return_value_if_fail(widget != NULL && e != NULL, RET_BAD_PARAMS); + widget_map_key(widget, e); widget->can_not_destroy++; ret = widget_on_keyup_impl(widget, e); if (widget->feedback) { diff --git a/src/tkc/utils.c b/src/tkc/utils.c index 70c8ef579..71efb4353 100644 --- a/src/tkc/utils.c +++ b/src/tkc/utils.c @@ -242,11 +242,13 @@ const char* tk_ftoa(char* str, int len, double value) { } char* tk_strcpy(char* dst, const char* src) { + return_value_if_fail(dst != NULL && src != NULL, NULL); + return strcpy(dst, src); } char* tk_strncpy(char* dst, const char* src, size_t len) { - return_value_if_fail(dst != NULL && src != NULL, dst); + return_value_if_fail(dst != NULL && src != NULL, NULL); strncpy(dst, src, len); dst[len] = '\0'; @@ -585,6 +587,22 @@ int32_t tk_str_cmp(const char* a, const char* b) { return strcmp(a, b); } +int32_t tk_str_icmp(const char* a, const char* b) { + if (a == b) { + return 0; + } + + if (a == NULL) { + return -1; + } + + if (b == NULL) { + return 1; + } + + return strcasecmp(a, b); +} + char* tk_str_copy(char* dst, const char* src) { if (src != NULL) { uint32_t size = strlen(src) + 1; @@ -729,3 +747,41 @@ int32_t tk_pointer_to_int(void* p) { void* tk_pointer_from_int(int32_t v) { return ((char*)NULL) + v; } + +char* tk_str_toupper(char* str) { + char* p = str; + return_value_if_fail(str != NULL, NULL); + + while (*p) { + *p = toupper(*p); + p++; + } + + return str; +} + +char* tk_str_tolower(char* str) { + char* p = str; + return_value_if_fail(str != NULL, NULL); + + while (*p) { + *p = tolower(*p); + p++; + } + + return str; +} + +const char* tk_normalize_key_name(const char* name, char fixed_name[TK_NAME_LEN + 1]) { + uint32_t len = NULL; + return_value_if_fail(name != NULL && fixed_name != NULL, NULL); + + len = strlen(name); + tk_strncpy(fixed_name, name, TK_NAME_LEN); + + if (len > 1) { + tk_str_toupper(fixed_name); + } + + return fixed_name; +} diff --git a/src/tkc/utils.h b/src/tkc/utils.h index 4ca7f3fa4..f26480912 100644 --- a/src/tkc/utils.h +++ b/src/tkc/utils.h @@ -32,6 +32,7 @@ bool_t tk_atob(const char* str); double tk_atof(const char* str); int32_t tk_str_cmp(const char* a, const char* b); +int32_t tk_str_icmp(const char* a, const char* b); int tk_watoi(const wchar_t* str); bool_t tk_watob(const wchar_t* str); @@ -42,6 +43,7 @@ const char* tk_itoa(char* str, int len, int n); const char* tk_ftoa(char* str, int len, double f); long tk_strtol(const char* str, const char** end, int base); +char* tk_strcpy(char* dst, const char* src); char* tk_strncpy(char* dst, const char* src, size_t len); char* tk_strdup(const char* str); wchar_t* tk_wstrdup(const wchar_t* str); @@ -82,6 +84,10 @@ const char* tk_under_score_to_camel(const char* name, char* out, uint32_t max_ou int32_t tk_pointer_to_int(void* p); void* tk_pointer_from_int(int32_t v); +char* tk_str_toupper(char* str); +char* tk_str_tolower(char* str); +const char* tk_normalize_key_name(const char* name, char fixed_name[TK_NAME_LEN + 1]); + END_C_DECLS #endif /*TK_UTILS_H*/ diff --git a/tests/utils_test.cc b/tests/utils_test.cc index d372eb1d5..e9a256e0d 100644 --- a/tests/utils_test.cc +++ b/tests/utils_test.cc @@ -306,3 +306,50 @@ TEST(Utils, tk_under_score_to_camel) { string("testObjGet")); ASSERT_EQ(string(tk_under_score_to_camel("test_obj_get", name, 7)), string("testObj")); } + +TEST(Utils, strcmp) { + ASSERT_EQ(tk_str_cmp("abc", "abc") == 0, true); + ASSERT_NE(tk_str_cmp("abc", "Abc") == 0, true); + ASSERT_EQ(tk_str_icmp("abc", "abc") == 0, true); + ASSERT_EQ(tk_str_icmp("abc", "Abc") == 0, true); +} + +TEST(Utils, tk_normalize_key_name) { + char fix_name[TK_NAME_LEN + 1]; + + tk_normalize_key_name("a", fix_name); + ASSERT_STREQ(fix_name, "a"); + + tk_normalize_key_name("A", fix_name); + ASSERT_STREQ(fix_name, "A"); + + tk_normalize_key_name("left", fix_name); + ASSERT_STREQ(fix_name, "LEFT"); + + tk_normalize_key_name("LEFT", fix_name); + ASSERT_STREQ(fix_name, "LEFT"); +} + +TEST(Utils, tk_str_toupper) { + char str[TK_NAME_LEN + 1]; + + tk_strcpy(str, "left"); + tk_str_toupper(str); + ASSERT_STREQ(str, "LEFT"); + + tk_strcpy(str, "Left"); + tk_str_toupper(str); + ASSERT_STREQ(str, "LEFT"); +} + +TEST(Utils, tk_str_tolower) { + char str[TK_NAME_LEN + 1]; + + tk_strcpy(str, "left"); + tk_str_tolower(str); + ASSERT_STREQ(str, "left"); + + tk_strcpy(str, "Left"); + tk_str_tolower(str); + ASSERT_STREQ(str, "left"); +} diff --git a/tests/widget_test.cc b/tests/widget_test.cc index 4c27337e4..e708e1bc0 100644 --- a/tests/widget_test.cc +++ b/tests/widget_test.cc @@ -1130,3 +1130,50 @@ TEST(Widget, off_by_tag) { widget_destroy(w); } + +static ret_t on_key_event(void* ctx, event_t* e) { + uint32_t* key = (uint32_t*)ctx; + + *key = ((key_event_t*)e)->key; + + return RET_OK; +} + +TEST(Widget, map_key) { + key_event_t e; + uint32_t key = 0; + widget_t* w = button_create(NULL, 0, 0, 0, 0); + + key_event_init(&e, EVT_KEY_DOWN, w, TK_KEY_s); + ASSERT_EQ(widget_on(w, EVT_KEY_DOWN, on_key_event, &key) > 0, TRUE); + + widget_on_keydown(w, &e); + ASSERT_EQ(key, TK_KEY_s); + + widget_set_prop_str(w, "map_key:s", "left"); + widget_on_keydown(w, &e); + ASSERT_EQ(key, TK_KEY_LEFT); + + widget_destroy(w); +} + +TEST(Widget, map_key1) { + key_event_t e; + uint32_t key = 0; + widget_t* w = button_create(NULL, 0, 0, 0, 0); + + ASSERT_EQ(widget_on(w, EVT_KEY_DOWN, on_key_event, &key) > 0, TRUE); + + widget_set_prop_str(w, "map_key:left", "pageup"); + widget_set_prop_str(w, "map_key:RIGHT", "PAGEDOWN"); + + key_event_init(&e, EVT_KEY_DOWN, w, TK_KEY_LEFT); + widget_on_keydown(w, &e); + ASSERT_EQ(key, TK_KEY_PAGEUP); + + key_event_init(&e, EVT_KEY_DOWN, w, TK_KEY_RIGHT); + widget_on_keydown(w, &e); + ASSERT_EQ(key, TK_KEY_PAGEDOWN); + + widget_destroy(w); +}