/** 追加子部件 */ int $(Append)( LCUI_Widget container, LCUI_Widget widget ) { int i, n; LCUI_Widget old_container; LCUI_WidgetEvent e; DEBUG_MSG("container: %p, widget: %p\n", container, widget); if( !container || !widget || container == widget->parent ) { return -1; } if( container == widget ) { return -2; } if( widget->parent ) { old_container = widget->parent; } else { goto remove_done; } /* 移除在之前的容器中的记录 */ n = LinkedList_GetTotal( &old_container->children ); for( i=0; i<n; ++i ) { LinkedList_Goto( &old_container->children, i ); if( LinkedList_Get(&old_container->children) == widget ) { LinkedList_Delete( &old_container->children ); break; } } /* 如果是从根级部件中移出,则触发 WET_REMOVE 事件 */ if( i < n && old_container == LCUIRootWidget ) { e.type_name = "TopLevelWidget"; e.target = widget; Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_REMOVE ); } n = LinkedList_GetTotal( &old_container->children_show ); for( i=0; i<n; ++i ) { LinkedList_Goto( &old_container->children_show, i ); if( LinkedList_Get(&old_container->children_show) == widget ) { LinkedList_Delete( &old_container->children_show ); break; } } remove_done: widget->parent = container; LinkedList_AddData( &container->children, widget ); LinkedList_AddData( &container->children_show, widget ); /* 如果是添加至根部件内,则触发 WET_ADD 事件 */ if( container == LCUIRootWidget ) { int ret; e.type_name = "TopLevelWidget"; e.target = widget; ret = Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_ADD ); DEBUG_MSG("post done, ret = %d\n", ret); } Widget_UpdateTaskStatus( widget ); DEBUG_MSG("tip\n"); return 0; }
/** 解除事件连接 */ int $(Unbind)( LCUI_EventBox box, int handler_id ) { int i, n; LCUI_RBTreeNode *node; LCUI_EventSlot *slot; LCUI_EventHandler *handler; if( !(node = RBTree_Search(&box->event_handler, handler_id)) ) { return -1; } if( !(node = RBTree_Search(&box->event_slot, (int)(node->data))) ) { return -2; } slot = (LCUI_EventSlot*)node->data; LinkedList_Goto( &slot->handlers, 0 ); n = LinkedList_GetTotal( &slot->handlers ); for( i=0; i<n; ++i ) { handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers ); if( handler->id == handler_id ) { LinkedList_Delete( &slot->handlers ); RBTree_Erase( &box->event_handler, handler_id ); return 0; } LinkedList_ToNext( &slot->handlers ); } return -3; }
static int LCUI_RunTask(void) { LCUI_Task *task, task_bak; LCUIMutex_Lock( &MainApp.task_run_mutex ); LCUIMutex_Lock( &MainApp.task_list_mutex ); task = (LCUI_Task*)LinkedList_Get( &MainApp.task_list ); if( !task ) { LCUIMutex_Unlock( &MainApp.task_list_mutex ); LCUIMutex_Unlock( &MainApp.task_run_mutex ); return -1; } if( !task->func ) { LinkedList_Delete( &MainApp.task_list ); LCUIMutex_Unlock( &MainApp.task_list_mutex ); LCUIMutex_Unlock( &MainApp.task_run_mutex ); return -2; } /* 备份该任务数据 */ task_bak = *task; /* 重置数据 */ task->func = NULL; task->arg[0] = NULL; task->arg[1] = NULL; task->destroy_arg[0] = FALSE; task->destroy_arg[1] = FALSE; /* 删除之 */ LinkedList_Delete( &MainApp.task_list ); /* 解锁,现在的任务数据已经与任务列表独立开了 */ LCUIMutex_Unlock( &MainApp.task_list_mutex ); /* 调用函数指针指向的函数,并传递参数 */ task_bak.func( task_bak.arg[0], task_bak.arg[1] ); /* 若需要在调用回调函数后销毁参数 */ if( task_bak.destroy_arg[0] && task_bak.arg[0] ) { if( task_bak.destroy_func[0] ) { task_bak.destroy_func[0]( task_bak.arg[0] ); } free( task_bak.arg[0] ); } if( task_bak.destroy_arg[1] && task_bak.arg[1] ) { if( task_bak.destroy_func[1] ) { task_bak.destroy_func[1]( task_bak.arg[1] ); } free( task_bak.arg[1] ); } LCUIMutex_Unlock( &MainApp.task_run_mutex ); return 0; }
/** 从已触发的事件记录中删除一个事件信息 */ int $(DeleteEvent)( LCUI_EventBox box ) { LinkedList *elist; elist = &box->events[box->current == 1 ? 0:1]; if( LinkedList_GetTotal( elist ) <= 0 ) { return -2; } LinkedList_Delete( elist ); return 0; }
static void LCUIDisplay_CleanSurfaces( void ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, 0 ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); Surface_Delete( p_sr->surface ); LinkedList_Delete( &display.surfaces ); } }
/** 解除 widget 与 sruface 的绑定 */ static void LCUIDisplay_UnbindSurface( LCUI_Widget widget ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( p_sr->widget != widget ) { continue; } Surface_Delete( p_sr->surface ); LinkedList_Delete( &display.surfaces ); break; } }
/** 更新各种图形元素的显示 */ static void LCUIDisplay_Update(void) { int i, n, j, m; LCUI_Rect *p_rect; SurfaceRecord *p_sr; LCUI_DirtyRectList rlist; LCUI_PaintContext paint; DirtyRectList_Init( &rlist ); n = LinkedList_GetTotal( &display.surfaces ); /* 遍历当前的 surface 记录列表 */ for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( !p_sr->widget || !p_sr->surface || !Surface_IsReady(p_sr->surface) ) { continue; } /* 更新表面 */ Surface_Update( p_sr->surface ); /* 收集无效区域记录 */ Widget_ProcInvalidArea( p_sr->widget, &rlist ); m = LinkedList_GetTotal( &rlist ); DEBUG_MSG("proc invalid area, m = %d\n", m); LinkedList_Goto( &rlist, 0 ); /* 在 surface 上逐个重绘无效区域 */ for( j=0; j<m; ++j ) { p_rect = (LCUI_Rect*)LinkedList_Get( &rlist ); paint = Surface_BeginPaint( p_sr->surface, p_rect ); DEBUG_MSG( "[%s]: render rect: (%d,%d,%d,%d), %d\n", p_sr->widget->type, paint->rect.left, paint->rect.top, paint->rect.w, paint->rect.h, j ); Widget_Render( p_sr->widget, paint ); Surface_EndPaint( p_sr->surface, paint ); LinkedList_Delete( &rlist ); } if( m > 0 ) { Surface_Present( p_sr->surface ); } } LinkedList_Destroy( &rlist ); }
/** 派发当前待处理的事件至对应的处理器 */ int $(Dispatch)( LCUI_EventBox box ) { int i, n; LCUI_Event *e; LinkedList *elist; box->current = box->current ? 0:1; elist = &box->events[box->current ? 0:1]; n = LinkedList_GetTotal( elist ); LinkedList_Goto( elist, 0 ); for( i=0; i<n; ++i ) { e = (LCUI_Event*)LinkedList_Get( elist ); $(Send)( box, e->name, e->data ); e->destroy_data ? e->destroy_data( e->data ):0; LinkedList_Goto( elist, 0 ); LinkedList_Delete( elist ); } box->current = box->current ? 0:1; return 0; }
/** 将指定标签的样式数据从队列中删除,只删除队列尾部第一个匹配的标签 */ static void StyleTagStack_Delete( LCUI_StyleTagStack *tags, LCUI_StyleTagID tag ) { int i, total; LCUI_StyleTagData *p; total = LinkedList_GetTotal( tags ); DEBUG_MSG("delete start, total tag: %d\n", total); if(total <= 0) { return; } for(i=total-1; i>=0; --i) { LinkedList_Goto( tags, i ); p = (LCUI_StyleTagData*)LinkedList_Get( tags ); if( p->tag_id == tag ) { LinkedList_Delete( tags ); break; } } DEBUG_MSG("delete end, total tag: %d\n", LinkedList_GetTotal( tags )); }
/** 派发当前待处理的事件至对应的处理器 */ int $(Dispatch)( LCUI_EventBox box ) { int i, n; LCUI_Event *e; LinkedList *elist; elist = &box->events[box->current]; box->current = box->current ? 0:1; n = LinkedList_GetTotal( elist ); LinkedList_Goto( elist, 0 ); DEBUG_MSG("event total: %d\n", n); for( i=0; i<n; ++i ) { e = (LCUI_Event*)LinkedList_Get( elist ); $(Send)( box, e->name, e->data ); e->destroy_data ? e->destroy_data( e->data ):0; e->data = NULL; LinkedList_Goto( elist, 0 ); LinkedList_Delete( elist ); } DEBUG_MSG("quit\n"); return 0; }
/** 从程序任务队列中删除有指定回调函数的任务 */ int LCUI_RemoveTask( CallBackFunc task_func, LCUI_BOOL need_lock ) { int n; LCUI_Task *exist_task; if( need_lock ) { LCUIMutex_Lock( &MainApp.task_list_mutex ); } n = LinkedList_GetTotal( &MainApp.task_list ); for ( ; n>0; --n ) { exist_task = (LCUI_Task*)LinkedList_Get( &MainApp.task_list ); if( exist_task && exist_task->func == task_func ) { LinkedList_Delete( &MainApp.task_list ); } else { LinkedList_ToNext( &MainApp.task_list ); } } if( need_lock ) { LCUIMutex_Unlock( &MainApp.task_list_mutex ); } return n; }
static int _Widget_ProcInvalidArea( LCUI_Widget w, LCUI_BOOL is_root, int x, int y, LCUI_Rect *valid_box, LCUI_DirtyRectList *rlist ) { int i, n, count; LCUI_Widget child; LCUI_Rect rect, child_box, *r; count = n = LinkedList_GetTotal( &w->dirty_rects ); /* 取出当前记录的脏矩形 */ for( i=0; i<n; ++i ) { LinkedList_Goto( &w->dirty_rects, 0 ); r = (LCUI_Rect*)LinkedList_Get( &w->dirty_rects ); /* 若有独立位图缓存,则重绘脏矩形区域 */ if( Graph_IsValid(&w->graph) ) { LCUI_PaintContextRec_ paint; paint.rect = *r; Graph_Quote( &paint.canvas, &w->graph, &paint.rect ); Widget_OnPaint( w, &paint ); } /* 转换为相对于父部件的坐标 */ rect.x = r->x; rect.y = r->y; /* 如果当前是根部件,则不用加上自身坐标 */ if( !is_root ) { rect.x += w->base.box.graph.x; rect.y += w->base.box.graph.y; } rect.w = r->w; rect.h = r->h; /* 取出与容器内有效区域相交的区域 */ if( LCUIRect_GetOverlayRect(&rect, valid_box, &rect) ) { /* 转换相对于根级部件的坐标 */ rect.x += x; rect.y += y; DirtyRectList_Add( rlist, &rect ); } LinkedList_Delete( &w->dirty_rects ); } /* 若子级部件没有脏矩形记录 */ if( !w->has_dirty_child ) { return count; } /* 缩小有效区域到当前部件内容框内,若没有重叠区域,则不向子级部件递归 */ if( !LCUIRect_GetOverlayRect(valid_box, &w->base.box.content, &child_box) ) { return count; } /* 转换有效区域的坐标,相对于当前部件的内容框 */ child_box.x -= w->base.box.content.x; child_box.y -= w->base.box.content.y; n = LinkedList_GetTotal( &w->children ); /* 向子级部件递归 */ for( i=0; i<n; ++i ) { child = (LCUI_Widget)LinkedList_Get( &w->children ); if( !child->style.visible ) { continue; } count += _Widget_ProcInvalidArea( child, FALSE, child->base.box.graph.x + x, child->base.box.graph.y + y, &child_box, rlist ); } return count; }
/** 运行目标主循环 */ int LCUI_MainLoop_Run( LCUI_MainLoop loop ) { if( loop->state == STATE_RUNNING ) { _DEBUG_MSG("error: main-loop already running."); return -1; } DEBUG_MSG("loop: %p, enter\n", loop); loop->state = STATE_RUNNING; /* 将主循环记录插入至列表表头 */ LinkedList_Goto( &MainApp.loop_list, 0 ); LinkedList_Insert( &MainApp.loop_list, loop ); MainApp.loop = loop; LCUIMutex_Lock( &MainApp.loop_changed ); /* 广播,让其它线程交出主循环运行权 */ LCUICond_Broadcast( &MainApp.loop_cond ); /* 获取运行权 */ LCUIMutex_Lock( &MainApp.loop_mutex ); LCUIMutex_Unlock( &MainApp.loop_changed ); loop->tid = LCUIThread_SelfID(); while( loop->state != STATE_EXITED ) { if( LinkedList_GetTotal(&MainApp.task_list) <= 0 ) { DEBUG_MSG("loop: %p, sleeping...\n", loop); LCUICond_TimedWait( &MainApp.loop_cond, 1000 ); DEBUG_MSG("loop: %p, wakeup\n", loop); /** 如果当前运行的主循环不是自己 */ if( MainApp.loop != loop ) { loop->state = STATE_PAUSED; DEBUG_MSG("loop: %p, release control.\n", loop); LCUIMutex_Unlock( &MainApp.loop_mutex ); /* 等待其它线程获得主循环运行权 */ LCUIMutex_Lock( &MainApp.loop_changed ); LCUIMutex_Unlock( &MainApp.loop_changed ); DEBUG_MSG("loop: %p, waiting...\n", loop); /* 等待其它线程释放主循环运行权 */ LCUIMutex_Lock( &MainApp.loop_mutex ); } continue; } DEBUG_MSG("loop: %p, run task.\n", loop); LCUI_RunTask(); } loop->state = STATE_EXITED; LinkedList_Goto( &MainApp.loop_list, 0 ); LinkedList_Delete( &MainApp.loop_list ); /* 获取处于列表表头的主循环 */ loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list ); if( loop ) { /* 改变当前运行的主循环 */ MainApp.loop = loop; LCUICond_Broadcast( &MainApp.loop_cond ); } /* 释放运行权 */ LCUIMutex_Unlock( &MainApp.loop_mutex ); /* 如果列表为空,一般意味着LCUI需要退出了 */ if( LinkedList_GetTotal( &MainApp.loop_list ) <= 0 ) { /** 广播,通知相关线程开始进行清理操作 */ LCUICond_Broadcast( &MainApp.loop_list_empty ); } DEBUG_MSG("loop: %p, exit\n", loop); return 0; }