Radio button group #101
|
@ -14,6 +14,7 @@ oc_canvas canvas;
|
|||
oc_font font;
|
||||
oc_ui_context ui;
|
||||
oc_arena textArena = { 0 };
|
||||
oc_ui_theme* theme = &OC_UI_DARK_THEME;
|
||||
|
||||
ORCA_EXPORT void oc_on_init(void)
|
||||
{
|
||||
|
@ -86,6 +87,7 @@ void widget_end_view(void)
|
|||
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||
{
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
oc_ui_set_theme(theme);
|
||||
|
||||
oc_ui_style defaultStyle = { .font = font };
|
||||
|
||||
|
@ -184,7 +186,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
|
|||
|
||||
oc_ui_container("up", OC_UI_FLAG_NONE)
|
||||
{
|
||||
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
|
||||
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.33 },
|
||||
.size.height = { OC_UI_SIZE_PARENT, 1 } },
|
||||
OC_UI_STYLE_SIZE);
|
||||
widget_view("Buttons")
|
||||
|
@ -205,7 +207,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
|
|||
}
|
||||
}
|
||||
|
||||
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
|
||||
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.33 },
|
||||
.size.height = { OC_UI_SIZE_PARENT, 1 } },
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
|
@ -219,6 +221,24 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
|
|||
oc_ui_checkbox("check2", &check2);
|
||||
oc_ui_checkbox("check3", &check3);
|
||||
}
|
||||
|
||||
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.33 },
|
||||
.size.height = { OC_UI_SIZE_PARENT, 1 } },
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
widget_view("Radio group")
|
||||
{
|
||||
static int radioSelected = 0;
|
||||
oc_str8 options[] = { OC_STR8("Dark theme"),
|
||||
OC_STR8("Light theme") };
|
||||
oc_ui_radio_group_info info = { .selectedIndex = radioSelected,
|
||||
.optionCount = 2,
|
||||
.options = options };
|
||||
|
||||
oc_ui_radio_group_info result = oc_ui_radio_group("radio_group", &info);
|
||||
radioSelected = result.selectedIndex;
|
||||
theme = radioSelected == 0 ? &OC_UI_DARK_THEME : &OC_UI_LIGHT_THEME;
|
||||
}
|
||||
}
|
||||
|
||||
oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
|
||||
|
|
137
src/ui/ui.c
137
src/ui/ui.c
|
@ -15,6 +15,7 @@
|
|||
#include "util/memory.h"
|
||||
|
||||
//NOTE(ilia): Design system by semi.design: https://semi.design/en-US/start/overview
|
||||
// New widgets should support dark and light theme
|
||||
|
||||
oc_thread_local oc_ui_context oc_uiThreadContext = { 0 };
|
||||
oc_thread_local oc_ui_context* oc_uiCurrentContext = 0;
|
||||
|
@ -538,6 +539,16 @@ bool oc_ui_box_hot(oc_ui_box* box)
|
|||
return (box->hot);
|
||||
}
|
||||
|
||||
void oc_ui_box_set_dragging(oc_ui_box* box, bool dragging)
|
||||
{
|
||||
box->dragging = dragging;
|
||||
}
|
||||
|
||||
bool oc_ui_box_dragging(oc_ui_box* box)
|
||||
{
|
||||
return (box->dragging);
|
||||
}
|
||||
|
||||
oc_ui_sig oc_ui_box_sig(oc_ui_box* box)
|
||||
{
|
||||
//NOTE: compute input signals
|
||||
|
@ -2668,6 +2679,132 @@ oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_
|
|||
}
|
||||
oc_ui_box_set_closed(panel, !oc_ui_box_active(panel));
|
||||
}
|
||||
result.changed = result.selectedIndex != info->selectedIndex;
|
||||
return (result);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Radio group
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void oc_ui_radio_indicator_draw(oc_ui_box* box, void* data)
|
||||
{
|
||||
oc_mat2x3 matrix = {
|
||||
box->rect.w, 0, box->rect.x,
|
||||
0, box->rect.h, box->rect.y
|
||||
};
|
||||
oc_matrix_multiply_push(matrix);
|
||||
|
||||
oc_set_color(box->style.color);
|
||||
oc_circle_fill(0.5, 0.5, 35.0 / 192);
|
||||
|
||||
oc_matrix_pop();
|
||||
}
|
||||
|
||||
oc_ui_radio_group_info oc_ui_radio_group(const char* name, oc_ui_radio_group_info* info)
|
||||
{
|
||||
oc_ui_radio_group_info result = *info;
|
||||
|
||||
oc_ui_context* ui = oc_ui_get_context();
|
||||
oc_ui_theme* theme = ui->theme;
|
||||
|
||||
oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y,
|
||||
.layout.spacing = 12 },
|
||||
OC_UI_STYLE_LAYOUT_AXIS
|
||||
| OC_UI_STYLE_LAYOUT_SPACING);
|
||||
oc_ui_container(name, 0)
|
||||
{
|
||||
for(int i = 0; i < info->optionCount; i++)
|
||||
{
|
||||
oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
|
||||
.layout.spacing = 8 },
|
||||
OC_UI_STYLE_LAYOUT_AXIS
|
||||
| OC_UI_STYLE_LAYOUT_SPACING);
|
||||
oc_ui_box* row = oc_ui_box_begin_str8(info->options[i], OC_UI_FLAG_CLICKABLE);
|
||||
oc_ui_flags flags = OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_DRAW_BORDER | OC_UI_FLAG_DRAW_PROC;
|
||||
oc_ui_box* radio = oc_ui_box_make("radio", flags);
|
||||
oc_ui_box_set_draw_proc(radio, oc_ui_radio_indicator_draw, 0);
|
||||
|
||||
oc_ui_sig sig = oc_ui_box_sig(row);
|
||||
if(sig.clicked)
|
||||
{
|
||||
result.selectedIndex = i;
|
||||
}
|
||||
|
||||
oc_ui_box_set_hot(radio, sig.hovering);
|
||||
oc_ui_box_set_dragging(radio, sig.dragging);
|
||||
|
||||
const char* defaultTagStr = "radio";
|
||||
const char* selectedTagStr = "radio_selected";
|
||||
const char* radioTagStr = result.selectedIndex == i ? selectedTagStr : defaultTagStr;
|
||||
oc_ui_tag_box(radio, radioTagStr);
|
||||
|
||||
oc_ui_style baseStyle = { .size.width = { OC_UI_SIZE_PIXELS, 16 },
|
||||
.size.height = { OC_UI_SIZE_PIXELS, 16 },
|
||||
.color = { 0, 0, 0, 0 },
|
||||
.roundness = 8 };
|
||||
oc_ui_style_mask baseMask = OC_UI_STYLE_SIZE
|
||||
| OC_UI_STYLE_ROUNDNESS
|
||||
| OC_UI_STYLE_COLOR;
|
||||
oc_ui_style_box_before(radio, oc_ui_pattern_owner(), &baseStyle, baseMask);
|
||||
|
||||
oc_ui_tag defaultTag = oc_ui_tag_make(defaultTagStr);
|
||||
oc_ui_pattern defaultPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &defaultPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
|
||||
oc_ui_style defaultStyle = { .borderColor = theme->text3,
|
||||
.borderSize = 1 };
|
||||
oc_ui_style_mask defaultMask = OC_UI_STYLE_BORDER_COLOR
|
||||
| OC_UI_STYLE_BORDER_SIZE;
|
||||
oc_ui_style_box_before(radio, defaultPattern, &defaultStyle, defaultMask);
|
||||
|
||||
oc_ui_pattern hoverPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &hoverPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
|
||||
oc_ui_pattern_push(&ui->frameArena, &hoverPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_HOVER });
|
||||
oc_ui_style hoverStyle = { .bgColor = theme->fill0,
|
||||
.borderColor = theme->primary };
|
||||
oc_ui_style_mask hoverMask = OC_UI_STYLE_BG_COLOR
|
||||
| OC_UI_STYLE_BORDER_COLOR;
|
||||
oc_ui_style_box_after(radio, hoverPattern, &hoverStyle, hoverMask);
|
||||
|
||||
oc_ui_pattern draggingPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &draggingPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
|
||||
oc_ui_pattern_push(&ui->frameArena, &draggingPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_DRAGGING });
|
||||
oc_ui_style draggingStyle = { .bgColor = theme->fill1,
|
||||
.borderColor = theme->primary };
|
||||
oc_ui_style_mask draggingMask = OC_UI_STYLE_BG_COLOR
|
||||
| OC_UI_STYLE_BORDER_COLOR;
|
||||
oc_ui_style_box_after(radio, draggingPattern, &draggingStyle, draggingMask);
|
||||
|
||||
oc_ui_tag selectedTag = oc_ui_tag_make(selectedTagStr);
|
||||
oc_ui_pattern selectedPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &selectedPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
|
||||
oc_ui_style selectedStyle = { .color = theme->palette->white,
|
||||
.bgColor = theme->primary };
|
||||
oc_ui_style_mask selectedMask = OC_UI_STYLE_COLOR
|
||||
| OC_UI_STYLE_BG_COLOR;
|
||||
oc_ui_style_box_before(radio, selectedPattern, &selectedStyle, selectedMask);
|
||||
|
||||
oc_ui_pattern selectedHoverPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &selectedHoverPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
|
||||
oc_ui_pattern_push(&ui->frameArena, &selectedHoverPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_HOVER });
|
||||
oc_ui_style selectedHoverStyle = { .bgColor = theme->primaryHover };
|
||||
oc_ui_style_box_after(radio, selectedHoverPattern, &selectedHoverStyle, OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
oc_ui_pattern selectedDraggingPattern = { 0 };
|
||||
oc_ui_pattern_push(&ui->frameArena, &selectedDraggingPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
|
||||
oc_ui_pattern_push(&ui->frameArena, &selectedDraggingPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_DRAGGING });
|
||||
oc_ui_style selectedDraggingStyle = { .bgColor = theme->primaryActive };
|
||||
oc_ui_style_box_after(radio, selectedDraggingPattern, &selectedDraggingStyle, OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
oc_ui_container("label", 0)
|
||||
{
|
||||
oc_ui_label_str8(info->options[i]);
|
||||
}
|
||||
|
||||
oc_ui_box_end(); // row
|
||||
}
|
||||
}
|
||||
result.changed = result.selectedIndex != info->selectedIndex;
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
10
src/ui/ui.h
10
src/ui/ui.h
|
@ -778,6 +778,16 @@ typedef struct oc_ui_select_popup_info
|
|||
|
||||
ORCA_API oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info);
|
||||
|
||||
typedef struct oc_ui_radio_group_info
|
||||
{
|
||||
bool changed;
|
||||
int selectedIndex; // -1 if nothing is selected
|
||||
int optionCount;
|
||||
oc_str8* options;
|
||||
} oc_ui_radio_group_info;
|
||||
|
||||
ORCA_API oc_ui_radio_group_info oc_ui_radio_group(const char* name, oc_ui_radio_group_info* info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue