351 lines
10 KiB
C++
351 lines
10 KiB
C++
//- sixten: Rows and columns.
|
|
inline void UI_RowBegin(u32 Flags, string Name)
|
|
{
|
|
UI_SetNextLayoutAxis(Axis2_X);
|
|
ui_box *Box = UI_MakeBox(Flags, Name);
|
|
UI_PushParent(Box);
|
|
}
|
|
|
|
inline void UI_RowEnd(void)
|
|
{
|
|
UI_PopParent();
|
|
}
|
|
|
|
inline void UI_ColumnBegin(u32 Flags, string Name)
|
|
{
|
|
UI_SetNextLayoutAxis(Axis2_Y);
|
|
ui_box *Box = UI_MakeBox(Flags, Name);
|
|
UI_PushParent(Box);
|
|
}
|
|
|
|
inline void UI_ColumnEnd(void)
|
|
{
|
|
UI_PopParent();
|
|
}
|
|
|
|
//- sixten: Compositions
|
|
inline void UI_PushAxisSize(axis2 Axis, ui_size Size)
|
|
{
|
|
if(Axis == Axis2_X)
|
|
{
|
|
UI_PushWidth(Size);
|
|
}
|
|
else
|
|
{
|
|
UI_PushHeight(Size);
|
|
}
|
|
}
|
|
|
|
inline void UI_PopAxisSize(axis2 Axis)
|
|
{
|
|
if(Axis == Axis2_X)
|
|
{
|
|
UI_PopWidth();
|
|
}
|
|
else
|
|
{
|
|
UI_PopHeight();
|
|
}
|
|
}
|
|
|
|
inline void UI_SetNextAxisSize(axis2 Axis, ui_size Size)
|
|
{
|
|
if(Axis == Axis2_X)
|
|
{
|
|
UI_SetNextWidth(Size);
|
|
}
|
|
else
|
|
{
|
|
UI_SetNextHeight(Size);
|
|
}
|
|
}
|
|
|
|
//- sixten: Spacing
|
|
static ui_box *UI_NamedSpacer(ui_size Size, string String)
|
|
{
|
|
ui_box *Parent = UI_TopParent();
|
|
UI_SetNextAxisSize(Parent->LayoutAxis, Size);
|
|
|
|
ui_box *Box = UI_MakeBox(0, String);
|
|
return(Box);
|
|
}
|
|
|
|
static ui_box *UI_NamedSpacerF(ui_size Size, char *Format, ...)
|
|
{
|
|
temporary_memory Scratch = GetScratch(0, 0);
|
|
|
|
va_list Arguments;
|
|
va_start(Arguments, Format);
|
|
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
|
|
va_end(Arguments);
|
|
|
|
ui_box *Box = UI_NamedSpacer(Size, String);
|
|
|
|
ReleaseScratch(Scratch);
|
|
|
|
return(Box);
|
|
}
|
|
|
|
static void UI_Spacer(ui_size Size)
|
|
{
|
|
UI_NamedSpacer(Size, StrLit(""));
|
|
}
|
|
|
|
//- sixten: Scrollable regions
|
|
|
|
|
|
//- sixten: Common widgets
|
|
static ui_box *UI_Label(string String)
|
|
{
|
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawText, String);
|
|
return(Box);
|
|
}
|
|
|
|
static ui_box *UI_LabelF(char *Format, ...)
|
|
{
|
|
temporary_memory Scratch = GetScratch(0, 0);
|
|
|
|
va_list Arguments;
|
|
va_start(Arguments, Format);
|
|
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
|
|
va_end(Arguments);
|
|
|
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawText, String);
|
|
|
|
ReleaseScratch(Scratch);
|
|
|
|
return(Box);
|
|
}
|
|
|
|
static ui_signal UI_Button(string String)
|
|
{
|
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawText|
|
|
UI_BoxFlag_DrawBackground|
|
|
UI_BoxFlag_DrawBorder|
|
|
UI_BoxFlag_HotAnimation|
|
|
UI_BoxFlag_ActiveAnimation|
|
|
UI_BoxFlag_Clickable,
|
|
String);
|
|
ui_signal Signal = UI_SignalFromBox(Box);
|
|
return(Signal);
|
|
}
|
|
|
|
static ui_signal UI_ButtonF(char *Format, ...)
|
|
{
|
|
temporary_memory Scratch = GetScratch(0, 0);
|
|
|
|
va_list Arguments;
|
|
va_start(Arguments, Format);
|
|
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
|
|
va_end(Arguments);
|
|
|
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawText|
|
|
UI_BoxFlag_DrawBackground|
|
|
UI_BoxFlag_DrawBorder|
|
|
UI_BoxFlag_HotAnimation|
|
|
UI_BoxFlag_ActiveAnimation|
|
|
UI_BoxFlag_Clickable,
|
|
String);
|
|
ui_signal Signal = UI_SignalFromBox(Box);
|
|
|
|
ReleaseScratch(Scratch);
|
|
|
|
return(Signal);
|
|
}
|
|
|
|
static ui_signal UI_Checkbox(b32 *Checked, string String)
|
|
{
|
|
UI_SetNextSize(UI_ChildrenSum(1, 1), UI_ChildrenSum(1, 1));
|
|
UI_SetNextLayoutAxis(Axis2_X);
|
|
|
|
ui_box *ContainerBox = UI_MakeBox(UI_BoxFlag_Clickable, String);
|
|
UI_Parent(ContainerBox)
|
|
{
|
|
r32 OpacityTransition = AnimationCurve_AnimateValueF(*Checked, *Checked, 0.15, "UI Checkbox Transition %p", Checked);
|
|
|
|
v4 TextColor = UI_TopTextColor();
|
|
TextColor.a = OpacityTransition;
|
|
|
|
UI_CornerRadius(2) UI_Size(UI_Em(1, 1), UI_Em(1, 1)) UI_Font(Font_Icons) UI_TextColor(TextColor)
|
|
UI_MakeBoxF(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawText, "%U", FontIcon_Cancel);
|
|
|
|
UI_Size(UI_TextContent(15, 1), UI_Em(1, 1)) UI_Label(String);
|
|
}
|
|
|
|
ui_signal Signal = UI_SignalFromBox(ContainerBox);
|
|
if(Signal.Hovering)
|
|
{
|
|
Platform.SetCursor(PlatformCursor_Hand);
|
|
}
|
|
|
|
if(Signal.Pressed)
|
|
{
|
|
*Checked = !*Checked;
|
|
}
|
|
|
|
return(Signal);
|
|
}
|
|
|
|
//- sixten: Scrollable regions
|
|
static ui_signal UI_Scrollbar(axis2 Axis, string Name, r32 Size, r32 Offset)
|
|
{
|
|
ui_signal Signal;
|
|
|
|
UI_SetNextAxisSize(Axis, UI_Percent(1, 0));
|
|
UI_SetNextAxisSize(Opposite(Axis), UI_Em(1, 1));
|
|
UI_SetNextBackgroundColor(Darken(UI_TopBackgroundColor(), 2));
|
|
UI_SetNextLayoutAxis(Axis);
|
|
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, Name))
|
|
{
|
|
UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1));
|
|
UI_SetNextFont(Font_Icons);
|
|
UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Axis?FontIcon_UpDir:FontIcon_LeftDir);
|
|
|
|
UI_Spacer(UI_Pixels(Offset, 1));
|
|
|
|
UI_SetNextAxisSize(Axis, UI_Pixels(Size, 1));
|
|
UI_SetNextAxisSize(Opposite(Axis), UI_Percent(1, 1));
|
|
|
|
Signal = UI_SignalFromBox(UI_MakeBox(UI_BoxFlag_DrawBorder |
|
|
UI_BoxFlag_DrawBackground |
|
|
UI_BoxFlag_Clickable |
|
|
UI_BoxFlag_HotAnimation |
|
|
UI_BoxFlag_ActiveAnimation,
|
|
StrLit("Slider")));
|
|
|
|
UI_Spacer(UI_Percent(1, 0));
|
|
|
|
UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1));
|
|
UI_SetNextFont(Font_Icons);
|
|
UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Axis?FontIcon_DownDir:FontIcon_RightDir);
|
|
}
|
|
|
|
return(Signal);
|
|
}
|
|
|
|
static void UI_ScrollBegin(r32 *X, r32 *Y, string Name)
|
|
{
|
|
u32 Flags = 0;
|
|
|
|
b32 AllowOnX = (X != 0);
|
|
b32 AllowOnY = (Y != 0);
|
|
|
|
UI_RowBegin(UI_BoxFlag_Clip|UI_BoxFlag_DrawBorder, Name);
|
|
{
|
|
UI_SetNextSize(UI_Percent(1, 0), UI_Percent(1, 0));
|
|
UI_ColumnBegin();
|
|
{
|
|
if(AllowOnX)
|
|
{
|
|
Flags |= UI_BoxFlag_OverflowX;
|
|
UI_SetNextOffsetX(-(*X));
|
|
}
|
|
|
|
if(AllowOnY)
|
|
{
|
|
Flags |= UI_BoxFlag_OverflowY;
|
|
UI_SetNextOffsetY(-(*Y));
|
|
}
|
|
|
|
UI_SetNextSize(AllowOnX?UI_ChildrenSum(1, 1):UI_Percent(1, 0),
|
|
AllowOnY?UI_ChildrenSum(1, 1):UI_Percent(1, 0));
|
|
|
|
ui_box *ScrollableBox = UI_MakeBox(Flags, StrLit("Scrollable Box"));
|
|
|
|
UI_PushParent(ScrollableBox);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void UI_ScrollEnd(r32 *X, r32 *Y)
|
|
{
|
|
b32 AllowOnX = (X != 0);
|
|
b32 AllowOnY = (Y != 0);
|
|
|
|
ui_box *ScrollableBox = UI_TopParent();
|
|
ui_signal ScrollableBoxSignal = UI_SignalFromBox(ScrollableBox);
|
|
{
|
|
{
|
|
UI_PopParent();
|
|
|
|
if(AllowOnX)
|
|
{
|
|
r32 TotalWidth = UI_CalculateBoxSize(ScrollableBox, Axis2_X);
|
|
r32 ViewWidth = UI_CalculateBoxSize(ScrollableBox->Parent->Parent, Axis2_X);
|
|
|
|
if(ViewWidth / TotalWidth < 1)
|
|
{
|
|
r32 TotalScrollWidth = ViewWidth - ScrollableBox->FontSize*2;
|
|
r32 ScrollScale = TotalScrollWidth / TotalWidth;
|
|
|
|
// sixten(TODO): Add a max of 1 em, and figure out the associated algebra.
|
|
r32 ScrollWidth = ViewWidth*ScrollScale;
|
|
r32 ScrollOffset = (*X)*ScrollScale;
|
|
|
|
ui_signal Signal = UI_Scrollbar(Axis2_X, StrLit("Scroll X"), ScrollWidth, ScrollOffset);
|
|
{
|
|
if(Signal.Dragging)
|
|
{
|
|
if(Signal.Pressed)
|
|
{
|
|
UI_StoreDragR32(*X);
|
|
}
|
|
|
|
r32 StartOffset = UI_GetDragR32();
|
|
r32 EndOffset = StartOffset + Signal.DragDelta.x/ScrollScale;
|
|
|
|
AnimationCurve_AnimateValueDirect(EndOffset, 0.2, X);
|
|
}
|
|
}
|
|
}
|
|
*X = Clamp(*X, 0, Max(0.0, TotalWidth - ViewWidth));
|
|
}
|
|
}
|
|
UI_ColumnEnd();
|
|
|
|
if(AllowOnY)
|
|
{
|
|
UI_SetNextSize(UI_ChildrenSum(1, 1), UI_Percent(1, 0));
|
|
UI_Column()
|
|
{
|
|
r32 TotalHeight = UI_CalculateBoxSize(ScrollableBox, Axis2_Y);
|
|
r32 ViewHeight = UI_CalculateBoxSize(ScrollableBox->Parent->Parent, Axis2_Y);
|
|
|
|
if(ViewHeight / TotalHeight < 1)
|
|
{
|
|
r32 TotalScrollHeight = ViewHeight - ScrollableBox->FontSize*2;
|
|
r32 ScrollScale = TotalScrollHeight / TotalHeight;
|
|
|
|
// sixten(TODO): Add a max of 1 em, and figure out the associated algebra.
|
|
r32 ScrollHeight = ViewHeight*ScrollScale;
|
|
r32 ScrollOffset = (*Y)*ScrollScale;
|
|
|
|
ui_signal Signal = UI_Scrollbar(Axis2_Y, StrLit("Scroll Y"), ScrollHeight, ScrollOffset);
|
|
{
|
|
if(Signal.Dragging)
|
|
{
|
|
if(Signal.Pressed)
|
|
{
|
|
UI_StoreDragR32(*Y);
|
|
}
|
|
|
|
r32 StartOffset = UI_GetDragR32();
|
|
r32 EndOffset = StartOffset + Signal.DragDelta.y/ScrollScale;
|
|
|
|
AnimationCurve_AnimateValueDirect(EndOffset, 0.2, Y);
|
|
}
|
|
}
|
|
}
|
|
*Y = Clamp(*Y, 0, Max(0.0, TotalHeight - ViewHeight));
|
|
}
|
|
// sixten: Add padding
|
|
if(AllowOnX && AllowOnY)
|
|
{
|
|
UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1));
|
|
UI_SetNextBackgroundColor(Darken(UI_TopBackgroundColor(), 2));
|
|
UI_MakeBox(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, StrLit("Padding"));
|
|
}
|
|
}
|
|
}
|
|
UI_RowEnd();
|
|
} |