Skip to content

Commit c9d8ded

Browse files
committed
feat(gui): add TextEdit_BindProperty()
1 parent 0d3fb68 commit c9d8ded

File tree

3 files changed

+75
-12
lines changed

3 files changed

+75
-12
lines changed

include/LCUI/gui/widget_base.h

+5
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,11 @@ LCUI_API int Widget_SetRules(LCUI_Widget w, const LCUI_WidgetRulesRec *rules);
461461
/** Set widget content text */
462462
LCUI_API void Widget_SetText(LCUI_Widget w, const char *text);
463463

464+
/* Bind an object to a widget property, and the widget property is automatically
465+
* updated when the value of the object changes */
466+
LCUI_API void Widget_BindProperty(LCUI_Widget w, const char *name,
467+
LCUI_Object value);
468+
464469
/** 计算部件的最大宽度 */
465470
LCUI_API float Widget_ComputeMaxWidth(LCUI_Widget w);
466471

src/gui/widget/textedit.c

+49-12
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,19 @@ typedef struct LCUI_TextEditRec_ {
6464
LCUI_TextLayer layer_mask; /**< 屏蔽后的文本层 */
6565
LCUI_TextLayer layer_placeholder; /**< 占位符的文本层 */
6666
LCUI_TextLayer layer; /**< 当前使用的文本层 */
67-
LCUI_Widget scrollbars[2]; /**< 两个滚动条 */
68-
LCUI_Widget caret; /**< 文本插入符 */
69-
LCUI_BOOL is_read_only; /**< 是否只读 */
70-
LCUI_BOOL is_multiline_mode; /**< 是否为多行模式 */
71-
LCUI_BOOL is_placeholder_shown; /**< 是否已经显示占位符 */
72-
wchar_t *allow_input_char; /**< 允许输入的字符 */
73-
wchar_t password_char; /**< 屏蔽符的副本 */
74-
size_t text_block_size; /**< 块大小 */
75-
LinkedList text_blocks; /**< 文本块缓冲区 */
76-
LinkedList text_tags; /**< 当前处理的标签列表 */
77-
LCUI_BOOL tasks[TASK_TOTAL]; /**< 待处理的任务 */
78-
LCUI_Mutex mutex; /**< 互斥锁 */
67+
LCUI_ObjectWatcher value_watcher;
68+
LCUI_Widget scrollbars[2]; /**< 两个滚动条 */
69+
LCUI_Widget caret; /**< 文本插入符 */
70+
LCUI_BOOL is_read_only; /**< 是否只读 */
71+
LCUI_BOOL is_multiline_mode; /**< 是否为多行模式 */
72+
LCUI_BOOL is_placeholder_shown; /**< 是否已经显示占位符 */
73+
wchar_t *allow_input_char; /**< 允许输入的字符 */
74+
wchar_t password_char; /**< 屏蔽符的副本 */
75+
size_t text_block_size; /**< 块大小 */
76+
LinkedList text_blocks; /**< 文本块缓冲区 */
77+
LinkedList text_tags; /**< 当前处理的标签列表 */
78+
LCUI_BOOL tasks[TASK_TOTAL]; /**< 待处理的任务 */
79+
LCUI_Mutex mutex; /**< 互斥锁 */
7980
} LCUI_TextEditRec, *LCUI_TextEdit;
8081

8182
typedef enum {
@@ -886,6 +887,7 @@ static void TextEdit_OnInit(LCUI_Widget w)
886887
edit->layer_source = TextLayer_New();
887888
edit->layer_placeholder = TextLayer_New();
888889
edit->layer = edit->layer_source;
890+
edit->value_watcher = NULL;
889891
edit->text_block_size = TEXT_BLOCK_SIZE;
890892
edit->caret = LCUIWidget_New("textcaret");
891893
w->computed_style.focusable = TRUE;
@@ -920,6 +922,10 @@ static void TextEdit_OnDestroy(LCUI_Widget widget)
920922
TextLayer_Destroy(edit->layer_mask);
921923
CSSFontStyle_Destroy(&edit->style);
922924
TextBlocks_Clear(&edit->text_blocks);
925+
if (edit->value_watcher) {
926+
ObjectWatcher_Delete(edit->value_watcher);
927+
edit->value_watcher = NULL;
928+
}
923929
}
924930

