[ui layout]
- implement ui box min size, + small fixes in layout code of ui sample - quick workaround for background showing on resize: clear to current theme's bg0 color - precompute minsize based on children to avoid upward fixup step - fix scrollable panel - Simplify color overrides, override more things to counteract the light theme - Change dragging to active for after #106 is merged - when clamping box to minsize during shrinking, redistribute excess to siblings that still have some slack - wrap demo in a scrollable panel Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com> Co-authored-by: Martin Fouilleul <martinfouilleul@gmail.com>
This commit is contained in:
		
							parent
							
								
									33078fd9dc
								
							
						
					
					
						commit
						7d3f29e43b
					
				| 
						 | 
				
			
			@ -89,7 +89,7 @@ void log_pushf(const char* format, ...)
 | 
			
		|||
 | 
			
		||||
void column_begin(const char* header, f32 widthFraction)
 | 
			
		||||
{
 | 
			
		||||
    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, widthFraction },
 | 
			
		||||
    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, widthFraction, 1 },
 | 
			
		||||
                                     .size.height = { OC_UI_SIZE_PARENT, 1 },
 | 
			
		||||
                                     .layout.axis = OC_UI_AXIS_Y,
 | 
			
		||||
                                     .layout.margin.y = 8,
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ void column_begin(const char* header, f32 widthFraction)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
 | 
			
		||||
                                     .size.height = { OC_UI_SIZE_PARENT, 0.8 },
 | 
			
		||||
                                     .size.height = { OC_UI_SIZE_PARENT, 1, 1 },
 | 
			
		||||
                                     .layout.align.x = OC_UI_ALIGN_START,
 | 
			
		||||
                                     .layout.margin.x = 16,
 | 
			
		||||
                                     .layout.spacing = 24 },
 | 
			
		||||
