Progress on GUI scrolling

This commit is contained in:
Allen Webster 2018-07-16 20:21:22 -07:00
parent af5d6c8360
commit 468a7a33bc
11 changed files with 308 additions and 161 deletions

View File

@ -737,6 +737,8 @@ STRUCT UI_List{
STRUCT UI_Control{
UI_Item *items;
int32_t count;
i32_Rect bounding_box;
};
/*

View File

@ -1509,16 +1509,27 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
int32_t line_height = (int32_t)view.line_height;
int32_t block_height = line_height*2;
int32_t hot_buffer_id = 0;
int32_t item_index = 0;
Temp_Memory temp = begin_temp_memory(scratch);
String text_field = push_string(scratch, 256);
Temp_Memory list_restore_point = begin_temp_memory(scratch);
for(;;){
end_temp_memory(list_restore_point);
Temp_Memory full_temp = begin_temp_memory(scratch);
refresh_view(app, &view);
Mouse_State mouse_state = get_mouse_state(app);
int32_t mx = mouse_state.x - view.file_region.x0 + (int32_t)view.scroll_vars.scroll_x;
int32_t my = mouse_state.y - view.file_region.y0 + (int32_t)view.scroll_vars.scroll_y;
int32_t y_pos = line_height;
UI_List list = {0};
int32_t item_index_counter = 0;
UI_Item *highlighted_item = 0;
UI_Item *hot_item = 0;
UI_Item *hovered_item = 0;
int32_t option_item_count = 0;
for (Buffer_Summary buffer = get_buffer_first(app, AccessAll);
buffer.exists;
get_buffer_next(app, &buffer, AccessAll)){
@ -1543,17 +1554,39 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
item.user_data = (void*)buffer.buffer_id;
item.activation_level = UIActivation_None;
item.rectangle = item_rect;
if (highlighted_item == 0){
item.activation_level = UIActivation_Hover;
UI_Item *item_ptr = ui_list_add_item(scratch, &list, item);
UI_Item *item_ptr = ui_list_add_item(scratch, &list, item);
option_item_count += 1;
if (item_rect.x0 <= mx && mx < item_rect.x1 &&
item_rect.y0 <= my && my < item_rect.y1){
hovered_item = item_ptr;
}
if (item_index_counter == item_index){
highlighted_item = item_ptr;
}
else{
ui_list_add_item(scratch, &list, item);
item_index_counter += 1;
if (buffer.buffer_id == hot_buffer_id){
hot_item = item_ptr;
}
}
}
if (hovered_item != 0){
hovered_item->activation_level = UIActivation_Hover;
}
if (hot_item != 0){
if (hot_item == hovered_item){
hot_item->activation_level = UIActivation_Active;
}
else{
hot_item->activation_level = UIActivation_Hover;
}
}
if (highlighted_item != 0){
highlighted_item->activation_level = UIActivation_Active;
}
{
i32_Rect item_rect = {0};
item_rect.x0 = x0;
@ -1566,6 +1599,7 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
item.type = UIType_TextField;
item.query = push_string_copy(scratch, "Switch: ");
item.string = text_field;
item.activation_level = UIActivation_Active;
item.user_data = 0;
item.rectangle = item_rect;
ui_list_add_item(scratch, &list, item);
@ -1574,45 +1608,94 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
UI_Control control = ui_list_to_ui_control(scratch, &list);
view_set_ui(app, &view, &control);
User_Input in = get_user_input(app, EventAll, EventOnEsc);
if (in.abort){
goto done;
}
UI_Item *activated_item = 0;
switch (in.type){
case UserInputKey:
{
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
activated_item = highlighted_item;
}
else if (in.key.keycode == key_back){
backspace_utf8(&text_field);
}
else{
uint8_t character[4];
uint32_t length = to_writable_character(in, character);
if (length > 0){
append(&text_field, make_string(character, length));
}
}
}break;
for (;;){
bool32 needs_full_update = false;
case UserInputMouse:
{
if (in.mouse.press_l){
int32_t mx = in.mouse.x - view.view_region.x0;
int32_t my = in.mouse.y - view.view_region.y0;
activated_item = ui_control_get_mouse_hit(&control, mx, my);
}
}break;
}
if (activated_item != 0){
int32_t buffer_id = (int32_t)activated_item->user_data;
view_set_buffer(app, &view, buffer_id, 0);
goto done;
User_Input in = get_user_input(app, EventAll, EventOnEsc);
if (in.abort){
goto done;
}
UI_Item *activated_item = 0;
switch (in.type){
case UserInputKey:
{
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
activated_item = highlighted_item;
}
else if (in.key.keycode == key_back){
backspace_utf8(&text_field);
needs_full_update = true;
item_index = 0;
}
else if (in.key.keycode == key_up || in.key.keycode == key_page_up){
item_index = item_index - 1;
if (item_index < 0){
item_index = 0;
}
needs_full_update = true;
}
else if (in.key.keycode == key_down || in.key.keycode == key_page_down){
item_index = item_index + 1;
if (item_index > option_item_count - 1){
item_index = option_item_count - 1;
}
needs_full_update = true;
}
else{
uint8_t character[4];
uint32_t length = to_writable_character(in, character);
if (length > 0){
append(&text_field, make_string(character, length));
needs_full_update = true;
item_index = 0;
}
}
}break;
case UserInputMouse:
{
if (in.mouse.wheel != 0){
GUI_Scroll_Vars scroll = view.scroll_vars;
scroll.target_y += in.mouse.wheel;
view_set_scroll(app, &view, scroll);
}
if (in.mouse.press_l || in.mouse.release_l){
int32_t mx = in.mouse.x - view.file_region.x0;
int32_t my = in.mouse.y - view.file_region.y0;
UI_Item *clicked = ui_control_get_mouse_hit(&control, mx, my);
if (in.mouse.press_l){
if (clicked != 0){
hot_buffer_id = (int32_t)clicked->user_data;
}
}
if (in.mouse.release_l){
if (clicked != 0){
if (hot_buffer_id == (int32_t)clicked->user_data){
activated_item = clicked;
}
}
hot_buffer_id = 0;
}
needs_full_update = true;
}
if (mx != in.mouse.x || my != in.mouse.y){
needs_full_update = true;
}
}break;
}
if (activated_item != 0){
int32_t buffer_id = (int32_t)activated_item->user_data;
view_set_buffer(app, &view, buffer_id, 0);
goto done;
}
if (needs_full_update){
goto full_update;
}
}
full_update:;
end_temp_memory(full_temp);
}
done:;

View File

@ -307,7 +307,7 @@ static Command_Metadata fcoder_metacmd_table[185] = {
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 42, 1062 },
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1492 },
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1339 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1625 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1708 },
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 58 },
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 74 },
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 66 },

View File

@ -17,22 +17,50 @@ static UI_Control
ui_list_to_ui_control(Partition *arena, UI_List *list){
UI_Control control = {0};
control.items = push_array(arena, UI_Item, list->count);
if (list->count > 0){
control.bounding_box = list->first->fixed.rectangle;
}
for (UI_Item_Node *node = list->first;
node != 0;
node = node->next){
control.items[control.count++] = node->fixed;
if (control.bounding_box.x0 > node->fixed.rectangle.x0){
control.bounding_box.x0 = node->fixed.rectangle.x0;
}
if (control.bounding_box.x1 < node->fixed.rectangle.x1){
control.bounding_box.x1 = node->fixed.rectangle.x1;
}
if (control.bounding_box.y0 > node->fixed.rectangle.y0){
control.bounding_box.y0 = node->fixed.rectangle.y0;
}
if (control.bounding_box.y1 < node->fixed.rectangle.y1){
control.bounding_box.y1 = node->fixed.rectangle.y1;
}
}
return(control);
}
static void
ui_control_set_top(UI_Control *control, int32_t top_y){
control->bounding_box.y0 = top_y;
}
static void
ui_control_set_bottom(UI_Control *control, int32_t bottom_y){
control->bounding_box.y1 = bottom_y;
}
static UI_Item*
ui_control_get_mouse_hit(UI_Control *control, int32_t mx, int32_t my){
int32_t count = control->count;
UI_Item *item = control->items + count - 1;
for (int32_t i = 0; i < count; ++i, item -= 1){
i32_Rect r = item->rectangle;
if (r.x0 <= mx && mx < r.x1 && r.y0 <= my && my < r.y1){
return(item);
if (control->bounding_box.x0 <= mx && mx < control->bounding_box.x1 &&
control->bounding_box.y0 <= my && my < control->bounding_box.y1){
int32_t count = control->count;
UI_Item *item = control->items + count - 1;
for (int32_t i = 0; i < count; ++i, item -= 1){
i32_Rect r = item->rectangle;
if (r.x0 <= mx && mx < r.x1 && r.y0 <= my && my < r.y1){
return(item);
}
}
}
return(0);

75
4ed.cpp
View File

@ -1868,51 +1868,46 @@ App_Step_Sig(app_step){
b32 active = (panel == active_panel);
Input_Summary summary = (active)?(active_input):(dead_input);
view->transient.changed_context_in_step = 0;
if (panel == mouse_panel && !input->mouse.out_of_window){
summary.mouse = mouse_state;
}
if (view->transient.changed_context_in_step == 0){
active = (panel == active_panel);
summary = (active)?(active_input):(dead_input);
if (panel == mouse_panel && !input->mouse.out_of_window){
summary.mouse = mouse_state;
}
b32 file_scroll = true;
GUI_Scroll_Vars *scroll_vars = &view->transient.edit_pos->scroll;
i32 max_y = 0;
if (view->transient.ui_mode_counter == 0){
max_y = view_compute_max_target_y(view);
GUI_Scroll_Vars *scroll_vars = 0;
i32 max_y = 0;
b32 file_scroll = false;
if (view->transient.ui_mode_counter == 0){
scroll_vars = &view->transient.edit_pos->scroll;
max_y = view_compute_max_target_y(view);
file_scroll = true;
}
else{
scroll_vars = &view->transient.ui_scroll;
i32 bottom = view->transient.ui_control.bounding_box.y1;
max_y = view_compute_max_target_y_from_bottom_y(view, (f32)bottom);
file_scroll = false;
}
Input_Process_Result ip_result = do_step_file_view(system, view, models, panel->inner, active, &summary, *scroll_vars, max_y);
if (ip_result.is_animating){
app_result.animating = true;
}
if (ip_result.consumed_l){
consume_input(&vars->available_input, Input_MouseLeftButton, "file view step");
}
if (ip_result.consumed_r){
consume_input(&vars->available_input, Input_MouseRightButton, "file view step");
}
if (memcmp(scroll_vars, &ip_result.scroll, sizeof(*scroll_vars)) != 0){
if (file_scroll){
view_set_scroll(system, view, ip_result.scroll);
}
else{
#if 0
max_y = view->transient.gui_max_y;
#endif
*scroll_vars = ip_result.scroll;
}
Input_Process_Result ip_result = do_step_file_view(system, view, models, panel->inner, active, &summary, *scroll_vars, view->transient.scroll_region, max_y);
if (ip_result.is_animating){
app_result.animating = 1;
}
if (ip_result.consumed_l){
consume_input(&vars->available_input, Input_MouseLeftButton, "file view step");
}
if (ip_result.consumed_r){
consume_input(&vars->available_input, Input_MouseRightButton, "file view step");
}
if (memcmp(scroll_vars, &ip_result.vars, sizeof(*scroll_vars)) != 0){
if (file_scroll){
view_set_scroll(system, view, ip_result.vars);
}
else{
*scroll_vars = ip_result.vars;
}
}
view->transient.scroll_region = ip_result.region;
}
}
}

View File

@ -86,7 +86,12 @@ fill_view_summary(System_Functions *system, View_Summary *view, View *vptr, Live
view->view_region = vptr->transient.panel->inner;
view->file_region = vptr->transient.file_region;
view->scroll_vars = vptr->transient.edit_pos->scroll;
if (vptr->transient.ui_mode_counter == 0){
view->scroll_vars = vptr->transient.edit_pos->scroll;
}
else{
view->scroll_vars = vptr->transient.ui_scroll;
}
}
}
@ -2001,7 +2006,12 @@ DOC_SEE(GUI_Scroll_Vars)
Assert(file != 0);
if (!file->is_loading){
result = true;
view_set_scroll(system, vptr, scroll);
if (vptr->transient.ui_mode_counter == 0){
view_set_scroll(system, vptr, scroll);
}
else{
vptr->transient.ui_scroll = scroll;
}
fill_view_summary(system, view, vptr, cmd);
}
}
@ -2228,7 +2238,7 @@ View_Set_UI(Application_Links *app, View_Summary *view, UI_Control *control){
if (vptr->transient.ui_control.items != 0){
general_memory_free(general, vptr->transient.ui_control.items);
}
vptr->transient.ui_control.count = 0;
memset(&vptr->transient.ui_control, 0, sizeof(vptr->transient.ui_control));
if (control->count > 0){
i32 memory_size = sizeof(UI_Item)*control->count;
vptr->transient.ui_control.items = (UI_Item*)general_memory_allocate(general, memory_size);
@ -2240,9 +2250,7 @@ View_Set_UI(Application_Links *app, View_Summary *view, UI_Control *control){
return(false);
}
}
else{
vptr->transient.ui_control.items = 0;
}
vptr->transient.ui_control.bounding_box = control->bounding_box;
return(true);
}
return(false);

View File

@ -657,5 +657,23 @@ fits_inside(i32_Rect rect, i32_Rect outer){
return(rect.x0 >= outer.x0 && rect.x1 <= outer.x1 && rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
}
static int32_t
interval_overlap(float a0, float a1, float b0, float b1){
if (a0 <= b0 && b0 < a1 ||
b0 <= a0 && a0 < b1){
return(true);
}
return(false);
}
static int32_t
rect_opverlap(f32_Rect a, f32_Rect b){
if (interval_overlap(a.x0, a.x1, b.x0, b.x1) &&
interval_overlap(a.y0, a.y1, b.y0, b.y1)){
return(true);
}
return(false);
}
// BOTTOM

View File

@ -74,6 +74,20 @@ draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){
draw_rectangle_outline(target, f32R(rect), color);
}
internal void
draw_margin(Render_Target *target, f32_Rect outer, f32_Rect inner, u32 color){
draw_rectangle(target, f32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
draw_rectangle(target, f32R(outer.x0, inner.y1, outer.x1, outer.y1), color);
draw_rectangle(target, f32R(outer.x0, inner.y0, inner.x0, inner.y1), color);
draw_rectangle(target, f32R(inner.x1, inner.y0, outer.x1, inner.y1), color);
}
inline void
draw_margin(Render_Target *target, f32_Rect outer, f32 width, u32 color){
f32_Rect inner = get_inner_rect(outer, width);
draw_margin(target, outer, inner, color);
}
internal void
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);

View File

@ -138,6 +138,14 @@ view_cursor_limits(View *view){
return(limits);
}
inline i32
view_compute_max_target_y_from_bottom_y(View *view, f32 max_item_y){
i32 line_height = view->transient.line_height;
f32 height = clamp_bottom((f32)line_height, view_height(view));
f32 max_target_y = clamp_bottom(0.f, max_item_y - height*0.5f);
return(ceil32(max_target_y));
}
inline i32
view_compute_max_target_y(View *view){
i32 line_height = view->transient.line_height;
@ -147,9 +155,7 @@ view_compute_max_target_y(View *view){
if (!file->settings.unwrapped_lines){
lowest_line = file->state.wrap_line_index[buffer->line_count];
}
f32 height = clamp_bottom((f32)line_height, view_height(view));
f32 max_target_y = clamp_bottom(0.f, ((lowest_line + 0.5f)*line_height) - height*0.5f);
return(ceil32(max_target_y));
return(view_compute_max_target_y_from_bottom_y(view, (lowest_line + 0.5f)*(f32)line_height));
}
inline u32

View File

@ -48,6 +48,7 @@ struct View_Transient{
i32 ui_mode_counter;
UI_Control ui_control;
GUI_Scroll_Vars ui_scroll;
b32 hide_scrollbar;
b32 hide_file_bar;
@ -184,14 +185,10 @@ struct View_Step_Result{
};
struct Input_Process_Result{
GUI_Scroll_Vars vars;
i32_Rect region;
GUI_Scroll_Vars scroll;
b32 is_animating;
b32 consumed_l;
b32 consumed_r;
b32 has_max_y_suggestion;
i32 max_y;
};
enum{

View File

@ -146,13 +146,11 @@ global_const Style_Color_Edit colors_to_edit[] = {
};
internal Input_Process_Result
do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect rect, b32 is_active, Input_Summary *user_input, GUI_Scroll_Vars vars, i32_Rect region, i32 max_y){
do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect rect, b32 is_active, Input_Summary *user_input, GUI_Scroll_Vars scroll, i32 max_y){
scroll.target_y = clamp(0, scroll.target_y, max_y);
Input_Process_Result result = {0};
vars.target_y = clamp(0, vars.target_y, max_y);
result.vars = vars;
result.region = region;
result.scroll = scroll;
i32 line_height = view->transient.line_height;
@ -166,8 +164,8 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
}
if (user_input->mouse.wheel != 0){
result.vars.target_y += user_input->mouse.wheel;
result.vars.target_y = clamp(0, result.vars.target_y, max_y);
result.scroll.target_y += user_input->mouse.wheel;
result.scroll.target_y = clamp(0, result.scroll.target_y, max_y);
result.is_animating = true;
}
@ -194,26 +192,23 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
target_y = clamp_bottom(0, floor32(cursor.y - height*.5f));
}
result.vars.target_y = target_y;
result.vars.scroll_y = (f32)target_y;
result.vars.prev_target_y = -1000;
result.scroll.target_y = target_y;
result.scroll.scroll_y = (f32)target_y;
result.scroll.prev_target_y = -1000;
result.vars.target_x = target_x;
result.vars.scroll_x = (f32)target_x;
result.vars.prev_target_x = -1000;
result.scroll.target_x = target_x;
result.scroll.scroll_x = (f32)target_x;
result.scroll.prev_target_x = -1000;
}
if (!file->is_loading && file->state.paste_effect.seconds_down > 0.f){
file->state.paste_effect.seconds_down -= user_input->dt;
result.is_animating = true;
}
result.has_max_y_suggestion = true;
result.max_y = view_compute_max_target_y(view);
}
{
GUI_Scroll_Vars scroll_vars = result.vars;
GUI_Scroll_Vars scroll_vars = result.scroll;
b32 is_new_target = (scroll_vars.target_x != scroll_vars.prev_target_x ||
scroll_vars.target_y != scroll_vars.prev_target_y);
@ -227,7 +222,7 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
scroll_vars.prev_target_x = scroll_vars.target_x;
scroll_vars.prev_target_y = scroll_vars.target_y;
result.vars = scroll_vars;
result.scroll = scroll_vars;
}
return(result);
@ -398,46 +393,47 @@ do_render_file_view(System_Functions *system, View *view, Models *models, GUI_Sc
}
}
else{
f32_Rect rect_f32 = f32R(rect);
i32 item_count = view->transient.ui_control.count;
UI_Item *item = view->transient.ui_control.items;
GUI_Scroll_Vars scroll = view->transient.ui_scroll;
for (i32 i = 0; i < item_count; ++i, item += 1){
switch (item->type){
case UIType_Option:
{
u32 back = style->main.back_color;
u32 margin = style_get_margin_color(item->activation_level, style);
u32 text_color = style->main.default_color;
u32 pop_color = style->main.file_info_style.pop2_color;
i32_Rect item_rect = item->rectangle;
item_rect.x0 += rect.x0;
item_rect.y0 += rect.y0;
item_rect.x1 += rect.x0;
item_rect.y1 += rect.y0;
i32_Rect inner = get_inner_rect(item_rect, 3);
draw_rectangle(target, inner, back);
draw_margin(target, item_rect, inner, margin);
i32 x = inner.x0 + 3;
i32 y = inner.y0 + line_height/2 - 1;
x = ceil32(draw_string(system, target, font_id, item->string, x, y, text_color));
draw_string(system, target, font_id, item->status, x, y, pop_color);
}break;
case UIType_TextField:
{
u32 back_color = style->main.margin_color;
u32 text1_color = style->main.default_color;
u32 text2_color = style->main.file_info_style.pop1_color;
i32_Rect item_rect = item->rectangle;
item_rect.x0 += rect.x0;
item_rect.y0 += rect.y0;
item_rect.x1 += rect.x0;
item_rect.y1 += rect.y0;
draw_rectangle(target, item_rect, back_color);
i32 x = item_rect.x0;
i32 y = item_rect.y0 + 2;
x = ceil32(draw_string(system, target, font_id, item->query, x, y, text2_color));
draw_string(system, target, font_id, item->string, x, y, text1_color);
}break;
f32_Rect item_rect = f32R(item->rectangle);
item_rect.x0 += rect_f32.x0 - scroll.scroll_x;
item_rect.y0 += rect_f32.y0 - scroll.scroll_y;
item_rect.x1 += rect_f32.x0 - scroll.scroll_x;
item_rect.y1 += rect_f32.y0 - scroll.scroll_y;
if (rect_opverlap(item_rect, rect_f32)){
switch (item->type){
case UIType_Option:
{
u32 back = style->main.back_color;
u32 margin_color = style_get_margin_color(item->activation_level, style);
u32 text_color = style->main.default_color;
u32 pop_color = style->main.file_info_style.pop2_color;
f32_Rect inner = get_inner_rect(item_rect, 3);
draw_rectangle(target, inner, back);
draw_margin(target, item_rect, inner, margin_color);
i32 x = (i32)inner.x0 + 3;
i32 y = (i32)inner.y0 + line_height/2 - 1;
x = ceil32(draw_string(system, target, font_id, item->string, x, y, text_color));
draw_string(system, target, font_id, item->status, x, y, pop_color);
}break;
case UIType_TextField:
{
u32 back_color = style->main.margin_color;
u32 text1_color = style->main.default_color;
u32 text2_color = style->main.file_info_style.pop1_color;
draw_rectangle(target, item_rect, back_color);
i32 x = (i32)item_rect.x0;
i32 y = (i32)item_rect.y0 + 2;
x = ceil32(draw_string(system, target, font_id, item->query, x, y, text2_color));
draw_string(system, target, font_id, item->string, x, y, text1_color);
}break;
}
}
}
}