static si_t handle_window_cancel (union message * msg) { struct widget* w; w = application_widgets_for_each_increament(do_find_window, msg); if(w->callback != NULL) w->callback(w, msg); /* 如果要关闭主窗口 */ if(global_application.main_window == WINDOW_POINTER(w)) { application_del_window(WINDOW_POINTER(w)); } else { cancel_window(WINDOW_POINTER(w)->descriptor); application_del_window(WINDOW_POINTER(w)); /* 没有顶层窗口了 */ /* 退出程序 */ /* 这是为了处理没有设置主窗口的情况 */ if(vector_size(&(global_application.window_vector)) == 0) { application_exit(); } /* 还有顶层窗口 */ else { application_widgets_for_each_increament(do_dispatch_repaint_event_to_all, NULL); } } return 0; }
/** * parse each widget * * @param w: pointer to widget * @param m: no use * @return: NULL **/ static struct widget* do_parse_widget(struct widget* w, union message* m) { NOT_USED(m); /** * record focusable widget **/ if(w->input_enable == 1) { list_push_back(&global_application.focus_list, &w, sizeof(w)); } /** * register window and update active window **/ if(w->is_window) { struct window* parent = (struct window*)object_parent(OBJECT_POINTER(w)); struct window* window_ptr = WINDOW_POINTER(w); si_t parent_descriptor = (parent == NULL ? 0 : parent->descriptor); si_t window_descriptor = register_window(parent_descriptor, window_ptr->title, window_ptr->area.x, window_ptr->area.y, window_ptr->area.width, window_ptr->area.height, window_ptr->minimize_enable, window_ptr->maximize_enable, window_ptr->modal); if(0 == window_descriptor) { EGUI_PRINT_ERROR("failed to register window %s", window_ptr->title); return NULL; } window_ptr->descriptor = window_descriptor; global_application.focus = window_ptr; /** * find icon for the application **/ if((window_ptr->icon_path = (char*)malloc(256)) == NULL) { EGUI_PRINT_ERROR("failed to register window"); return NULL; } 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_ptr->icon_path, "%s/icons/%s.bmp", global_application.icon_root_path, global_application.name); if(access(window_ptr->icon_path, R_OK) == -1) { sprintf(window_ptr->icon_path, "%s/icons/default.bmp", global_application.icon_root_path); } } } return NULL; }
static si_t handle_window_activate (union message * msg) { struct object* node; si_t n = 0, i = 0; node = OBJECT_POINTER(application_widgets_for_each_increament(do_find_window, msg)); if(node == NULL) { return 0; } object_move_first(node); if(global_application.focus != NULL) { dispatch_msg_to_subchilds(node, MESSAGE_TYPE_WINDOW_DEACTIVATE); } global_application.focus = WINDOW_POINTER(node); if(WIDGET_POINTER(node)->callback != NULL) { WIDGET_POINTER(node)->callback(node, msg); } dispatch_msg_to_subchilds(node, MESSAGE_TYPE_WIDGET_REPAINT); /** * 次序提前 **/ node = object_get_root(node)->parent; n = vector_size(&global_application.window_vector); for(i = 0; i < n; ++ i) { if(vector_at(&global_application.window_vector, i) == node) { vector_move_back(&global_application.window_vector, i); break; } } return 0; }
/** * dispatch msg to all subchild of a widget * * @param node: the widget * @param type: msg type * @return: 0 **/ static si_t dispatch_msg_to_subchilds(struct object* node, int type) { struct object* n, *t, *parent; /** * change the structure of the tree just for this **/ n = node; t = n->parent; parent = t->parent; t->parent = n; n = object_tree_l_most_node(t); while(n != NULL) { union message msg; /** * pack the message **/ if(type == MESSAGE_TYPE_WINDOW_DEACTIVATE) { msg.base.type = MESSAGE_TYPE_WINDOW_DEACTIVATE; } else if(type == MESSAGE_TYPE_WIDGET_REPAINT) { struct widget* w = WIDGET_POINTER(n); msg.widget_repaint.type = MESSAGE_TYPE_WIDGET_REPAINT; msg.widget_repaint.area = w->area; } else if(type == MESSAGE_TYPE_WINDOW_MINIMIZE || type == MESSAGE_TYPE_WINDOW_RESTORE) { msg.base.window_descriptor = WINDOW_POINTER(n)->descriptor; } if(WIDGET_POINTER(n)->callback != NULL) WIDGET_POINTER(n)->callback(n, &msg); n = object_tree_iterator_increment(t, n); } t->parent = parent; return 0; }
/* 总是将孩子节点加在子节点链的最右边 如果 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; }
/** * find the specific window and returns * * @param msg: pointer to msg * @return: 1 if found **/ static struct widget* do_find_window(struct widget* w, union message* msg) { if(w->is_window && msg->base.window_descriptor == WINDOW_POINTER(w)->descriptor) return w; return NULL; }