| 
						 | 
				
			
			@ -158,8 +158,18 @@ void labeled_slider(const char* label, f32* value)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
 | 
			
		||||
{
 | 
			
		||||
    frameSize.x = width;
 | 
			
		||||
    frameSize.y = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reset_next_radio_group_to_dark_theme(oc_arena* arena);
 | 
			
		||||
 | 
			
		||||
ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		||||
{
 | 
			
		||||
    oc_arena_scope scratch = oc_scratch_begin();
 | 
			
		||||
 | 
			
		||||
    switch(command)
 | 
			
		||||
    {
 | 
			
		||||
        case CMD_SET_DARK_THEME:
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +183,6 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
    }
 | 
			
		||||
    command = CMD_NONE;
 | 
			
		||||
 | 
			
		||||
    oc_arena_scope scratch = oc_scratch_begin();
 | 
			
		||||
    oc_ui_style defaultStyle = { .font = fontRegular };
 | 
			
		||||
    oc_ui_style_mask defaultMask = OC_UI_STYLE_FONT;
 | 
			
		||||
    oc_ui_frame(frameSize, &defaultStyle, defaultMask)
 | 
			
		||||
| 
						 | 
				
			
			@ -204,8 +213,10 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        oc_ui_panel("main panel", OC_UI_FLAG_NONE)
 | 
			
		||||
        {
 | 
			
		||||
            oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
 | 
			
		||||
                                         .size.height = { OC_UI_SIZE_PARENT_MINUS_PIXELS, 28 },
 | 
			
		||||
                                             .size.height = { OC_UI_SIZE_PARENT, 1, 1 },
 | 
			
		||||
                                             .layout.axis = OC_UI_AXIS_X,
 | 
			
		||||
                                             .layout.margin.x = 16,
 | 
			
		||||
                                             .layout.margin.y = 16,
 | 
			
		||||
| 
						 | 
				
			
			@ -214,6 +225,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                 | OC_UI_STYLE_LAYOUT_AXIS
 | 
			
		||||
                                 | OC_UI_STYLE_LAYOUT_MARGINS
 | 
			
		||||
                                 | OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
 | 
			
		||||
            oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
 | 
			
		||||
            {
 | 
			
		||||
                column("Widgets", 1.0 / 3)
 | 
			
		||||
| 
						 | 
				
			
			@ -379,24 +391,27 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                    // Scrollable panel
 | 
			
		||||
                    //-------------------------------------------------------------------------------------
 | 
			
		||||
                    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
 | 
			
		||||
                                                 .size.height = { OC_UI_SIZE_PIXELS, 430 },
 | 
			
		||||
                                                 .layout.margin.x = 16,
 | 
			
		||||
                                                 .layout.margin.y = 16,
 | 
			
		||||
                                                 .layout.spacing = 8,
 | 
			
		||||
                                                     .size.height = { OC_UI_SIZE_PARENT, 1, 1, .minSize = 200 },
 | 
			
		||||
                                                     .bgColor = ui.theme->bg2,
 | 
			
		||||
                                                     .borderColor = ui.theme->border,
 | 
			
		||||
                                                     .borderSize = 1,
 | 
			
		||||
                                                     .roundness = ui.theme->roundnessSmall },
 | 
			
		||||
                                     OC_UI_STYLE_SIZE
 | 
			
		||||
                                     | OC_UI_STYLE_LAYOUT_MARGINS
 | 
			
		||||
                                     | OC_UI_STYLE_LAYOUT_SPACING
 | 
			
		||||
                                         | OC_UI_STYLE_BG_COLOR
 | 
			
		||||
                                         | OC_UI_STYLE_BORDER_COLOR
 | 
			
		||||
                                         | OC_UI_STYLE_BORDER_SIZE
 | 
			
		||||
                                         | OC_UI_STYLE_ROUNDNESS);
 | 
			
		||||
 | 
			
		||||
                    oc_ui_panel("log", OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_DRAW_BORDER)
 | 
			
		||||
                    {
 | 
			
		||||
                    if(oc_list_empty(&logLines.list))
 | 
			
		||||
                        oc_ui_style_next(&(oc_ui_style){ .layout.margin.x = 16,
 | 
			
		||||
                                                         .layout.margin.y = 16 },
 | 
			
		||||
                                         OC_UI_STYLE_LAYOUT_MARGINS
 | 
			
		||||
                                             | OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
 | 
			
		||||
                        oc_ui_container("contents", OC_UI_FLAG_NONE)
 | 
			
		||||
                        {
 | 
			
		||||
                            if(oc_list_empty(logLines.list))
 | 
			
		||||
                            {
 | 
			
		||||
                                oc_ui_style_next(&(oc_ui_style){ .color = ui.theme->text2 },
 | 
			
		||||
                                                 OC_UI_STYLE_COLOR);
 | 
			
		||||
| 
						 | 
				
			
			@ -404,7 +419,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                            }
 | 
			
		||||
 | 
			
		||||
                            i32 i = 0;
 | 
			
		||||
                    oc_list_for(&logLines.list, logLine, oc_str8_elt, listElt)
 | 
			
		||||
                            oc_list_for(logLines.list, logLine, oc_str8_elt, listElt)
 | 
			
		||||
                            {
 | 
			
		||||
                                char id[15];
 | 
			
		||||
                                snprintf(id, sizeof(id), "%d", i);
 | 
			
		||||
| 
						 | 
				
			
			@ -416,6 +431,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //-----------------------------------------------------------------------------------------
 | 
			
		||||
                // Styling
 | 
			
		||||
| 
						 | 
				
			
			@ -431,28 +447,16 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                    static f32 unselectedWidth = 16;
 | 
			
		||||
                    static f32 unselectedHeight = 16;
 | 
			
		||||
                    static f32 unselectedRoundness = 8;
 | 
			
		||||
                static f32 unselectedBgR = 0.086;
 | 
			
		||||
                static f32 unselectedBgG = 0.086;
 | 
			
		||||
                static f32 unselectedBgB = 0.102;
 | 
			
		||||
                static f32 unselectedBgA = 1;
 | 
			
		||||
                static f32 unselectedBorderR = 0.976;
 | 
			
		||||
                static f32 unselectedBorderG = 0.976;
 | 
			
		||||
                static f32 unselectedBorderB = 0.976;
 | 
			
		||||
                static f32 unselectedBorderA = 0.35;
 | 
			
		||||
                    static oc_color unselectedBgColor = { 0.086, 0.086, 0.102, 1 };
 | 
			
		||||
                    static oc_color unselectedBorderColor = { 0.976, 0.976, 0.976, 0.35 };
 | 
			
		||||
                    static f32 unselectedBorderSize = 1;
 | 
			
		||||
                    static oc_ui_status unselectedWhenStatus = OC_UI_NONE;
 | 
			
		||||
 | 
			
		||||
                    static f32 selectedWidth = 16;
 | 
			
		||||
                    static f32 selectedHeight = 16;
 | 
			
		||||
                    static f32 selectedRoundness = 8;
 | 
			
		||||
                static f32 selectedR = 1;
 | 
			
		||||
                static f32 selectedG = 1;
 | 
			
		||||
                static f32 selectedB = 1;
 | 
			
		||||
                static f32 selectedA = 1;
 | 
			
		||||
                static f32 selectedBgR = 0.33;
 | 
			
		||||
                static f32 selectedBgG = 0.66;
 | 
			
		||||
                static f32 selectedBgB = 1;
 | 
			
		||||
                static f32 selectedBgA = 1;
 | 
			
		||||
                    static oc_color selectedCenterColor = { 1, 1, 1, 1 };
 | 
			
		||||
                    static oc_color selectedBgColor = { 0.33, 0.66, 1, 1 };
 | 
			
		||||
                    static oc_ui_status selectedWhenStatus = OC_UI_NONE;
 | 
			
		||||
 | 
			
		||||
                    static oc_color labelFontColor = { 0.976, 0.976, 0.976, 1 };
 | 
			
		||||
| 
						 | 
				
			
			@ -471,21 +475,26 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                         | OC_UI_STYLE_ROUNDNESS);
 | 
			
		||||
                    oc_ui_container("styled_radios", OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_DRAW_BORDER)
 | 
			
		||||
                    {
 | 
			
		||||
                        reset_next_radio_group_to_dark_theme(scratch.arena);
 | 
			
		||||
 | 
			
		||||
                        oc_ui_pattern unselectedPattern = { 0 };
 | 
			
		||||
                        oc_ui_pattern_push(scratch.arena,
 | 
			
		||||
                                           &unselectedPattern,
 | 
			
		||||
                                           (oc_ui_selector){ .kind = OC_UI_SEL_TAG,
 | 
			
		||||
                                                             .tag = oc_ui_tag_make("radio") });
 | 
			
		||||
                        if(unselectedWhenStatus != OC_UI_NONE)
 | 
			
		||||
                        {
 | 
			
		||||
                            oc_ui_pattern_push(scratch.arena,
 | 
			
		||||
                                               &unselectedPattern,
 | 
			
		||||
                                               (oc_ui_selector){ .op = OC_UI_SEL_AND,
 | 
			
		||||
                                                                 .kind = OC_UI_SEL_STATUS,
 | 
			
		||||
                                                                 .status = unselectedWhenStatus });
 | 
			
		||||
                        }
 | 
			
		||||
                        oc_ui_style_match_after(unselectedPattern,
 | 
			
		||||
                                                &(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, unselectedWidth },
 | 
			
		||||
                                                                .size.height = { OC_UI_SIZE_PIXELS, unselectedHeight },
 | 
			
		||||
                                                            .bgColor = { unselectedBgR, unselectedBgG, unselectedBgB, unselectedBgA },
 | 
			
		||||
                                                            .borderColor = { unselectedBorderR, unselectedBorderG, unselectedBorderB, unselectedBorderA },
 | 
			
		||||
                                                                .bgColor = unselectedBgColor,
 | 
			
		||||
                                                                .borderColor = unselectedBorderColor,
 | 
			
		||||
                                                                .borderSize = unselectedBorderSize,
 | 
			
		||||
                                                                .roundness = unselectedRoundness },
 | 
			
		||||
                                                OC_UI_STYLE_SIZE
 | 
			
		||||
| 
						 | 
				
			
			@ -499,16 +508,19 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                           &selectedPattern,
 | 
			
		||||
                                           (oc_ui_selector){ .kind = OC_UI_SEL_TAG,
 | 
			
		||||
                                                             .tag = oc_ui_tag_make("radio_selected") });
 | 
			
		||||
                        if(selectedWhenStatus != OC_UI_NONE)
 | 
			
		||||
                        {
 | 
			
		||||
                            oc_ui_pattern_push(scratch.arena,
 | 
			
		||||
                                               &selectedPattern,
 | 
			
		||||
                                               (oc_ui_selector){ .op = OC_UI_SEL_AND,
 | 
			
		||||
                                                                 .kind = OC_UI_SEL_STATUS,
 | 
			
		||||
                                                                 .status = selectedWhenStatus });
 | 
			
		||||
                        }
 | 
			
		||||
                        oc_ui_style_match_after(selectedPattern,
 | 
			
		||||
                                                &(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, selectedWidth },
 | 
			
		||||
                                                                .size.height = { OC_UI_SIZE_PIXELS, selectedHeight },
 | 
			
		||||
                                                            .color = { selectedR, selectedG, selectedB, selectedA },
 | 
			
		||||
                                                            .bgColor = { selectedBgR, selectedBgG, selectedBgB, selectedBgA },
 | 
			
		||||
                                                                .color = selectedCenterColor,
 | 
			
		||||
                                                                .bgColor = selectedBgColor,
 | 
			
		||||
                                                                .roundness = selectedRoundness },
 | 
			
		||||
                                                OC_UI_STYLE_SIZE
 | 
			
		||||
                                                    | OC_UI_STYLE_COLOR
 | 
			
		||||
| 
						 | 
				
			
			@ -574,20 +586,20 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                             OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
                            oc_ui_container("background", OC_UI_FLAG_NONE)
 | 
			
		||||
                            {
 | 
			
		||||
                            labeled_slider("Background R", &unselectedBgR);
 | 
			
		||||
                            labeled_slider("Background G", &unselectedBgG);
 | 
			
		||||
                            labeled_slider("Background B", &unselectedBgB);
 | 
			
		||||
                            labeled_slider("Background A", &unselectedBgA);
 | 
			
		||||
                                labeled_slider("Background R", &unselectedBgColor.r);
 | 
			
		||||
                                labeled_slider("Background G", &unselectedBgColor.g);
 | 
			
		||||
                                labeled_slider("Background B", &unselectedBgColor.b);
 | 
			
		||||
                                labeled_slider("Background A", &unselectedBgColor.a);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 },
 | 
			
		||||
                                             OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
                            oc_ui_container("border", OC_UI_FLAG_NONE)
 | 
			
		||||
                            {
 | 
			
		||||
                            labeled_slider("Border R", &unselectedBorderR);
 | 
			
		||||
                            labeled_slider("Border G", &unselectedBorderG);
 | 
			
		||||
                            labeled_slider("Border B", &unselectedBorderB);
 | 
			
		||||
                            labeled_slider("Border A", &unselectedBorderA);
 | 
			
		||||
                                labeled_slider("Border R", &unselectedBorderColor.r);
 | 
			
		||||
                                labeled_slider("Border G", &unselectedBorderColor.g);
 | 
			
		||||
                                labeled_slider("Border B", &unselectedBorderColor.b);
 | 
			
		||||
                                labeled_slider("Border A", &unselectedBorderColor.a);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            f32 borderSizeSlider = unselectedBorderSize / 5;
 | 
			
		||||
| 
						 | 
				
			
			@ -603,7 +615,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                static int statusIndex = 0;
 | 
			
		||||
                                oc_str8 statusOptions[] = { OC_STR8("Always"),
 | 
			
		||||
                                                            OC_STR8("When hovering"),
 | 
			
		||||
                                                        OC_STR8("When dragging") };
 | 
			
		||||
                                                            OC_STR8("When active") };
 | 
			
		||||
                                oc_ui_radio_group_info statusInfo = { .selectedIndex = statusIndex,
 | 
			
		||||
                                                                      .optionCount = oc_array_size(statusOptions),
 | 
			
		||||
                                                                      .options = statusOptions };
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +630,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                        unselectedWhenStatus = OC_UI_HOVER;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    case 2:
 | 
			
		||||
                                    unselectedWhenStatus = OC_UI_DRAGGING;
 | 
			
		||||
                                        unselectedWhenStatus = OC_UI_ACTIVE;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    default:
 | 
			
		||||
                                        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -657,20 +669,20 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                             OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
                            oc_ui_container("color", OC_UI_FLAG_NONE)
 | 
			
		||||
                            {
 | 
			
		||||
                            labeled_slider("Center R", &selectedR);
 | 
			
		||||
                            labeled_slider("Center G", &selectedG);
 | 
			
		||||
                            labeled_slider("Center B", &selectedB);
 | 
			
		||||
                            labeled_slider("Center A", &selectedA);
 | 
			
		||||
                                labeled_slider("Center R", &selectedCenterColor.r);
 | 
			
		||||
                                labeled_slider("Center G", &selectedCenterColor.g);
 | 
			
		||||
                                labeled_slider("Center B", &selectedCenterColor.b);
 | 
			
		||||
                                labeled_slider("Center A", &selectedCenterColor.a);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 },
 | 
			
		||||
                                             OC_UI_STYLE_LAYOUT_SPACING);
 | 
			
		||||
                            oc_ui_container("background", OC_UI_FLAG_NONE)
 | 
			
		||||
                            {
 | 
			
		||||
                            labeled_slider("Background R", &selectedBgR);
 | 
			
		||||
                            labeled_slider("Background G", &selectedBgG);
 | 
			
		||||
                            labeled_slider("Background B", &selectedBgB);
 | 
			
		||||
                            labeled_slider("Background A", &selectedBgA);
 | 
			
		||||
                                labeled_slider("Background R", &selectedBgColor.r);
 | 
			
		||||
                                labeled_slider("Background G", &selectedBgColor.g);
 | 
			
		||||
                                labeled_slider("Background B", &selectedBgColor.b);
 | 
			
		||||
                                labeled_slider("Background A", &selectedBgColor.a);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 10 },
 | 
			
		||||
| 
						 | 
				
			
			@ -686,7 +698,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                static int statusIndex = 0;
 | 
			
		||||
                                oc_str8 statusOptions[] = { OC_STR8("Always"),
 | 
			
		||||
                                                            OC_STR8("When hovering"),
 | 
			
		||||
                                                        OC_STR8("When dragging") };
 | 
			
		||||
                                                            OC_STR8("When active") };
 | 
			
		||||
                                oc_ui_radio_group_info statusInfo = { .selectedIndex = statusIndex,
 | 
			
		||||
                                                                      .optionCount = oc_array_size(statusOptions),
 | 
			
		||||
                                                                      .options = statusOptions };
 | 
			
		||||
| 
						 | 
				
			
			@ -701,7 +713,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                                        selectedWhenStatus = OC_UI_HOVER;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    case 2:
 | 
			
		||||
                                    selectedWhenStatus = OC_UI_DRAGGING;
 | 
			
		||||
                                        selectedWhenStatus = OC_UI_ACTIVE;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    default:
 | 
			
		||||
                                        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -787,12 +799,70 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oc_canvas_select(canvas);
 | 
			
		||||
    oc_surface_select(surface);
 | 
			
		||||
 | 
			
		||||
    oc_set_color(ui.theme->bg0);
 | 
			
		||||
    oc_clear();
 | 
			
		||||
 | 
			
		||||
    oc_ui_draw();
 | 
			
		||||
    oc_render(canvas);
 | 
			
		||||
    oc_surface_present(surface);
 | 
			
		||||
 | 
			
		||||
    oc_scratch_end(scratch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This makes sure the light theme doesn't break the styling overrides
 | 
			
		||||
// You won't need it in a real program as long as your colors come from ui.theme or ui.theme->palette
 | 
			
		||||
void reset_next_radio_group_to_dark_theme(oc_arena* arena)
 | 
			
		||||
{
 | 
			
		||||
    oc_ui_tag defaultTag = oc_ui_tag_make("radio");
 | 
			
		||||
    oc_ui_pattern defaultPattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &defaultPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
 | 
			
		||||
    oc_ui_style defaultStyle = { .borderColor = OC_UI_DARK_THEME.text3,
 | 
			
		||||
                                 .borderSize = 1 };
 | 
			
		||||
    oc_ui_style_mask defaultMask = OC_UI_STYLE_BORDER_COLOR
 | 
			
		||||
                                 | OC_UI_STYLE_BORDER_SIZE;
 | 
			
		||||
    oc_ui_style_match_after(defaultPattern, &defaultStyle, defaultMask);
 | 
			
		||||
 | 
			
		||||
    oc_ui_pattern hoverPattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &hoverPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
 | 
			
		||||
    oc_ui_pattern_push(arena, &hoverPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_HOVER });
 | 
			
		||||
    oc_ui_style hoverStyle = { .bgColor = OC_UI_DARK_THEME.fill0,
 | 
			
		||||
                               .borderColor = OC_UI_DARK_THEME.primary };
 | 
			
		||||
    oc_ui_style_mask hoverMask = OC_UI_STYLE_BG_COLOR
 | 
			
		||||
                               | OC_UI_STYLE_BORDER_COLOR;
 | 
			
		||||
    oc_ui_style_match_after(hoverPattern, &hoverStyle, hoverMask);
 | 
			
		||||
 | 
			
		||||
    oc_ui_pattern activePattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &activePattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = defaultTag });
 | 
			
		||||
    oc_ui_pattern_push(arena, &activePattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_ACTIVE });
 | 
			
		||||
    oc_ui_style activeStyle = { .bgColor = OC_UI_DARK_THEME.fill1,
 | 
			
		||||
                                .borderColor = OC_UI_DARK_THEME.primary };
 | 
			
		||||
    oc_ui_style_mask activeMask = OC_UI_STYLE_BG_COLOR
 | 
			
		||||
                                | OC_UI_STYLE_BORDER_COLOR;
 | 
			
		||||
    oc_ui_style_match_after(activePattern, &activeStyle, activeMask);
 | 
			
		||||
 | 
			
		||||
    oc_ui_tag selectedTag = oc_ui_tag_make("radio_selected");
 | 
			
		||||
    oc_ui_pattern selectedPattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &selectedPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
 | 
			
		||||
    oc_ui_style selectedStyle = { .color = OC_UI_DARK_THEME.palette->white,
 | 
			
		||||
                                  .bgColor = OC_UI_DARK_THEME.primary };
 | 
			
		||||
    oc_ui_style_mask selectedMask = OC_UI_STYLE_COLOR
 | 
			
		||||
                                  | OC_UI_STYLE_BG_COLOR;
 | 
			
		||||
    oc_ui_style_match_after(selectedPattern, &selectedStyle, selectedMask);
 | 
			
		||||
 | 
			
		||||
    oc_ui_pattern selectedHoverPattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &selectedHoverPattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
 | 
			
		||||
    oc_ui_pattern_push(arena, &selectedHoverPattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_HOVER });
 | 
			
		||||
    oc_ui_style selectedHoverStyle = { .bgColor = OC_UI_DARK_THEME.primaryHover };
 | 
			
		||||
    oc_ui_style_match_after(selectedHoverPattern, &selectedHoverStyle, OC_UI_STYLE_BG_COLOR);
 | 
			
		||||
 | 
			
		||||
    oc_ui_pattern selectedActivePattern = { 0 };
 | 
			
		||||
    oc_ui_pattern_push(arena, &selectedActivePattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = selectedTag });
 | 
			
		||||
    oc_ui_pattern_push(arena, &selectedActivePattern, (oc_ui_selector){ .op = OC_UI_SEL_AND, .kind = OC_UI_SEL_STATUS, .status = OC_UI_ACTIVE });
 | 
			
		||||
    oc_ui_style selectedActiveStyle = { .bgColor = OC_UI_DARK_THEME.primaryActive };
 | 
			
		||||
    oc_ui_style_match_after(selectedActivePattern, &selectedActiveStyle, OC_UI_STYLE_BG_COLOR);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1153
									
								
								sketches/ui/main.c
								
								
								
								
							
							
						
						
									
										1153
									
								
								sketches/ui/main.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										243
									
								
								src/ui/ui.c
								
								
								
								
							
							
						
						
									
										243
									
								
								src/ui/ui.c
								
								
								
								
							| 
						 | 
				
			
			@ -1021,23 +1021,54 @@ bool oc_ui_layout_downward_dependency(oc_ui_box* child, int axis)
 | 
			
		|||
 | 
			
		||||
