4coder/4ed_gui.cpp

300 lines
6.6 KiB
C++

/*
* Mr. 4th Dimention - Allen Webster
*
* 20.02.2016
*
* GUI system for 4coder
*
*/
// TOP
struct Query_Slot{
Query_Slot *next;
Query_Bar *query_bar;
};
struct Query_Set{
Query_Slot slots[8];
Query_Slot *free_slot;
Query_Slot *used_slot;
};
internal void
init_query_set(Query_Set *set){
Query_Slot *slot = set->slots;
int i;
set->free_slot = slot;
set->used_slot = 0;
for (i = 0; i+1 < ArrayCount(set->slots); ++i, ++slot){
slot->next = slot + 1;
}
}
internal Query_Slot*
alloc_query_slot(Query_Set *set){
Query_Slot *slot = set->free_slot;
if (slot != 0){
set->free_slot = slot->next;
slot->next = set->used_slot;
set->used_slot = slot;
}
return(slot);
}
internal void
free_query_slot(Query_Set *set, Query_Bar *match_bar){
Query_Slot *slot = 0, *prev = 0;
for (slot = set->used_slot; slot != 0; slot = slot->next){
if (slot->query_bar == match_bar) break;
prev = slot;
}
if (slot){
if (prev){
prev->next = slot->next;
}
else{
set->used_slot = slot->next;
}
slot->next = set->free_slot;
set->free_slot = slot;
}
}
struct Super_Color{
Vec4 hsla;
Vec4 rgba;
u32 *out;
};
struct GUI_Target{
Partition push;
b32 show_file;
};
struct GUI_Header{
i32 type;
i32 size;
};
#define NextHeader(h) ((GUI_Header*)((char*)(h) + (h)->size))
enum GUI_Command_Type{
guicom_null,
guicom_begin_overlap,
guicom_end_overlap,
guicom_begin_serial,
guicom_end_serial,
guicom_top_bar,
guicom_file,
};
internal b32
gui_push_command(GUI_Target *target, void *item, i32 size){
b32 result = 0;
void *dest = partition_allocate(&target->push, size);
if (dest){
memcpy(dest, item, size);
result = 1;
}
return(result);
}
internal b32
gui_push_simple_command(GUI_Target *target, i32 type){
b32 result;
GUI_Header item;
item.type = type;
item.size = sizeof(item);
result = gui_push_command(target, &item, item.size);
return(result);
}
internal void
gui_begin_top_level(GUI_Target *target){
target->show_file = 0;
}
internal void
gui_end_top_level(GUI_Target *target){
gui_push_simple_command(target, guicom_null);
}
internal void
gui_begin_overlap(GUI_Target *target){
gui_push_simple_command(target, guicom_begin_overlap);
}
internal void
gui_end_overlap(GUI_Target *target){
gui_push_simple_command(target, guicom_end_overlap);
}
internal void
gui_begin_serial_section(GUI_Target *target){
gui_push_simple_command(target, guicom_begin_serial);
}
internal void
gui_end_serial_section(GUI_Target *target){
gui_push_simple_command(target, guicom_end_serial);
}
internal void
gui_do_top_bar(GUI_Target *target){
gui_push_simple_command(target, guicom_top_bar);
}
internal void
gui_do_file(GUI_Target *target){
gui_push_simple_command(target, guicom_file);
target->show_file = 1;
}
struct GUI_Section{
b32 overlapped;
i32 v;
i32 max_v;
};
struct GUI_Session{
i32_Rect full_rect;
i32_Rect rect;
i32_Rect clip_rect;
i32 line_height;
GUI_Section sections[64];
i32 t;
};
internal void
gui_session_init(GUI_Session *session, i32_Rect full_rect, i32 line_height){
GUI_Section *section;
*session = {0};
session->full_rect = full_rect;
session->line_height = line_height;
section = &session->sections[0];
section->v = full_rect.y0;
section->max_v = full_rect.y0;
}
internal void
gui_section_end_item(GUI_Section *section, i32 v){
if (!section->overlapped){
section->v = v;
}
section->max_v = v;
}
internal b32
gui_interpret(GUI_Session *session, GUI_Header *h){
GUI_Section *section = 0;
GUI_Section *new_section = 0;
GUI_Section *prev_section = 0;
GUI_Section *end_section = 0;
b32 give_to_user = 0;
i32_Rect rect = {0};
i32 y = 0;
i32 end_v = -1;
Assert(session->t < ArrayCount(session->sections));
section = session->sections + session->t;
y = section->v;
if (y < session->full_rect.y1){
switch (h->type){
case guicom_null: Assert(0); break;
case guicom_begin_overlap:
++session->t;
Assert(session->t < ArrayCount(session->sections));
new_section = &session->sections[session->t];
new_section->overlapped = 1;
new_section->v = y;
break;
case guicom_end_overlap:
Assert(session->t > 0);
Assert(section->overlapped);
prev_section = &session->sections[--session->t];
end_v = section->max_v;
end_section = prev_section;
break;
case guicom_begin_serial:
++session->t;
Assert(session->t < ArrayCount(session->sections));
new_section = &session->sections[session->t];
new_section->overlapped = 0;
new_section->v = y;
break;
case guicom_end_serial:
Assert(session->t > 0);
Assert(!section->overlapped);
prev_section = &session->sections[--session->t];
end_v = section->max_v;
end_section = prev_section;
break;
case guicom_top_bar:
give_to_user = 1;
rect.y0 = y;
rect.y1 = rect.y0 + session->line_height + 2;
rect.x0 = session->full_rect.x0;
rect.x1 = session->full_rect.x1;
end_v = rect.y1;
end_section = section;
break;
case guicom_file:
give_to_user = 1;
rect.y0 = y;
rect.y1 = session->full_rect.y1;
rect.x0 = session->full_rect.x0;
rect.x1 = session->full_rect.x1;
end_v = rect.y1;
end_section = section;
break;
}
if (give_to_user){
GUI_Section *section = session->sections;
i32 max_v = 0;
i32 i = 0;
for (i = 0; i <= session->t; ++i, ++section){
if (section->overlapped){
max_v = Max(max_v, section->max_v);
}
}
session->rect = rect;
if (rect.y0 < max_v){
rect.y0 = max_v;
}
session->clip_rect = rect;
}
if (end_section){
gui_section_end_item(end_section, end_v);
}
}
return(give_to_user);
}
// BOTTOM