925931
static void TextEdit_OnPaint(LCUI_Widget w, LCUI_PaintContext paint,
@@ -973,6 +979,36 @@ static void TextEdit_OnUpdate(LCUI_Widget w)
973979
TextStyle_Destroy(&ts);
974980
}
975981

982+
static void TextEdit_OnValueChanged(LCUI_Object value, void *arg)
983+
{
984+
LCUI_Widget w = arg;
985+
986+
if (value->type == LCUI_StringObject) {
987+
TextEdit_SetText(w, value->value.string);
988+
} else if (value->type == LCUI_WStringObject) {
989+
TextEdit_SetTextW(w, value->value.wstring);
990+
}
991+
}
992+
993+
void TextEdit_BindProperty(LCUI_Widget w, const char *name, LCUI_Object value)
994+
{
995+
LCUI_TextEdit edit = Widget_GetData(w, self.prototype);
996+
997+
if (strcmp(name, "value") == 0) {
998+
if (edit->value_watcher) {
999+
ObjectWatcher_Delete(edit->value_watcher);
1000+
edit->value_watcher = NULL;
1001+
}
1002+
if (value) {
1003+
edit->value_watcher =
1004+
Object_Watch(value, TextEdit_OnValueChanged, w);
1005+
TextEdit_OnValueChanged(value, w);
1006+
} else {
1007+
TextEdit_ClearText(w);
1008+
}
1009+
}
1010+
}
1011+
9761012
void LCUIWidget_AddTextEdit(void)
9771013
{
9781014
self.prototype = LCUIWidget_NewPrototype("textedit", NULL);
@@ -981,6 +1017,7 @@ void LCUIWidget_AddTextEdit(void)
9811017
self.prototype->destroy = TextEdit_OnDestroy;
9821018
self.prototype->settext = TextEdit_OnParseText;
9831019
self.prototype->setattr = TextEdit_SetAttr;
1020+
self.prototype->bindprop = TextEdit_BindProperty;
9841021
self.prototype->autosize = TextEdit_AutoSize;
9851022
self.prototype->runtask = TextEdit_OnTask;
9861023
self.prototype->update = TextEdit_OnUpdate;

test/test_textedit.c

+21
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ int test_textedit(void)
99
{
1010
int ret = 0;
1111
LCUI_Widget w;
12+
LCUI_Object value;
1213
wchar_t wcs[64];
1314

1415
LCUI_InitFontLibrary();
@@ -44,7 +45,27 @@ int test_textedit(void)
4445
CHECK(wcslen(L"hello, world!") == TextEdit_GetTextW(w, 0, 64, wcs));
4546
CHECK(wcscmp(L"hello, world!", wcs) == 0);
4647

48+
// test property binding
49+
value = String_New("property name is 'value'");
50+
Widget_BindProperty(w, "value", value);
51+
Widget_Update(w);
52+
CHECK(wcslen(L"property name is 'value'") == TextEdit_GetTextW(w, 0, 64, wcs));
53+
CHECK(wcscmp(L"property name is 'value'", wcs) == 0);
54+
55+
// change property value
56+
String_SetValue(value, "hello");
57+
Widget_Update(w);
58+
CHECK(wcslen(L"hello") == TextEdit_GetTextW(w, 0, 64, wcs));
59+
CHECK(wcscmp(L"hello", wcs) == 0);
60+
61+
// unbind property
62+
Widget_BindProperty(w, "value", NULL);
63+
Widget_Update(w);
64+
CHECK(0 == TextEdit_GetTextLength(w));
65+
4766
Widget_Destroy(w);
67+
Object_Delete(value);
68+
4869
LCUI_FreeWidget();
4970
LCUI_FreeFontLibrary();
5071
return ret;

0 commit comments

Comments
 (0)