support use tab/up/down key to change focused edit

This commit is contained in:
xianjimli 2019-03-20 17:24:30 +08:00
parent d802b180a9
commit 2227daeade
7 changed files with 168 additions and 3 deletions

View File

@ -6,6 +6,7 @@
* 修改关闭system\_bar时没有注销事件的BUG(感谢朝泽提供补丁)。 * 修改关闭system\_bar时没有注销事件的BUG(感谢朝泽提供补丁)。
* window支持fullscreen属性。 * window支持fullscreen属性。
* 修改edit缺省焦点的BUG。 * 修改edit缺省焦点的BUG。
* 支持用tab/up/down键切换编辑器焦点。
* 2019/03/19 * 2019/03/19
* 增加window\_close\_force函数。 * 增加window\_close\_force函数。

View File

@ -2082,3 +2082,79 @@ bool_t widget_is_keyboard(widget_t* widget) {
return FALSE; return FALSE;
} }
static bool_t widget_is_focusable(widget_t* widget) {
value_t v;
value_set_bool(&v, FALSE);
widget_get_prop(widget, WIDGET_PROP_FOCUSABLE, &v);
return value_bool(&v);
}
static ret_t widget_on_visit_focusable(void* ctx, const void* data) {
widget_t* widget = WIDGET(data);
darray_t* all_focusable = (darray_t*)ctx;
if (widget_is_focusable(widget)) {
darray_push(all_focusable, widget);
}
return RET_OK;
}
static ret_t widget_get_all_focusable_widgets_win(widget_t* widget, darray_t* all_focusable) {
widget_t* win = widget_get_window(widget);
return_value_if_fail(win != NULL, RET_BAD_PARAMS);
widget_foreach(win, widget_on_visit_focusable, all_focusable);
return RET_OK;
}
static ret_t widget_move_focus(widget_t* widget, bool_t next) {
uint32_t i = 0;
uint32_t focus = 0;
darray_t all_focusable;
return_value_if_fail(widget != NULL && widget->focused, RET_BAD_PARAMS);
return_value_if_fail(darray_init(&all_focusable, 10, NULL, NULL) != NULL, RET_OOM);
widget_get_all_focusable_widgets_win(widget, &all_focusable);
if (all_focusable.size > 1) {
for (i = 0; i < all_focusable.size; i++) {
widget_t* iter = WIDGET(all_focusable.elms[i]);
if (iter == widget) {
if (next) {
if ((i + 1) == all_focusable.size) {
focus = 0;
} else {
focus = i + 1;
}
} else {
if (i == 0) {
focus = all_focusable.size - 1;
} else {
focus = i - 1;
}
}
iter = WIDGET(all_focusable.elms[focus]);
widget_set_prop_bool(widget, WIDGET_PROP_FOCUS, FALSE);
widget_set_prop_bool(iter, WIDGET_PROP_FOCUS, TRUE);
break;
}
}
}
darray_deinit(&all_focusable);
return RET_OK;
}
ret_t widget_focus_prev(widget_t* widget) {
return widget_move_focus(widget, FALSE);
}
ret_t widget_focus_next(widget_t* widget) {
return widget_move_focus(widget, TRUE);
}

View File