void oc_ui_layout_downward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int axis)
 | 
			
		||||
{
 | 
			
		||||
    //NOTE: layout children and compute spacing
 | 
			
		||||
    f32 count = 0;
 | 
			
		||||
    //NOTE: layout children and compute spacing and minimum size
 | 
			
		||||
    i32 count = 0;
 | 
			
		||||
    f32 minSum = 0;
 | 
			
		||||
 | 
			
		||||
    oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
    {
 | 
			
		||||
        if(!oc_ui_box_hidden(child))
 | 
			
		||||
        {
 | 
			
		||||
            oc_ui_layout_downward_dependent_size(ui, child, axis);
 | 
			
		||||
 | 
			
		||||
            if(box->style.layout.axis == axis
 | 
			
		||||
               && !child->style.floating.c[axis])
 | 
			
		||||
            if(!child->style.floating.c[axis])
 | 
			
		||||
            {
 | 
			
		||||
                if(box->style.layout.axis == axis)
 | 
			
		||||
                {
 | 
			
		||||
                    count++;
 | 
			
		||||
                    minSum += child->minSize[axis];
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    minSum = oc_max(minSum, child->minSize[axis]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    box->spacing[axis] = oc_max(0, count - 1) * box->style.layout.spacing;
 | 
			
		||||
 | 
			
		||||
    switch(box->style.size.c[axis].kind)
 | 
			
		||||
    {
 | 
			
		||||
        case OC_UI_SIZE_TEXT:
 | 
			
		||||
        case OC_UI_SIZE_PIXELS:
 | 
			
		||||
            box->minSize[axis] = box->rect.c[2 + axis];
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OC_UI_SIZE_CHILDREN:
 | 
			
		||||
        case OC_UI_SIZE_PARENT:
 | 
			
		||||
        case OC_UI_SIZE_PARENT_MINUS_PIXELS:
 | 
			
		||||
        {
 | 
			
		||||
            int overflowFlag = (OC_UI_FLAG_OVERFLOW_ALLOW_X << axis);
 | 
			
		||||
 | 
			
		||||
            if(!(box->flags & overflowFlag))
 | 
			
		||||
            {
 | 
			
		||||
                box->minSize[axis] = minSum + box->spacing[axis] + 2 * box->style.layout.margin.c[axis];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    box->minSize[axis] = oc_max(box->minSize[axis], box->style.size.c[axis].minSize);
 | 
			
		||||
 | 
			
		||||
    oc_ui_size* size = &box->style.size.c[axis];
 | 
			
		||||
    if(size->kind == OC_UI_SIZE_CHILDREN)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1082,22 +1113,41 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
 | 
			
		|||
        oc_ui_size* size = &child->style.size.c[axis];
 | 
			
		||||
        if(size->kind == OC_UI_SIZE_PARENT)
 | 
			
		||||
        {
 | 
			
		||||
            child->rect.c[2 + axis] = availableSize * size->value;
 | 
			
		||||
            child->rect.c[2 + axis] = oc_max(child->minSize[axis], availableSize * size->value);
 | 
			
		||||
        }
 | 
			
		||||
        else if(size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
 | 
			
		||||
        {
 | 
			
		||||
            child->rect.c[2 + axis] = oc_max(0, availableSize - size->value);
 | 
			
		||||
            child->rect.c[2 + axis] = oc_max(child->minSize[axis], oc_max(0, availableSize - size->value));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //NOTE: solve downard conflicts
 | 
			
		||||
    int overflowFlag = (OC_UI_FLAG_ALLOW_OVERFLOW_X << axis);
 | 
			
		||||
    f32 sum = 0;
 | 
			
		||||
    //NOTE: solve downward conflicts
 | 
			
		||||
    int overflowFlag = (OC_UI_FLAG_OVERFLOW_ALLOW_X << axis);
 | 
			
		||||
 | 
			
		||||
    if(!(box->flags & overflowFlag))
 | 
			
		||||
    {
 | 
			
		||||
        if(box->style.layout.axis == axis)
 | 
			
		||||
        {
 | 
			
		||||
            f32 prevSum = FLT_MAX;
 | 
			
		||||
            int count = 0;
 | 
			
		||||
 | 
			
		||||
            //NOTE: take into account the _original size_ minus the _original slack_ in minimum size. This way the widget
 | 
			
		||||
            //      never gives up more than wantedSize * relax.
 | 
			
		||||
            oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
            {
 | 
			
		||||
                if(!oc_ui_box_hidden(child)
 | 
			
		||||
                   && !child->style.floating.c[axis])
 | 
			
		||||
                {
 | 
			
		||||
                    child->minSize[axis] = oc_max(child->minSize[axis], child->rect.c[2 + axis] * (1 - child->style.size.c[axis].relax));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //NOTE: Loop while we can remove excess. Each iterations reaffects excess to boxes that still have some slack.
 | 
			
		||||
            while(1)
 | 
			
		||||
            {
 | 
			
		||||
                //NOTE: if we're solving in the layout axis, first compute total sum of children and
 | 
			
		||||
                //      total slack available
 | 
			
		||||
                f32 sum = 0;
 | 
			
		||||
                f32 slack = 0;
 | 
			
		||||
 | 
			
		||||
                oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
| 
						 | 
				
			
			@ -1106,53 +1156,166 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
 | 
			
		|||
                       && !child->style.floating.c[axis])
 | 
			
		||||
                    {
 | 
			
		||||
                        sum += child->rect.c[2 + axis];
 | 
			
		||||
                slack += child->rect.c[2 + axis] * child->style.size.c[axis].relax;
 | 
			
		||||
                        slack += oc_min(child->rect.c[2 + axis] * child->style.size.c[axis].relax,
 | 
			
		||||
                                        child->rect.c[2 + axis] - child->minSize[axis]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
        if(!(box->flags & overflowFlag))
 | 
			
		||||
                if(prevSum - sum < 1)
 | 
			
		||||
                {
 | 
			
		||||
            //NOTE: then remove excess proportionally to each box slack, and recompute children sum.
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                count++;
 | 
			
		||||
                prevSum = sum;
 | 
			
		||||
 | 
			
		||||
                //NOTE: then remove excess proportionally to each box slack
 | 
			
		||||
                f32 totalContents = sum + box->spacing[axis] + 2 * box->style.layout.margin.c[axis];
 | 
			
		||||
                f32 excess = oc_clamp_low(totalContents - box->rect.c[2 + axis], 0);
 | 
			
		||||
                f32 alpha = oc_clamp(excess / slack, 0, 1);
 | 
			
		||||
 | 
			
		||||
            sum = 0;
 | 
			
		||||
                oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
                {
 | 
			
		||||
                    if(!oc_ui_box_hidden(child) && !child->style.floating.c[axis])
 | 
			
		||||
                    {
 | 
			
		||||
                        f32 relax = child->style.size.c[axis].relax;
 | 
			
		||||
                child->rect.c[2 + axis] -= alpha * child->rect.c[2 + axis] * relax;
 | 
			
		||||
                sum += child->rect.c[2 + axis];
 | 
			
		||||
                        f32 minSize = child->minSize[axis];
 | 
			
		||||
                        f32 remove = alpha * oc_clamp(child->rect.c[2 + axis] * relax, 0, child->rect.c[2 + axis] - child->minSize[axis]);
 | 
			
		||||
 | 
			
		||||
                        child->rect.c[2 + axis] = oc_max(minSize, child->rect.c[2 + axis] - remove);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            //NOTE: if we're solving on the secondary axis, we remove excess to each box individually
 | 
			
		||||
        //      according to its own slack. Children sum is the maximum child size.
 | 
			
		||||
 | 
			
		||||
            //      according to its own slack.
 | 
			
		||||
            oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
            {
 | 
			
		||||
                if(!oc_ui_box_hidden(child) && !child->style.floating.c[axis])
 | 
			
		||||
            {
 | 
			
		||||
                if(!(box->flags & overflowFlag))
 | 
			
		||||
                {
 | 
			
		||||
                    f32 totalContents = child->rect.c[2 + axis] + 2 * box->style.layout.margin.c[axis];
 | 
			
		||||
                    f32 excess = oc_clamp_low(totalContents - box->rect.c[2 + axis], 0);
 | 
			
		||||
                    f32 relax = child->style.size.c[axis].relax;
 | 
			
		||||
                    child->rect.c[2 + axis] -= oc_min(excess, child->rect.c[2 + axis] * relax);
 | 
			
		||||
                    f32 minSize = child->minSize[axis];
 | 
			
		||||
                    f32 remove = oc_min(excess, child->rect.c[2 + axis] * relax);
 | 
			
		||||
 | 
			
		||||
                    child->rect.c[2 + axis] = oc_max(minSize, child->rect.c[2 + axis] - remove);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    f32 sum = 0;
 | 
			
		||||
 | 
			
		||||
    //NOTE: recurse in children and recompute children sum
 | 
			
		||||
    oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
    {
 | 
			
		||||
        oc_ui_layout_upward_dependent_size(ui, child, axis);
 | 
			
		||||
 | 
			
		||||
        if(!oc_ui_box_hidden(child)
 | 
			
		||||
           && !child->style.floating.c[axis])
 | 
			
		||||
        {
 | 
			
		||||
            if(box->style.layout.axis == axis)
 | 
			
		||||
            {
 | 
			
		||||
                sum += child->rect.c[2 + axis];
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                sum = oc_max(sum, child->rect.c[2 + axis]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    box->childrenSum[axis] = sum;
 | 
			
		||||
 | 
			
		||||
    //NOTE: recurse in children
 | 
			
		||||
    OC_ASSERT(box->rect.c[2 + axis] >= box->minSize[axis], "parent->string = %.*s, box->string = %.*s, axis = %i, box->size[axis].kind = %i, box->rect.c[2+axis] = %f, box->minSize[axis] = %f",
 | 
			
		||||
              oc_str8_ip(box->parent->string),
 | 
			
		||||
              oc_str8_ip(box->string),
 | 
			
		||||
              axis,
 | 
			
		||||
              box->style.size.c[axis].kind,
 | 
			
		||||
              box->rect.c[2 + axis],
 | 
			
		||||
              box->minSize[axis]);
 | 
			
		||||
    /*
 | 
			
		||||
    if(!(box->flags & overflowFlag) && !oc_list_empty(box->children))
 | 
			
		||||
    {
 | 
			
		||||
        f32 minSize = sum + 2 * box->style.layout.margin.c[axis] + box->spacing[axis];
 | 
			
		||||
        box->rect.c[2 + axis] = oc_max(minSize, box->rect.c[2 + axis]);
 | 
			
		||||
    }
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void oc_ui_layout_upward_dependent_fixup(oc_ui_context* ui, oc_ui_box* box, int axis)
 | 
			
		||||
{
 | 
			
		||||
    f32 margin = box->style.layout.margin.c[axis];
 | 
			
		||||
    f32 availableSize = oc_max(0, box->rect.c[2 + axis] - box->spacing[axis] - 2 * margin);
 | 
			
		||||
 | 
			
		||||
    if(axis == box->style.layout.axis)
 | 
			
		||||
    {
 | 
			
		||||
        f32 availableToParentSized = availableSize;
 | 
			
		||||
        f32 relaxSum = 0;
 | 
			
		||||
 | 
			
		||||
        oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
        {
 | 
			
		||||
        oc_ui_layout_upward_dependent_size(ui, child, axis);
 | 
			
		||||
            oc_ui_size* size = &child->style.size.c[axis];
 | 
			
		||||
            if(size->kind == OC_UI_SIZE_PARENT || size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
 | 
			
		||||
            {
 | 
			
		||||
                f32 wantedSize = 0;
 | 
			
		||||
                if(size->kind == OC_UI_SIZE_PARENT)
 | 
			
		||||
                {
 | 
			
		||||
                    wantedSize = availableSize * size->value;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    wantedSize = availableSize - size->value;
 | 
			
		||||
                }
 | 
			
		||||
                if(wantedSize > child->rect.c[2 + axis])
 | 
			
		||||
                {
 | 
			
		||||
                    relaxSum += size->relax;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            availableToParentSized -= child->rect.c[2 + axis];
 | 
			
		||||
        }
 | 
			
		||||
        availableToParentSized = oc_max(0, availableToParentSized);
 | 
			
		||||
 | 
			
		||||
        if(availableToParentSized && relaxSum)
 | 
			
		||||
        {
 | 
			
		||||
            oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
            {
 | 
			
		||||
                oc_ui_size* size = &child->style.size.c[axis];
 | 
			
		||||
                if(size->kind == OC_UI_SIZE_PARENT || size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
 | 
			
		||||
                {
 | 
			
		||||
                    f32 wantedSize = 0;
 | 
			
		||||
                    if(size->kind == OC_UI_SIZE_PARENT)
 | 
			
		||||
                    {
 | 
			
		||||
                        wantedSize = availableSize * size->value;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        wantedSize = availableSize - size->value;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if(wantedSize > child->rect.c[2 + axis])
 | 
			
		||||
                    {
 | 
			
		||||
                        child->rect.c[2 + axis] += availableToParentSized * (size->relax / relaxSum);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oc_list_for(box->children, child, oc_ui_box, listElt)
 | 
			
		||||
    {
 | 
			
		||||
        if(axis != box->style.layout.axis)
 | 
			
		||||
        {
 | 
			
		||||
            oc_ui_size* size = &child->style.size.c[axis];
 | 
			
		||||
            if(size->kind == OC_UI_SIZE_PARENT)
 | 
			
		||||
            {
 | 
			
		||||
                child->rect.c[2 + axis] = oc_max(child->rect.c[2 + axis], availableSize * size->value);
 | 
			
		||||
            }
 | 
			
		||||
            else if(size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
 | 
			
		||||
            {
 | 
			
		||||
                child->rect.c[2 + axis] = oc_max(child->rect.c[2 + axis], oc_max(0, availableSize - size->value));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        oc_ui_layout_upward_dependent_fixup(ui, child, axis);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1233,6 +1396,11 @@ void oc_ui_layout_compute_rect(oc_ui_context* ui, oc_ui_box* box, oc_vec2 pos)
 | 
			
		|||
            currentPos.c[layoutAxis] += child->rect.c[2 + layoutAxis] + spacing;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(isnan(box->rect.w) || isnan(box->rect.h))
 | 
			
		||||
    {
 | 
			
		||||
        oc_log_error("error in box %.*s\n", oc_str8_ip(box->string));
 | 
			
		||||
        OC_ASSERT(0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void oc_ui_layout_find_next_hovered_recursive(oc_ui_context* ui, oc_ui_box* box, oc_vec2 p)
 | 
			
		||||
| 
						 | 
				
			
			@ -1285,6 +1453,8 @@ void oc_ui_solve_layout(oc_ui_context* ui)
 | 
			
		|||
    {
 | 
			
		||||
        oc_ui_layout_downward_dependent_size(ui, ui->root, axis);
 | 
			
		||||
        oc_ui_layout_upward_dependent_size(ui, ui->root, axis);
 | 
			
		||||
 | 
			
		||||
        //        oc_ui_layout_upward_dependent_fixup(ui, ui->root, axis);
 | 
			
		||||
    }
 | 
			
		||||
    oc_ui_layout_compute_rect(ui, ui->root, (oc_vec2){ 0, 0 });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1428,6 +1598,15 @@ void oc_ui_draw_box(oc_ui_box* box)
 | 
			
		|||
        oc_set_color(style->borderColor);
 | 
			
		||||
        oc_ui_rectangle_stroke(box->rect, style->roundness);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    if(box->rect.w && box->rect.h)
 | 
			
		||||
    {
 | 
			
		||||
        oc_set_width(1);
 | 
			
		||||
        oc_set_color_rgba(1, 0, 0, 1);
 | 
			
		||||
        oc_ui_rectangle_stroke(box->rect, 0);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void oc_ui_draw()
 | 
			
		||||
| 
						 | 
				
			
			@ -2121,13 +2300,23 @@ void oc_ui_panel_begin(const char* str, oc_ui_flags flags)
 | 
			
		|||
    flags = flags
 | 
			
		||||
          | OC_UI_FLAG_CLIP
 | 
			
		||||
          | OC_UI_FLAG_BLOCK_MOUSE
 | 
			
		||||
          | OC_UI_FLAG_ALLOW_OVERFLOW_X
 | 
			
		||||
          | OC_UI_FLAG_ALLOW_OVERFLOW_Y
 | 
			
		||||
          | OC_UI_FLAG_OVERFLOW_ALLOW_X
 | 
			
		||||
          | OC_UI_FLAG_OVERFLOW_ALLOW_Y
 | 
			
		||||
          | OC_UI_FLAG_SCROLL_WHEEL_X
 | 
			
		||||
          | OC_UI_FLAG_SCROLL_WHEEL_Y;
 | 
			
		||||
 | 
			
		||||
    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1, 1 },
 | 
			
		||||
                                     .size.height = { OC_UI_SIZE_PARENT, 1, 1 },
 | 
			
		||||
                                     .layout.margin.x = 0,
 | 
			
		||||
                                     .layout.margin.y = 0 },
 | 
			
		||||
                     OC_UI_STYLE_SIZE
 | 
			
		||||
                         | OC_UI_STYLE_LAYOUT_MARGINS);
 | 
			
		||||
    oc_ui_box_begin(str, flags);
 | 
			
		||||
 | 
			
		||||
    oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
 | 
			
		||||
                                     .size.height = { OC_UI_SIZE_PARENT, 1 } },
 | 
			
		||||
                     OC_UI_STYLE_SIZE);
 | 
			
		||||
 | 
			
		||||
    oc_ui_box_begin("contents", 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2532,7 +2721,7 @@ oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_
 | 
			
		|||
                                           OC_UI_FLAG_CLICKABLE
 | 
			
		||||
                                               | OC_UI_FLAG_DRAW_BACKGROUND
 | 
			
		||||
                                               | OC_UI_FLAG_DRAW_BORDER
 | 
			
		||||
                                               | OC_UI_FLAG_ALLOW_OVERFLOW_X
 | 
			
		||||
                                               | OC_UI_FLAG_OVERFLOW_ALLOW_X
 | 
			
		||||
                                               | OC_UI_FLAG_CLIP);
 | 
			
		||||
 | 
			
		||||
        f32 maxOptionWidth = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								src/ui/ui.h
								
								
								
								
							
							
						
						
									
										17
									
								
								src/ui/ui.h
								
								
								
								
							| 
						 | 
				
			
			@ -69,7 +69,7 @@ typedef struct oc_ui_layout
 | 
			
		|||
 | 
			
		||||
typedef enum oc_ui_size_kind
 | 
			
		||||
{
 | 
			
		||||
    OC_UI_SIZE_TEXT,
 | 
			
		||||
    OC_UI_SIZE_TEXT = 0,
 | 
			
		||||
    OC_UI_SIZE_PIXELS,
 | 
			
		||||
    OC_UI_SIZE_CHILDREN,
 | 
			
		||||
    OC_UI_SIZE_PARENT,
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +82,7 @@ typedef struct oc_ui_size
 | 
			
		|||
    oc_ui_size_kind kind;
 | 
			
		||||
    f32 value;
 | 
			
		||||
    f32 relax;
 | 
			
		||||
    f32 minSize;
 | 
			
		||||
} oc_ui_size;
 | 
			
		||||
 | 
			
		||||
typedef union oc_ui_box_size
 | 
			
		||||
| 
						 | 
				
			
			@ -479,8 +480,8 @@ typedef enum
 | 
			
		|||
    OC_UI_FLAG_ACTIVE_ANIMATION = (1 << 5),
 | 
			
		||||
    //WARN: these two following flags need to be kept as consecutive bits to
 | 
			
		||||
    //      play well with axis-agnostic functions
 | 
			
		||||
    OC_UI_FLAG_ALLOW_OVERFLOW_X = (1 << 6),
 | 
			
		||||
    OC_UI_FLAG_ALLOW_OVERFLOW_Y = (1 << 7),
 | 
			
		||||
    OC_UI_FLAG_OVERFLOW_ALLOW_X = (1 << 6),
 | 
			
		||||
    OC_UI_FLAG_OVERFLOW_ALLOW_Y = (1 << 7),
 | 
			
		||||
    OC_UI_FLAG_CLIP = (1 << 8),
 | 
			
		||||
    OC_UI_FLAG_DRAW_BACKGROUND = (1 << 9),
 | 
			
		||||
    OC_UI_FLAG_DRAW_FOREGROUND = (1 << 10),
 | 
			
		||||
| 
						 | 
				
			
			@ -488,7 +489,7 @@ typedef enum
 | 
			
		|||
    OC_UI_FLAG_DRAW_TEXT = (1 << 12),
 | 
			
		||||
    OC_UI_FLAG_DRAW_PROC = (1 << 13),
 | 
			
		||||
 | 
			
		||||
    OC_UI_FLAG_OVERLAY = (1 << 14),
 | 
			
		||||
    OC_UI_FLAG_OVERLAY = (1 << 16),
 | 
			
		||||
} oc_ui_flags;
 | 
			
		||||
 | 
			
		||||
struct oc_ui_box
 | 
			
		||||
| 
						 | 
				
			
			@ -525,6 +526,7 @@ struct oc_ui_box
 | 
			
		|||
    oc_vec2 floatPos;
 | 
			
		||||
    f32 childrenSum[2];
 | 
			
		||||
    f32 spacing[2];
 | 
			
		||||
    f32 minSize[2];
 | 
			
		||||
    oc_rect rect;
 | 
			
		||||
 | 
			
		||||
    // signals
 | 
			
		||||
| 
						 | 
				
			
			@ -656,12 +658,8 @@ ORCA_API void oc_ui_set_theme(oc_ui_theme* theme);
 | 
			
		|||
ORCA_API oc_ui_key oc_ui_key_make_str8(oc_str8 string);
 | 
			
		||||
ORCA_API oc_ui_key oc_ui_key_make_path(oc_str8_list path);
 | 
			
		||||
 | 
			
		||||
ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key);
 | 
			
		||||
ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string);
 | 
			
		||||
 | 
			
		||||
// C-string helper
 | 
			
		||||
#define oc_ui_key_make(s) oc_ui_key_make_str8(OC_STR8(s))
 | 
			
		||||
#define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s))
 | 
			
		||||
 | 
			
		||||
//-------------------------------------------------------------------------------------
 | 
			
		||||
// Box hierarchy building
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +675,9 @@ ORCA_API void oc_ui_box_push(oc_ui_box* box);
 | 
			
		|||
ORCA_API void oc_ui_box_pop(void);
 | 
			
		||||
ORCA_API oc_ui_box* oc_ui_box_top(void);
 | 
			
		||||
 | 
			
		||||
ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key);
 | 
			
		||||
ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string);
 | 
			
		||||
 | 
			
		||||
ORCA_API void oc_ui_box_set_draw_proc(oc_ui_box* box, oc_ui_box_draw_proc proc, void* data);
 | 
			
		||||
 | 
			
		||||
// C-string helpers
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue