diff --git a/docs/changes.md b/docs/changes.md index 2081ea46c..1170758dd 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,6 +1,7 @@ # 最新动态 * 2019/07/19 * Slider的图标用ICON方式绘制。 + * 增加属性with\_focus\_state,如果希望控件具有焦点状态,有不希望焦点停留,可以用本属性代替focusable属性。 * 2019/07/18 * gles的canvas画直线和画矩形边框的线宽问题,gles统一和agge一样为1线宽(感谢智明提供补丁)。 diff --git a/src/base/widget.c b/src/base/widget.c index 6373596fb..026865df8 100644 --- a/src/base/widget.c +++ b/src/base/widget.c @@ -55,18 +55,19 @@ static bool_t widget_is_scrollable(widget_t* widget) { return widget != NULL && widget->vt != NULL && widget->vt->scrollable; } -static bool_t widget_is_focusable(widget_t* widget) { +static bool_t widget_with_focus_state(widget_t* widget) { value_t v; return_value_if_fail(widget != NULL && widget->vt != NULL, FALSE); + value_set_bool(&v, FALSE); + widget_get_prop(widget, WIDGET_PROP_WITH_FOCUS_STATE, &v); - if (widget->vt->focusable) { - return TRUE; - } else { - value_set_bool(&v, FALSE); - widget_get_prop(widget, WIDGET_PROP_FOCUSABLE, &v); + return value_bool(&v); +} - return value_bool(&v); - } +static bool_t widget_is_focusable(widget_t* widget) { + return_value_if_fail(widget != NULL && widget->vt != NULL, FALSE); + + return widget->focusable || widget->vt->focusable; } ret_t widget_move(widget_t* widget, xy_t x, xy_t y) { @@ -457,7 +458,7 @@ const char* widget_get_state_for_style(widget_t* widget, bool_t active, bool_t c return WIDGET_STATE_DISABLE; } - if (widget_is_focusable(widget)) { + if (widget_is_focusable(widget) || widget_with_focus_state(widget)) { if (widget->focused) { if (tk_str_eq(state, WIDGET_STATE_NORMAL)) { state = WIDGET_STATE_FOCUSED; @@ -1141,6 +1142,10 @@ ret_t widget_set_prop(widget_t* widget, const char* name, const value_t* v) { widget->sensitive = value_bool(v); } else if (tk_str_eq(name, WIDGET_PROP_FLOATING)) { widget->floating = value_bool(v); + } else if (tk_str_eq(name, WIDGET_PROP_FOCUSABLE)) { + widget->focusable = value_bool(v); + } else if (tk_str_eq(name, WIDGET_PROP_WITH_FOCUS_STATE)) { + widget->with_focus_state = value_bool(v); } else if (tk_str_eq(name, WIDGET_PROP_STYLE)) { const char* name = value_str(v); return widget_use_style(widget, name); @@ -1213,6 +1218,10 @@ ret_t widget_get_prop(widget_t* widget, const char* name, value_t* v) { value_set_bool(v, widget->sensitive); } else if (tk_str_eq(name, WIDGET_PROP_FLOATING)) { value_set_bool(v, widget->floating); + } else if (tk_str_eq(name, WIDGET_PROP_FOCUSABLE)) { + value_set_bool(v, widget_is_focusable(widget)); + } else if (tk_str_eq(name, WIDGET_PROP_WITH_FOCUS_STATE)) { + value_set_bool(v, widget->with_focus_state); } else if (tk_str_eq(name, WIDGET_PROP_STYLE)) { value_set_str(v, widget->style); } else if (tk_str_eq(name, WIDGET_PROP_ENABLE)) { @@ -2170,6 +2179,9 @@ widget_t* widget_init(widget_t* widget, widget_t* parent, const widget_vtable_t* widget->key_target = NULL; widget->grab_widget = NULL; widget->grab_widget_count = 0; + widget->focused = FALSE; + widget->focusable = FALSE; + widget->with_focus_state = FALSE; if (parent) { widget_add_child(parent, widget); @@ -2216,6 +2228,10 @@ ret_t widget_get_prop_default_value(widget_t* widget, const char* name, value_t* value_set_bool(v, TRUE); } else if (tk_str_eq(name, WIDGET_PROP_FLOATING)) { value_set_bool(v, FALSE); + } else if (tk_str_eq(name, WIDGET_PROP_FOCUSABLE)) { + value_set_bool(v, FALSE); + } else if (tk_str_eq(name, WIDGET_PROP_WITH_FOCUS_STATE)) { + value_set_bool(v, FALSE); } else if (tk_str_eq(name, WIDGET_PROP_STYLE)) { value_set_str(v, NULL); } else if (tk_str_eq(name, WIDGET_PROP_ENABLE)) { @@ -2338,12 +2354,22 @@ ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c) { return RET_OK; } -static const char* s_widget_persistent_props[] = { - WIDGET_PROP_NAME, WIDGET_PROP_STYLE, WIDGET_PROP_TR_TEXT, - WIDGET_PROP_TEXT, WIDGET_PROP_ANIMATION, WIDGET_PROP_ENABLE, - WIDGET_PROP_VISIBLE, WIDGET_PROP_FLOATING, WIDGET_PROP_CHILDREN_LAYOUT, - WIDGET_PROP_SELF_LAYOUT, WIDGET_PROP_OPACITY, WIDGET_PROP_FOCUS, - WIDGET_PROP_FOCUSABLE, WIDGET_PROP_SENSITIVE, NULL}; +static const char* s_widget_persistent_props[] = {WIDGET_PROP_NAME, + WIDGET_PROP_STYLE, + WIDGET_PROP_TR_TEXT, + WIDGET_PROP_TEXT, + WIDGET_PROP_ANIMATION, + WIDGET_PROP_ENABLE, + WIDGET_PROP_VISIBLE, + WIDGET_PROP_FLOATING, + WIDGET_PROP_CHILDREN_LAYOUT, + WIDGET_PROP_SELF_LAYOUT, + WIDGET_PROP_OPACITY, + WIDGET_PROP_FOCUS, + WIDGET_PROP_FOCUSABLE, + WIDGET_PROP_WITH_FOCUS_STATE, + WIDGET_PROP_SENSITIVE, + NULL}; const char** widget_get_persistent_props(void) { return s_widget_persistent_props; diff --git a/src/base/widget.h b/src/base/widget.h index decf12865..a74699764 100644 --- a/src/base/widget.h +++ b/src/base/widget.h @@ -291,6 +291,21 @@ struct _widget_t { * 是否接受用户事件。 */ uint8_t sensitive : 1; + /** + * @property {bool_t} focusable + * @annotation ["set_prop","get_prop","readable","writable","persitent","design","scriptable"] + * 是否支持焦点停留。 + */ + uint8_t focusable : 1; + + /** + * @property {bool_t} with_focus_state + * @annotation ["set_prop","get_prop","readable","writable","persitent","design","scriptable"] + * 是否支持焦点状态。 + * > 如果希望style支持焦点状态,但有不希望焦点停留,可用本属性。 + */ + uint8_t with_focus_state : 1; + /** * @property {bool_t} focused * @annotation ["readable"] diff --git a/src/base/widget_animator.c b/src/base/widget_animator.c index d20cc696d..67d575916 100644 --- a/src/base/widget_animator.c +++ b/src/base/widget_animator.c @@ -275,6 +275,7 @@ ret_t widget_animator_destroy(widget_animator_t* animator) { if (animator->destroy != NULL) { return animator->destroy(animator); } else { + memset(animator, 0x00, sizeof(widget_animator_t)); TKMEM_FREE(animator); } diff --git a/src/base/widget_consts.h b/src/base/widget_consts.h index fa7cf64c6..3f9703b58 100644 --- a/src/base/widget_consts.h +++ b/src/base/widget_consts.h @@ -683,6 +683,12 @@ BEGIN_C_DECLS */ #define WIDGET_PROP_FOCUSABLE "focusable" +/** + * @const WIDGET_PROP_WITH_FOCUS_STATE + * 是否支持焦点状态(如果希望style支持焦点状态,但有不希望焦点停留,可用本属性)。 + */ +#define WIDGET_PROP_WITH_FOCUS_STATE "with_focus_state" + /** * @const WIDGET_PROP_MOVE_FOCUS_NEXT_KEY * 将焦点移到下一个的键值。 diff --git a/src/widgets/slider.c b/src/widgets/slider.c index 4042fe378..14b4927c1 100644 --- a/src/widgets/slider.c +++ b/src/widgets/slider.c @@ -75,7 +75,7 @@ static ret_t slider_paint_dragger(widget_t* widget, canvas_t* c) { } else { image_name = style_get_str(style, STYLE_ID_ICON, NULL); if (image_name && image_manager_get_bitmap(image_manager(), image_name, &img) == RET_OK) { - r = rect_init(0, 0, img.w/ratio, img.h/ratio); + r = rect_init(0, 0, img.w / ratio, img.h / ratio); slider_get_dragger_rect(widget, &r); canvas_draw_image_ex(c, &img, IMAGE_DRAW_ICON, &r); } diff --git a/src/widgets/spin_box.c b/src/widgets/spin_box.c index 0c7d7948d..cb087ca56 100644 --- a/src/widgets/spin_box.c +++ b/src/widgets/spin_box.c @@ -30,6 +30,7 @@ widget_t* spin_box_create_self(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) TK_DECL_VTABLE(spin_box) = {.size = sizeof(spin_box_t), .type = WIDGET_TYPE_SPIN_BOX, .inputable = TRUE, + .focusable = TRUE, .clone_properties = s_edit_properties, .persistent_properties = s_edit_properties, .parent = TK_PARENT_VTABLE(edit), diff --git a/tests/widget_test.cc b/tests/widget_test.cc index 2138d0583..abdae89d5 100644 --- a/tests/widget_test.cc +++ b/tests/widget_test.cc @@ -1106,3 +1106,13 @@ TEST(Widget, mutable_style1) { widget_destroy(w); } + +TEST(Widget, with_focus_state) { + widget_t* w = window_create(NULL, 0, 0, 400, 300); + + ASSERT_EQ(widget_get_prop_bool(w, WIDGET_PROP_WITH_FOCUS_STATE, FALSE), FALSE); + ASSERT_EQ(widget_set_prop_str(w, WIDGET_PROP_WITH_FOCUS_STATE, "true"), RET_OK); + ASSERT_EQ(widget_get_prop_bool(w, WIDGET_PROP_WITH_FOCUS_STATE, FALSE), TRUE); + + widget_destroy(w); +}