diff --git a/gui/gui.c b/gui/gui.c index d7a92ee..5318e14 100644 --- a/gui/gui.c +++ b/gui/gui.c @@ -127,7 +127,6 @@ typedef enum { } GUI_Layout_Direction; typedef struct GUI_Node { - #define RDIC_GUI_NODE_MEMBER_NAME rdic_node RDIC_Node rdic_node; GUI_Style *style; GUI_String text_string; // Optional. @@ -156,18 +155,19 @@ typedef struct GUI_Node { #define GUI_NODE_FIRST_CHILD(node) ((GUI_Node*)(node)->rdic_node.first_child) typedef union GUI_Node_Reference { - RDIC_Node_Reference rdic; + RDIC_Node_Reference rdic_ref; struct { GUI_Node *node; unsigned int generation; }; } GUI_Node_Reference; -#define gui_node_references_equal(n, m) rdic_node_references_equal((n).rdic,(m).rdic) #if 0 +#define gui_node_references_equal(n, m) rdic_node_references_equal((n).rdic_ref,(m).rdic_ref) +#else // NOTE(Zelaven): This was just for debugging with better debug messages. -int _gui_node_references_equal(GUI_Node_Reference n, GUI_Node_Reference m) +int gui_node_references_equal(GUI_Node_Reference n, GUI_Node_Reference m) { - return rdic_node_references_equal(n.rdic,m.rdic); + return rdic_node_references_equal(n.rdic_ref, m.rdic_ref); } #endif @@ -183,10 +183,10 @@ typedef struct { typedef struct GUI_Subtree GUI_Subtree; struct GUI_Subtree { + // NOTE(Zelaven): We are maintaining an immediate interface of subtrees too. + RDIC_Node rdic_node; + RDIC_Context rdic; - GUI_Subtree *prev; - GUI_Subtree *next; - GUI_Subtree *structural_parent; // TODO(Zelaven): // GUI_Rectangle cliprect; @@ -199,13 +199,23 @@ struct GUI_Subtree { int offset_own_size_percentage_x; int offset_own_size_percentage_y; }; +typedef union GUI_Subtree_Reference { + RDIC_Node_Reference rdic_ref; + struct { + GUI_Subtree *node; + unsigned int generation; + }; +} GUI_Subtree_Reference; typedef struct { - GUI_Subtree *first_subtree; + RDIC_Context subtree_rdic; + //GUI_Subtree *first_subtree; //GUI_Subtree *last_subtree; //GUI_Subtree *current_subtree; + GUI_Subtree_Reference root_subtree; + GUI_Draw_Command *first_draw_command; int num_draw_commands; Pixel_Buffer pixel_buffer; @@ -217,11 +227,13 @@ typedef struct { //GUI_Subtree *first_subtree; //GUI_Subtree *last_subtree; - GUI_Subtree *current_subtree; + //GUI_Subtree *current_subtree; GUI_Layer background_layer; GUI_Layer top_layer; + GUI_Layer *current_layer; + GUI_Node_Reference focused_node; GUI_Node_Reference hovered_node; GUI_Node_Reference top_node_under_cursor; @@ -231,7 +243,8 @@ typedef struct { int mouse_y; // TODO: An allocator for the nodes. - RDIC_Node *node_freelist; + RDIC_Freelist *node_freelist; + RDIC_Freelist *subtree_freelist; Memory_Arena *draw_command_arena; int num_draw_commands; @@ -328,6 +341,13 @@ void gui_apply_input( GUI_Context *context, int mouse_x, int mouse_y) +{ + (void)context; + (void)mouse_x; + (void)mouse_y; + return; +} +#if 0 { // --- Mouse Input --- // NOTE(Zelaven): First hit test against layers. @@ -371,6 +391,7 @@ void gui_apply_input( top_node_under_cursor->debug_string.length, top_node_under_cursor->debug_string.cstring); } +#endif GUI_Node_Reference gui_get_node( @@ -380,10 +401,17 @@ GUI_Node_Reference gui_get_node( GUI_Style *style, GUI_Size size[static 2]) { + GUI_Layer *current_layer = context->current_layer; + if(current_layer == NULL) { + return (GUI_Node_Reference){0}; + } + GUI_Subtree *current_subtree = + (GUI_Subtree*)current_layer->subtree_rdic.frame_current_node; int get_node_flags = 0; GUI_Node_Reference new_reference = { - .rdic = rdic_get_node( - &context->current_subtree->rdic, last_reference.rdic, &get_node_flags), + .rdic_ref = rdic_get_node( + //&context->current_subtree->rdic, last_reference.rdic, &get_node_flags), + ¤t_subtree->rdic, last_reference.rdic_ref, &get_node_flags), }; GUI_Node *node = new_reference.node; node->layout_direction = direction; @@ -407,9 +435,70 @@ GUI_Node_Reference gui_get_node( node->dirty = (get_node_flags & RDIC_GET_NODE__NODE_ALLOCATED) != 0; + return new_reference; +} +GUI_Subtree_Reference gui_get_subtree( + GUI_Context *context, + GUI_Subtree_Reference last_reference) +{ + GUI_Layer *current_layer = context->current_layer; + if(current_layer == NULL) { + return (GUI_Subtree_Reference){0}; + } + RDIC_Context *subtree_rdic = ¤t_layer->subtree_rdic; + RDIC_Node *old_subtree_freelist_head = subtree_rdic->freelist->head; + int get_node_flags = 0; + GUI_Subtree_Reference new_reference = { + .rdic_ref = rdic_get_node( + //&context->current_subtree->rdic, last_reference.rdic, &get_node_flags), + subtree_rdic, last_reference.rdic_ref, &get_node_flags), + }; + GUI_Subtree *subtree = new_reference.node; + subtree->rdic = (RDIC_Context){0}; + subtree->relative_to = (GUI_Node_Reference){0}; + subtree->flat_offset_x = 0; + subtree->flat_offset_y = 0; + subtree->offset_relative_node_percentage_x = 0; + subtree->offset_relative_node_percentage_y = 0; + subtree->offset_own_size_percentage_x = 0; + subtree->offset_own_size_percentage_y = 0; + + // TODO(Zelaven): + // get_node_flags & RDIC_GET_NODE__OUT_OF_FREELIST + // ^ This should result in an attempt to allocate more nodes for the freelist. + // Then rdic_get_node should be retried. + + if(get_node_flags & RDIC_GET_NODE__NODES_COLLECTED) + { + // NOTE(Zelaven): Some subtrees were collected, which means that their RDIC + // node trees should be collected too. + for( + RDIC_Node *i = subtree_rdic->freelist->head; + i != old_subtree_freelist_head; + i = i->sibling) + { + GUI_Subtree *subtree = (GUI_Subtree*)i; + rdic_cull_subtrees(&subtree->rdic, subtree->rdic.root); + } + } + +#if 0 + if(get_node_flags & RDIC_GET_NODE__NODES_COLLECTED) + { + GUI_NODE_PARENT(node)->dirty = true; + } + if(get_node_flags & RDIC_GET_NODE__NODE_ALLOCATED) + { + GUI_NODE_PARENT(node)->dirty = true; + } + node->dirty = (get_node_flags & RDIC_GET_NODE__NODE_ALLOCATED) != 0; +#endif + + return new_reference; } + #undef ENABLE_DEBUG #define ENABLE_DEBUG 0 // TODO(Zelaven): Make this cause redrawing of root on parameter change. @@ -438,16 +527,34 @@ GUI_Node_Reference gui_context_start_frame( context->mouse_x, context->mouse_y, context->mouse_pressed, context->mouse_down); - static GUI_Subtree background_subtree = {0}; - background_subtree.rdic.node_freelist = context->node_freelist; - context->background_layer.first_subtree = &background_subtree; + context->current_layer = &context->background_layer; + + GUI_Subtree_Reference root_subtree = context->current_layer->root_subtree; + //root_subtree = gui_get_subtree(context, root_subtree); + root_subtree.rdic_ref = rdic_context_start_frame( + &context->current_layer->subtree_rdic, root_subtree.rdic_ref); + if(root_subtree.node == NULL) + { + return (GUI_Node_Reference){0}; + } + context->current_layer->root_subtree = root_subtree; + root_subtree.node->rdic.freelist = context->node_freelist; + + //static GUI_Subtree background_subtree = {0}; + //background_subtree.rdic.freelist = context->node_freelist; + //context->background_layer.first_subtree = &background_subtree; //context->background_layer.last_subtree = &background_subtree; - context->current_subtree = &background_subtree; + //context->current_subtree = &background_subtree; GUI_Node_Reference new_root_reference = { - .rdic = rdic_context_start_frame( - &background_subtree.rdic, last_root_reference.rdic) + .rdic_ref = rdic_context_start_frame( + //&background_subtree.rdic, last_root_reference.rdic) + &root_subtree.node->rdic, last_root_reference.rdic_ref) }; + if(new_root_reference.node == NULL) + { + return (GUI_Node_Reference){0}; + } //RDIC_Node_Reference new_root_reference = rdic_context_start_frame( // &background_subtree.rdic, // last_root_reference); @@ -475,35 +582,38 @@ GUI_Node_Reference gui_context_start_frame( void gui_context_finish_frame( GUI_Context *context) { - rdic_context_finish_frame(&context->background_layer.first_subtree->rdic); - context->node_freelist = - context->background_layer.first_subtree->rdic.node_freelist; + //rdic_context_finish_frame(&context->background_layer.first_subtree->rdic); + rdic_context_finish_frame(&context->background_layer.root_subtree.node->rdic); + //context->node_freelist = + // context->background_layer.first_subtree->rdic.node_freelist; } GUI_Node_Reference gui_push_subtree( GUI_Context *context, - GUI_Subtree *subtree, + GUI_Subtree_Reference subtree, GUI_Node_Reference last_root_reference, GUI_Layout_Direction layout_direction, GUI_Style *style, GUI_Size size[static 2], GUI_Node_Reference relative_to) { - context->node_freelist = context->current_subtree->rdic.node_freelist; - subtree->rdic.node_freelist = context->node_freelist; + RDIC_Context *layer_rdic_context = &context->current_layer->subtree_rdic; + rdic_push_parent(layer_rdic_context, subtree.rdic_ref); + //context->node_freelist = context->current_subtree->rdic.node_freelist; + //subtree->rdic.node_freelist = context->node_freelist; // NOTE(Zelaven): Well, not being able to do this is a problem... //context->last_subtree->next = subtree; //subtree->prev = context->last_subtree; //context->last_subtree = subtree; - subtree->structural_parent = context->current_subtree; - context->current_subtree = subtree; - subtree->relative_to = relative_to; + //subtree->structural_parent = context->current_subtree; + //context->current_subtree = subtree; + subtree.node->relative_to = relative_to; GUI_Node_Reference new_root_reference = { - .rdic = rdic_context_start_frame( - &subtree->rdic, last_root_reference.rdic) + .rdic_ref = rdic_context_start_frame( + &subtree.node->rdic, last_root_reference.rdic_ref) }; GUI_Node *root = (GUI_Node*)new_root_reference.node; root->dirty = false; @@ -526,9 +636,12 @@ GUI_Node_Reference gui_push_subtree( void gui_pop_subtree( GUI_Context *context) { - context->node_freelist = context->current_subtree->rdic.node_freelist; - context->current_subtree = context->current_subtree->structural_parent; - context->current_subtree->rdic.node_freelist = context->node_freelist; + //context->node_freelist = context->current_subtree->rdic.node_freelist; + //context->current_subtree = context->current_subtree->structural_parent; + //context->current_subtree->rdic.node_freelist = context->node_freelist; + + RDIC_Context *layer_rdic_context = &context->current_layer->subtree_rdic; + rdic_pop_parent(layer_rdic_context); } @@ -536,13 +649,19 @@ void gui_push_parent( GUI_Context *context, GUI_Node_Reference parent) { - rdic_push_parent(&context->current_subtree->rdic, parent.rdic); + GUI_Layer *current_layer = context->current_layer; + GUI_Subtree *current_subtree = + (GUI_Subtree*)current_layer->subtree_rdic.frame_current_node; + rdic_push_parent(¤t_subtree->rdic, parent.rdic_ref); } void gui_pop_parent( GUI_Context *context) { - rdic_pop_parent(&context->current_subtree->rdic); + GUI_Layer *current_layer = context->current_layer; + GUI_Subtree *current_subtree = + (GUI_Subtree*)current_layer->subtree_rdic.frame_current_node; + rdic_pop_parent(¤t_subtree->rdic); } @@ -1431,6 +1550,7 @@ void test_gui__draw_command_using_sliders( } +#if 0 void test_gui__subtree( GUI_Context *context, GUI_Rectangle full_gui_rectangle) @@ -1544,6 +1664,7 @@ void test_gui__subtree( gui_context_finish_frame(context); } +#endif #if 0 @@ -2749,8 +2870,21 @@ void init_node_freelist(GUI_Node *nodes, int node_count) } nodes[node_count-1].rdic_node = (RDIC_Node){0}; } +void init_subtree_freelist(GUI_Subtree *nodes, int subtree_count) +{ + // NOTE(Zelaven): We special-case the last node. + for(int i = 0; i < subtree_count -1; i++) + { + nodes[i] = (GUI_Subtree){0}; + nodes[i].rdic_node = (RDIC_Node){ + .sibling = &((nodes+i+1)->rdic_node), + }; + } + nodes[subtree_count-1].rdic_node = (RDIC_Node){0}; +} GUI_Node g_gui_node_freelist[128]; +GUI_Subtree g_gui_subtree_freelist[16]; @@ -3026,11 +3160,11 @@ int main(void) // GUI initializaiton. - //gui = test_gui; + gui = test_gui; //gui = test_gui__calculator; //gui = test_gui__scrollbars; //gui = test_gui__draw_command_using_sliders; - gui = test_gui__subtree; + //gui = test_gui__subtree; X11_Window xwindow = {0}; int xinit_status = init_x11(&xwindow); @@ -3050,7 +3184,18 @@ int main(void) context.rdic.node_freelist = &g_gui_node_freelist[0].rdic_node; #else init_node_freelist(g_gui_node_freelist, ARRAYLENGTH(g_gui_node_freelist)); - context.node_freelist = &g_gui_node_freelist[0].rdic_node; + RDIC_Freelist node_freelist = {&g_gui_node_freelist[0].rdic_node}; + context.node_freelist = &node_freelist; + init_subtree_freelist(g_gui_subtree_freelist, ARRAYLENGTH(g_gui_subtree_freelist)); + RDIC_Freelist subtree_freelist = {&g_gui_subtree_freelist[0].rdic_node}; + context.subtree_freelist = &subtree_freelist; + + context.background_layer = (GUI_Layer){ + .subtree_rdic.freelist = &subtree_freelist, + }; + context.top_layer = (GUI_Layer){ + .subtree_rdic.freelist = &subtree_freelist, + }; #endif context.draw_command_arena = &draw_command_arena; @@ -3190,9 +3335,9 @@ int main(void) //gui_layout_nodes(&context); #if 1 for( - GUI_Subtree *current = context.background_layer.first_subtree; + GUI_Subtree *current = (GUI_Subtree*)context.background_layer.subtree_rdic.root; current != NULL; - current = current->next) + current = NULL)//current->next) { gui_layout_nodes((GUI_Node*)current->rdic.root); gui_generate_draw_commands(