3232#include <stdlib.h>
3333#include <errno.h>
3434#include <string.h>
35+ #include <assert.h>
3536#include <LCUI_Build.h>
3637#include <LCUI/LCUI.h>
3738#include <LCUI/gui/widget.h>
3839#include <LCUI/gui/metrics.h>
3940
4041static struct LCUI_WidgetModule {
41- LCUI_Widget root ; /**< 根级部件 */
4242 Dict * ids ; /**< 各种部件的ID索引 */
43- LCUI_Mutex mutex ; /**< 互斥锁 */
4443 DictType dt_ids ; /**< 部件ID映射表的类型模板 */
4544 DictType dt_attributes ; /**< 部件属性表的类型模板 */
45+
46+ LCUI_Widget root ; /**< 根级部件 */
47+ LCUI_Mutex mutex ; /**< 互斥锁 */
48+
49+ LinkedList trash ; /**< 待删除的部件列表 */
4650} LCUIWidget ;
4751
4852#define StrList_Destroy freestrs
@@ -103,6 +107,32 @@ static void Widget_UpdateStatus(LCUI_Widget widget)
103107 }
104108}
105109
110+ void LCUIWidget_ClearTrash (void )
111+ {
112+ LinkedListNode * node ;
113+ node = LCUIWidget .trash .head .next ;
114+ while (node ) {
115+ LinkedListNode * next = node -> next ;
116+ LinkedList_Unlink (& LCUIWidget .trash , node );
117+ Widget_ExecDestroy (node -> data );
118+ node = next ;
119+ }
120+ }
121+
122+ static void Widget_AddToTrash (LCUI_Widget w )
123+ {
124+ LCUI_WidgetEventRec e = { 0 };
125+ e .type = LCUI_WEVENT_UNLINK ;
126+ w -> state = LCUI_WSTATE_DELETED ;
127+ Widget_TriggerEvent (w , & e , NULL );
128+ if (!w -> parent ) {
129+ return ;
130+ }
131+ Widget_Unlink (w );
132+ LinkedList_AppendNode (& LCUIWidget .trash , & w -> node );
133+ Widget_PostSurfaceEvent (w , LCUI_WEVENT_UNLINK , TRUE);
134+ }
135+
106136int Widget_Unlink (LCUI_Widget widget )
107137{
108138 LCUI_Widget child ;
@@ -223,44 +253,47 @@ int Widget_Prepend(LCUI_Widget parent, LCUI_Widget widget)
223253
224254int Widget_Unwrap (LCUI_Widget widget )
225255{
226- int i ;
256+ size_t len ;
227257 LCUI_Widget child ;
228- LinkedList * list , * list_show ;
258+ LinkedList * children , * children_show ;
229259 LinkedListNode * target , * node , * prev , * snode ;
230260
231261 if (!widget -> parent ) {
232262 return -1 ;
233263 }
234- list = & widget -> parent -> children ;
235- list_show = & widget -> parent -> children_show ;
236- if (widget -> children .length > 0 ) {
264+ children = & widget -> parent -> children ;
265+ children_show = & widget -> parent -> children_show ;
266+ len = widget -> children .length ;
267+ if (len > 0 ) {
237268 node = LinkedList_GetNode (& widget -> children , 0 );
238269 Widget_RemoveStatus (node -> data , "first-child" );
239270 node = LinkedList_GetNodeAtTail (& widget -> children , 0 );
240271 Widget_RemoveStatus (node -> data , "last-child" );
241272 }
242273 node = & widget -> node ;
243- i = widget -> children .length ;
244274 target = node -> prev ;
245275 node = widget -> children .tail .prev ;
246- while (i -- > 0 ) {
276+ while (len > 0 ) {
277+ assert (node != NULL );
278+ assert (node -> data != NULL );
247279 prev = node -> prev ;
248280 child = node -> data ;
249281 snode = & child -> node_show ;
250282 LinkedList_Unlink (& widget -> children , node );
251283 LinkedList_Unlink (& widget -> children_show , snode );
252284 child -> parent = widget -> parent ;
253- LinkedList_Link (list , target , node );
254- LinkedList_AppendNode (list_show , snode );
285+ LinkedList_Link (children , target , node );
286+ LinkedList_AppendNode (children_show , snode );
255287 Widget_AddTaskForChildren (child , LCUI_WTASK_REFRESH_STYLE );
256288 Widget_UpdateTaskStatus (child );
257289 node = prev ;
290+ -- len ;
258291 }
259292 if (widget -> index == 0 ) {
260293 Widget_AddStatus (target -> next -> data , "first-child" );
261294 }
262- if (widget -> index == list -> length - 1 ) {
263- node = LinkedList_GetNodeAtTail (list , 0 );
295+ if (widget -> index == children -> length - 1 ) {
296+ node = LinkedList_GetNodeAtTail (children , 0 );
264297 Widget_AddStatus (node -> data , "last-child" );
265298 }
266299 Widget_Destroy (widget );
@@ -325,6 +358,11 @@ static void Widget_OnDestroy(void *arg)
325358void Widget_ExecDestroy (LCUI_Widget widget )
326359{
327360 LCUI_WidgetEventRec e = { LCUI_WEVENT_DESTROY , 0 };
361+
362+ if (widget -> parent ) {
363+ Widget_UpdateLayout (widget -> parent );
364+ Widget_Unlink (widget );
365+ }
328366 Widget_TriggerEvent (widget , & e , NULL );
329367 Widget_ReleaseMouseCapture (widget );
330368 Widget_ReleaseTouchCapture (widget , -1 );
@@ -340,9 +378,6 @@ void Widget_ExecDestroy(LCUI_Widget widget)
340378 StyleSheet_Delete (widget -> inherited_style );
341379 StyleSheet_Delete (widget -> custom_style );
342380 StyleSheet_Delete (widget -> style );
343- if (widget -> parent ) {
344- Widget_UpdateLayout (widget -> parent );
345- }
346381 if (widget -> title ) {
347382 free (widget -> title );
348383 widget -> title = NULL ;
@@ -361,6 +396,7 @@ void Widget_Destroy(LCUI_Widget w)
361396 while (root -> parent ) {
362397 root = root -> parent ;
363398 }
399+ /* If this widget is not mounted in the root widget tree */
364400 if (root != LCUIWidget .root ) {
365401 LCUI_WidgetEventRec e = { 0 };
366402 e .type = LCUI_WEVENT_UNLINK ;
@@ -372,8 +408,9 @@ void Widget_Destroy(LCUI_Widget w)
372408 if (w -> parent ) {
373409 LCUI_Widget child ;
374410 LinkedListNode * node ;
375- node = & w -> node ;
376- node = node -> next ;
411+
412+ /* Update the index of the siblings behind it */
413+ node = w -> node .next ;
377414 while (node ) {
378415 child = node -> data ;
379416 child -> index -= 1 ;
@@ -1727,6 +1764,7 @@ static void OnClearWidgetList(void *privdata, void *data)
17271764
17281765void LCUIWidget_InitBase (void )
17291766{
1767+ LinkedList_Init (& LCUIWidget .trash );
17301768 LCUIMutex_Init (& LCUIWidget .mutex );
17311769 LCUIWidget .root = LCUIWidget_New ("root" );
17321770 LCUIWidget .dt_ids = DictType_StringCopyKey ;
0 commit comments