@ -82,6 +82,12 @@ struct _widget_vtable_t {
* *
*/ */
uint32_t is_window : 1; uint32_t is_window : 1;
/**
* focusable
*
*>
*/
uint32_t is_focusable : 1;
/** /**
* *
*/ */
@ -1683,6 +1689,30 @@ ret_t widget_update_style(widget_t* widget);
*/ */
ret_t widget_set_as_key_target(widget_t* widget); ret_t widget_set_as_key_target(widget_t* widget);
/**
* @method widget_focus_next
*
*
*>widget必须是当前焦点控件
* @annotation ["private"]
* @param {widget_t*} widget widget对象
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_focus_next(widget_t* widget);
/**
* @method widget_focus_prev
*
*
*>widget必须是当前焦点控件
* @annotation ["private"]
* @param {widget_t*} widget widget对象
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_focus_prev(widget_t* widget);
/** /**
* @method widget_get_state_for_style * @method widget_get_state_for_style
* style选要的状态使 * style选要的状态使

View File

@ -647,6 +647,12 @@ BEGIN_C_DECLS
*/ */
#define WIDGET_PROP_FOCUS "focus" #define WIDGET_PROP_FOCUS "focus"
/**
* @const WIDGET_PROP_FOCUSABLE
*
*/
#define WIDGET_PROP_FOCUSABLE "focusable"
/** /**
* @enum widget_type_t * @enum widget_type_t
* @annotation ["scriptable", "string"] * @annotation ["scriptable", "string"]

View File

@ -597,9 +597,6 @@ ret_t window_manager_on_paint_children(widget_t* widget, canvas_t* c) {
widget_paint(iter, c); widget_paint(iter, c);
if (!has_fullscreen_win) { if (!has_fullscreen_win) {
has_fullscreen_win = is_window_fullscreen(iter); has_fullscreen_win = is_window_fullscreen(iter);
if (has_fullscreen_win) {
log_debug("%s is fullscreen\n", iter->name);
}
} }
} }
} }

View File

@ -427,6 +427,12 @@ static ret_t edit_on_key_down(widget_t* widget, key_event_t* e) {
} else { } else {
return edit_set_cursor_pos(widget, edit->cursor_pos + 1, edit->cursor_pos + 1); return edit_set_cursor_pos(widget, edit->cursor_pos + 1, edit->cursor_pos + 1);
} }
} else if (key == TK_KEY_TAB || key == TK_KEY_DOWN) {
widget_focus_next(widget);
return RET_OK;
} else if (key == TK_KEY_UP) {
widget_focus_prev(widget);
return RET_OK;
} else { } else {
if (system_info()->app_type != APP_DESKTOP && key < 128 && isprint(key)) { if (system_info()->app_type != APP_DESKTOP && key < 128 && isprint(key)) {
return edit_input_char(widget, (wchar_t)key); return edit_input_char(widget, (wchar_t)key);
@ -844,6 +850,9 @@ ret_t edit_get_prop(widget_t* widget, const char* name, value_t* v) {
} else if (tk_str_eq(name, WIDGET_PROP_TIPS)) { } else if (tk_str_eq(name, WIDGET_PROP_TIPS)) {
value_set_str(v, edit->tips); value_set_str(v, edit->tips);
return RET_OK; return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_FOCUSABLE)) {
value_set_bool(v, !(edit->readonly));
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_VALUE)) { } else if (tk_str_eq(name, WIDGET_PROP_VALUE)) {
value_set_wstr(v, widget->text.str); value_set_wstr(v, widget->text.str);
return RET_OK; return RET_OK;
@ -1225,6 +1234,7 @@ const char* s_edit_properties[] = {WIDGET_PROP_MIN,
NULL}; NULL};
TK_DECL_VTABLE(edit) = {.size = sizeof(edit_t), TK_DECL_VTABLE(edit) = {.size = sizeof(edit_t),
.type = WIDGET_TYPE_EDIT, .type = WIDGET_TYPE_EDIT,
.is_focusable = TRUE,
.clone_properties = s_edit_properties, .clone_properties = s_edit_properties,
.persistent_properties = s_edit_properties, .persistent_properties = s_edit_properties,
.parent = TK_PARENT_VTABLE(widget), .parent = TK_PARENT_VTABLE(widget),

View File

@ -164,3 +164,48 @@ TEST(Edit, focus) {
widget_destroy(w); widget_destroy(w);
} }
TEST(Edit, focus_next) {
widget_t* w = window_create(NULL, 0, 0, 400, 400);
widget_t* g = group_box_create(w, 0, 0, 400, 400);
widget_t* e1 = edit_create(g, 10, 20, 30, 40);
widget_t* e2 = edit_create(g, 10, 60, 30, 40);
widget_t* e3 = edit_create(g, 10, 90, 30, 40);
ASSERT_EQ(edit_set_focus(e1, TRUE), RET_OK);
ASSERT_EQ(g->key_target, e1);
ASSERT_EQ(widget_focus_next(e1), RET_OK);
ASSERT_EQ(g->key_target, e2);
ASSERT_EQ(widget_focus_next(e1), RET_BAD_PARAMS);
ASSERT_EQ(widget_focus_next(e2), RET_OK);
ASSERT_EQ(g->key_target, e3);
ASSERT_EQ(widget_focus_next(e3), RET_OK);
ASSERT_EQ(g->key_target, e1);
widget_destroy(w);
}
TEST(Edit, focus_prev) {
widget_t* w = window_create(NULL, 0, 0, 400, 400);
widget_t* g = group_box_create(w, 0, 0, 400, 400);
widget_t* e1 = edit_create(g, 10, 20, 30, 40);
widget_t* e2 = edit_create(g, 10, 60, 30, 40);
widget_t* e3 = edit_create(g, 10, 90, 30, 40);
ASSERT_EQ(edit_set_focus(e1, TRUE), RET_OK);
ASSERT_EQ(g->key_target, e1);
ASSERT_EQ(widget_focus_prev(e1), RET_OK);
ASSERT_EQ(g->key_target, e3);
ASSERT_EQ(widget_focus_prev(e1), RET_BAD_PARAMS);
ASSERT_EQ(widget_focus_prev(e3), RET_OK);
ASSERT_EQ(g->key_target, e2);
ASSERT_EQ(widget_focus_prev(e2), RET_OK);
ASSERT_EQ(g->key_target, e1);
widget_destroy(w);
}