/* 总是将孩子节点加在子节点链的最右边 如果 obj 在对象树中 那么完成添加工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_insert_child(struct object* parent, struct object* child) { struct object* tree = NULL; if(NULL == parent) { return 0; } /* 父节点有右子节点 */ if(parent->rchild != NULL) { parent->rchild->parent = child; /* 父节点的右子节点作为自己的左子节点 */ child->lchild = parent->rchild; } child->parent = parent; parent->rchild = child; /* 找到这棵树根节点的父节点 */ tree = object_get_root(parent)->parent; /* child 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); return 0; }
void object_move_first(struct object* obj) { struct object * tree = NULL, * parent = NULL; /* 如果活动窗口不是顶层窗口也不是父窗口的右子节点 */ /* 将活动窗口变成父窗口的右子节点 */ if(obj == obj->parent->parent || obj == obj->parent->rchild) { return 0; } /* 找到 win_info_ptr 的父窗口 */ parent = obj->parent; while(parent == parent->parent->lchild) { parent = parent->parent; } parent = parent->parent; /* obj 有左子节点 */ /* obj 在末端 */ if(obj->lchild != NULL) { obj->lchild->parent = obj->parent; obj->parent->lchild = obj->lchild; } /* obj 没有左子节点 */ /* obj 在中间*/ else { obj->parent->lchild = NULL; } obj->lchild = parent->rchild; parent->rchild->parent =obj; obj->parent = parent; parent->rchild = obj; /* 找到这棵树根节点的父节点 */ tree = object_get_root(parent)->parent; /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); }
/* 总是将孩子节点加在子节点链的最左边 如果 obj 在对象树中 那么完成添加工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_attach_child(struct object * obj, struct object * child) { struct object * tree; /* parent 没有子对象 */ if(obj->rchild == NULL) { /* 作为上层对象的右子节点 */ obj->rchild = child; child->parent = obj; } else { obj = obj->rchild; /* 一直往左走 */ while(obj->lchild != NULL) { obj = obj->lchild; } /* 作为同层对象的左子节点 */ obj->lchild = child; child->parent = obj; } /* 找到这棵树根节点的父节点 */ /* 没有的话 tree == NULL */ tree = object_get_root(obj)->parent; /* obj 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } return 0; }
struct node_t *random_tree(ui_t count) { struct node_t *root = calloc(1, sizeof(struct node_t)); struct node_t *fakeroot = calloc(1, sizeof(struct node_t)); static struct node_t **nodes; ui_t i; root->obj.parent = &fakeroot->obj; fakeroot->obj.parent = &root->obj; fakeroot->obj.lchild = object_tree_l_most_node(&root->obj); fakeroot->obj.rchild = object_tree_r_most_node(&root->obj); nodes = calloc(count, sizeof(struct node_t *)); nodes[0] = root; nodes[0]->obj.id = 0; for (i = 1; i < count; i++) { struct node_t *par = nodes[rand() % i]; nodes[i] = calloc(1, sizeof(struct node_t)); nodes[i]->obj.id = i; object_attach_child(OBJECT_POINTER(par), OBJECT_POINTER(nodes[i])); } free(nodes); return root; }
/* 总是将孩子节点加在子节点链的最右边 如果 parent 在对象树中 那么完成添加工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t application_add_window(struct window * parent, struct window * window) { struct object node, * tree; /* 添加顶层窗口 */ if(parent == NULL) { /* node 的父节点是 window */ node.parent = OBJECT_POINTER(window); node.lchild = object_tree_l_most_node(OBJECT_POINTER(window)); node.rchild = object_tree_r_most_node(OBJECT_POINTER(window)); node.name = NULL; node.id = 0; /* 将窗口添加到向量 */ vector_push_back(&(global_application.window_vector), &node, sizeof(struct object)); tree = vector_back(&(global_application.window_vector)); /* window 的父节点是 node */ window->parent = tree; } /* 添加非顶层窗口 */ else { object_insert_child(OBJECT_POINTER(parent), OBJECT_POINTER(window)); } /** * if already running in app_exec **/ if(global_application.exec_flag) { union message msg; msg.base.type = MESSAGE_TYPE_WIDGET_REPAINT; msg.widget_repaint.area = window->area; if(global_application.focus != NULL) { struct window* w = WINDOW_POINTER(global_application.focus); struct object* tree, *node, *tree_real_parent; w->is_activated = 0; msg.widget_repaint.area = w->area; if(w->callback != NULL) { w->callback(w, &msg); } node = OBJECT_POINTER(w); tree = node->parent; tree_real_parent = tree->parent; tree->parent = node; node = object_tree_l_most_node(tree); while(node != NULL) { union message msg; msg.base.type = MESSAGE_TYPE_WIDGET_REPAINT; msg.widget_repaint.area = WIDGET_POINTER(node)->area; if(WIDGET_POINTER(node)->callback != NULL) WIDGET_POINTER(node)->callback(node, &msg); node = object_tree_iterator_increment(tree, node); } tree->parent = tree_real_parent; } window->descriptor = register_window((parent == NULL ? 0 : parent->descriptor), window->title, window->area.x, window->area.y, window->area.width, window->area.height, window->minimize_enable, window->maximize_enable, window->modal); if(window->descriptor == 0) { EGUI_PRINT_ERROR("failed to register window"); application_exit(); return -1; } /** * find icon for the application **/ if((window->icon_path = (char*)malloc(256)) == NULL) { EGUI_PRINT_SYS_ERROR("failed to malloc for icon path. malloc"); application_exit(); return -1; } else { /** * in C89 standard, snprintf() is NOT included in <stdio.h> * so you have to use sprintf, which may be dangerous. be careful **/ sprintf(window->icon_path, "%s/icons/%s.bmp", global_application.icon_root_path, global_application.name); if(access(window->icon_path, R_OK) == -1) { sprintf(window->icon_path, "%s/icons/default.bmp", global_application.icon_root_path); } } msg.widget_repaint.area = window->area; global_application.focus = window; window->is_activated = 1; if(window->callback != NULL) { window->callback(window, &msg); } } return 0; }
si_t object_delete(struct object* object, void(*destructor)(void*)) { if(object->parent->parent == object) { object_tree_for_each(object, destructor); } else { /* 找到这棵树根节点的父节点 */ struct object* tree = object_get_root(object)->parent; /* 是父节点的右子节点 */ if(object == object->parent->rchild) { /* object 没有左子节点 */ /* parent 的下一层对象只有 object */ if(object->lchild == NULL) { /* 清除父节点中的指针 */ object->parent->rchild = NULL; } /* object 有左子节点 */ /* parent 的下一层有多个对象 */ else { /* 处理 object 同层的对象 */ object->parent->rchild = object->lchild; object->lchild->parent = object->parent; /* 清空 object->lchild */ object->lchild = NULL; } } /* 是父节点的左子节点 */ /* 此时 parent 的下一层有多个对象 */ else if(object == object->parent->lchild) { /* object 没有左子节点 */ /* object 处于末端 */ if(object->lchild == NULL) { /* 清除父节点中的指针 */ object->parent->lchild = NULL; } /* object 有左子节点 */ /* object 处于中间 */ else { /* 处理 object 同层的对象 */ object->parent->lchild = object->lchild; object->lchild->parent = object->parent; /* 清空 object->lchild */ object->lchild = NULL; } } object_tree_for_each(object, destructor); /* 必须更新 root->parent 节点的 lchild 和 rchild */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } } return 0; }
/* 如果 obj 有左子节点 那么这个左子节点并不是 obj 子对象 所以在析构以 obj 为根的树之前一定要要将 obj->lchild 成员清空 如果 obj 在对象树中 那么完成删除工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_remove(struct object * obj) { struct object * tree; /* obj 有父对象 */ if(obj->parent != NULL) { /* 找到这棵树根节点的父节点 */ /* 没有的话 tree == NULL */ tree = object_get_root(obj)->parent; /* obj 是由父节点右子节点 */ if(obj == obj->parent->rchild) { /* obj 没有左子节点 */ /* parent 的下一层对象只有 obj */ if(obj->lchild == NULL) { /* 清除父节点中的指针 */ obj->parent->rchild = NULL; } /* obj 有左子节点 */ /* parent 的下一层有多个对象 */ else { /* 处理 obj 同层的对象 */ obj->parent->rchild = obj->lchild; obj->lchild->parent = obj->parent; /* 清空 obj->lchild */ obj->lchild = NULL; } } /* obj 是由父节点左子节点 */ /* 此时 parent 的下一层有多个对象 */ else if(obj == obj->parent->lchild) { /* obj 没有左子节点 */ /* obj 处于末端 */ if(obj->lchild == NULL) { /* 清除父节点中的指针 */ obj->parent->lchild = NULL; } /* obj 有左子节点 */ /* obj 处于中间 */ else { /* 处理 obj 同层的对象 */ obj->parent->lchild = obj->lchild; obj->lchild->parent = obj->parent; /* 清空 obj->lchild */ obj->lchild = NULL; } } /* 删除 obj 以及它的所有子对象 */ object_tree_free(obj); /* obj 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } } /* 没有父对象 */ else { /* 清空 obj->lchild */ obj->lchild = NULL; /* 删除 obj 以及它的所有子对象 */ object_tree_free(obj); } return 0; }