Updated tests for strings, and added cursor to widget strings if the widget is currently being edited
This commit is contained in:
parent
bf72a52142
commit
3a04aab4fd
|
@ -6,12 +6,12 @@
|
||||||
#ifndef FOLDHAUS_EDITOR_DRAW_H
|
#ifndef FOLDHAUS_EDITOR_DRAW_H
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color)
|
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color, s32 CursorPosition)
|
||||||
{
|
{
|
||||||
gs_string Temp = PushString(State->Transient, 256);
|
gs_string Temp = PushString(State->Transient, 256);
|
||||||
PrintF(&Temp, "%d", Widget.Id.Id);
|
PrintF(&Temp, "%d", Widget.Id.Id);
|
||||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
|
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
|
||||||
Widget.String.Length,
|
Widget.String.Length + 1,
|
||||||
State->Interface.Style.Font->BitmapMemory,
|
State->Interface.Style.Font->BitmapMemory,
|
||||||
State->Interface.Style.Font->BitmapTextureHandle,
|
State->Interface.Style.Font->BitmapTextureHandle,
|
||||||
State->Interface.Style.Font->BitmapWidth,
|
State->Interface.Style.Font->BitmapWidth,
|
||||||
|
@ -25,7 +25,8 @@ Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffe
|
||||||
{
|
{
|
||||||
case Align_Left:
|
case Align_Left:
|
||||||
{
|
{
|
||||||
RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
|
RegisterPosition = DrawStringLeftAligned(RenderBuffer,
|
||||||
|
&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color, CursorPosition, GreenV4);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case Align_Right:
|
case Align_Right:
|
||||||
|
@ -82,6 +83,8 @@ Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* Ren
|
||||||
rect2 WidgetParentUnion = Widget.Bounds;
|
rect2 WidgetParentUnion = Widget.Bounds;
|
||||||
WidgetParentUnion = Rect2Union(Widget.Bounds, ParentClipBounds);
|
WidgetParentUnion = Rect2Union(Widget.Bounds, ParentClipBounds);
|
||||||
|
|
||||||
|
bool IsActiveWidget = ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget);
|
||||||
|
;
|
||||||
if (!Widget.Parent || (Rect2Area(WidgetParentUnion) > 0))
|
if (!Widget.Parent || (Rect2Area(WidgetParentUnion) > 0))
|
||||||
{
|
{
|
||||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawBackground))
|
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawBackground))
|
||||||
|
@ -101,7 +104,13 @@ Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* Ren
|
||||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
|
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
|
||||||
{
|
{
|
||||||
v4 Color = State->Interface.Style.TextColor;
|
v4 Color = State->Interface.Style.TextColor;
|
||||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, Color);
|
s32 CursorPosition = -1;
|
||||||
|
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_Typable) && IsActiveWidget)
|
||||||
|
{
|
||||||
|
CursorPosition = State->Interface.CursorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, Color, CursorPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) ||
|
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) ||
|
||||||
|
@ -122,11 +131,14 @@ Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* Ren
|
||||||
{
|
{
|
||||||
// TODO(pjs): add this color to the style
|
// TODO(pjs): add this color to the style
|
||||||
v4 TextColor = BlackV4;
|
v4 TextColor = BlackV4;
|
||||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor);
|
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawOutline))
|
bool DrawOutline = ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawOutline);
|
||||||
|
DrawOutline |= ui_WidgetIsFlagSet(Widget, UIWidgetFlag_Typable) && IsActiveWidget;
|
||||||
|
|
||||||
|
if (DrawOutline)
|
||||||
{
|
{
|
||||||
// TODO(pjs): replace these with values from the style
|
// TODO(pjs): replace these with values from the style
|
||||||
r32 Thickness = 1.0f;
|
r32 Thickness = 1.0f;
|
||||||
|
|
|
@ -335,7 +335,7 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r
|
||||||
r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames);
|
r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames);
|
||||||
r32 FrameX = LerpR32(FramePercent, BarBounds.Min.x, BarBounds.Max.x);
|
r32 FrameX = LerpR32(FramePercent, BarBounds.Min.x, BarBounds.Max.x);
|
||||||
v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2};
|
v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2};
|
||||||
DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, FrameTextPos, WhiteV4);
|
DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, FrameTextPos, WhiteV4, -1, GreenV4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time Slider
|
// Time Slider
|
||||||
|
@ -352,7 +352,7 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r
|
||||||
v2 HeadMin = v2{SliderX - SliderHalfWidth, BarBounds.Min.y};
|
v2 HeadMin = v2{SliderX - SliderHalfWidth, BarBounds.Min.y};
|
||||||
v2 HeadMax = v2{SliderX + SliderHalfWidth, BarBounds.Max.y};
|
v2 HeadMax = v2{SliderX + SliderHalfWidth, BarBounds.Max.y};
|
||||||
PushRenderQuad2D(Interface.RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
PushRenderQuad2D(Interface.RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
||||||
DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4);
|
DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4, -1, GreenV4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ DrawLayerMenu(animation_system* AnimationSystem, animation ActiveAnim, ui_interf
|
||||||
{
|
{
|
||||||
PushRenderBoundingBox2D(Interface.RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4);
|
PushRenderBoundingBox2D(Interface.RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4);
|
||||||
}
|
}
|
||||||
DrawString(Interface.RenderBuffer, Layer->Name, Interface.Style.Font, LayerTextPos, WhiteV4);
|
DrawString(Interface.RenderBuffer, Layer->Name, Interface.Style.Font, LayerTextPos, WhiteV4, -1, GreenV4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +573,7 @@ FrameCount_Render(animation_timeline_state* TimelineState, animation* ActiveAnim
|
||||||
r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames);
|
r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames);
|
||||||
r32 FrameX = LerpR32(FramePercent, Bounds.Min.x, Bounds.Max.x);
|
r32 FrameX = LerpR32(FramePercent, Bounds.Min.x, Bounds.Max.x);
|
||||||
v2 FrameTextPos = v2{FrameX, Bounds.Min.y + 2};
|
v2 FrameTextPos = v2{FrameX, Bounds.Min.y + 2};
|
||||||
DrawString(Interface->RenderBuffer, TempString, Interface->Style.Font, FrameTextPos, WhiteV4);
|
DrawString(Interface->RenderBuffer, TempString, Interface->Style.Font, FrameTextPos, WhiteV4, -1, GreenV4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time Slider
|
// Time Slider
|
||||||
|
@ -591,7 +591,7 @@ FrameCount_Render(animation_timeline_state* TimelineState, animation* ActiveAnim
|
||||||
v2 HeadMin = v2{SliderX - SliderHalfWidth, Bounds.Min.y};
|
v2 HeadMin = v2{SliderX - SliderHalfWidth, Bounds.Min.y};
|
||||||
v2 HeadMax = v2{SliderX + SliderHalfWidth, Bounds.Max.y};
|
v2 HeadMax = v2{SliderX + SliderHalfWidth, Bounds.Max.y};
|
||||||
PushRenderQuad2D(Interface->RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
PushRenderQuad2D(Interface->RenderBuffer, HeadMin, HeadMax, TimeSliderColor);
|
||||||
DrawString(Interface->RenderBuffer, TempString, Interface->Style.Font, HeadMin + v2{6, 4}, WhiteV4);
|
DrawString(Interface->RenderBuffer, TempString, Interface->Style.Font, HeadMin + v2{6, 4}, WhiteV4, -1, GreenV4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interaction
|
// Interaction
|
||||||
|
@ -620,7 +620,7 @@ LayerList_DrawLayerButton (ui_interface* Interface, gs_string Name, rect2 Bounds
|
||||||
{
|
{
|
||||||
PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, 1, BoxColor);
|
PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, 1, BoxColor);
|
||||||
}
|
}
|
||||||
DrawString(Interface->RenderBuffer, Name, Interface->Style.Font, TextPos, WhiteV4);
|
DrawString(Interface->RenderBuffer, Name, Interface->Style.Font, TextPos, WhiteV4, -1, GreenV4);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ SculptureView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren
|
||||||
gs_string Tempgs_string = PushString(State->Transient, 256);
|
gs_string Tempgs_string = PushString(State->Transient, 256);
|
||||||
PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id,
|
PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id,
|
||||||
State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id);
|
State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id);
|
||||||
DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4);
|
DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4, -1, GreenV4);
|
||||||
|
|
||||||
}
|
}
|
||||||
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
|
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
|
||||||
|
|
|
@ -487,6 +487,13 @@ PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 Min, v2 Max, v
|
||||||
v2{0, 0}, v2{1, 1}, Color);
|
v2{0, 0}, v2{1, 1}, Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, rect2 Rect, v4 Color)
|
||||||
|
{
|
||||||
|
PushQuad2DOnBatch(Constructor, v2{Rect.Min.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Max.y}, v2{Rect.Min.x, Rect.Max.y},
|
||||||
|
v2{0, 0}, v2{1, 1}, Color);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 Thickness, v4 Color)
|
PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 Thickness, v4 Color)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,17 +99,35 @@ DrawCharacterRightAligned (render_quad_batch_constructor* BatchConstructor, char
|
||||||
return PointAfterCharacter;
|
return PointAfterCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawCursor (render_command_buffer* RenderBuffer, v2 RegisterPosition, bitmap_font* Font, v4 Color)
|
||||||
|
{
|
||||||
|
rect2 CursorRect = {};
|
||||||
|
CursorRect.Min = RegisterPosition;
|
||||||
|
CursorRect.Max = CursorRect.Min + v2{5, (r32)Font->Ascent};
|
||||||
|
PushRenderQuad2D(RenderBuffer, CursorRect, Color);
|
||||||
|
}
|
||||||
|
|
||||||
internal v2
|
internal v2
|
||||||
DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, rect2 ClippingBox, v4 Color)
|
DrawStringLeftAligned (render_command_buffer* RenderBuffer, render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, rect2 ClippingBox, v4 Color, s32 CursorBeforeIndex, v4 CursorColor)
|
||||||
{
|
{
|
||||||
v2 RegisterPosition = InitialRegisterPosition;
|
v2 RegisterPosition = InitialRegisterPosition;
|
||||||
char* C = gs_string;
|
char* C = gs_string;
|
||||||
for (s32 i = 0; i < Length; i++)
|
for (s32 i = 0; i < Length; i++)
|
||||||
{
|
{
|
||||||
|
if (i == CursorBeforeIndex)
|
||||||
|
{
|
||||||
|
DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor);
|
||||||
|
}
|
||||||
|
|
||||||
v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color);
|
v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color);
|
||||||
RegisterPosition.x = PositionAfterCharacter.x;
|
RegisterPosition.x = PositionAfterCharacter.x;
|
||||||
C++;
|
C++;
|
||||||
}
|
}
|
||||||
|
if (CursorBeforeIndex == Length)
|
||||||
|
{
|
||||||
|
DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor);
|
||||||
|
}
|
||||||
return RegisterPosition;
|
return RegisterPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +146,12 @@ DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Len
|
||||||
}
|
}
|
||||||
|
|
||||||
internal v2
|
internal v2
|
||||||
DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* Font, v2 Position, v4 Color, gs_string_alignment Alignment = Align_Left)
|
DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* Font, v2 Position, v4 Color, s32 CursorPosition, v4 CursorColor, gs_string_alignment Alignment = Align_Left)
|
||||||
{
|
{
|
||||||
DEBUG_TRACK_FUNCTION;
|
DEBUG_TRACK_FUNCTION;
|
||||||
v2 LowerRight = Position;
|
v2 LowerRight = Position;
|
||||||
|
|
||||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length,
|
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length + 1,
|
||||||
Font->BitmapMemory,
|
Font->BitmapMemory,
|
||||||
Font->BitmapTextureHandle,
|
Font->BitmapTextureHandle,
|
||||||
Font->BitmapWidth,
|
Font->BitmapWidth,
|
||||||
|
@ -152,7 +170,7 @@ DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* F
|
||||||
v2 RegisterPosition = Position;
|
v2 RegisterPosition = Position;
|
||||||
if (Alignment == Align_Left)
|
if (Alignment == Align_Left)
|
||||||
{
|
{
|
||||||
RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color);
|
RegisterPosition = DrawStringLeftAligned(RenderBuffer, &BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color, CursorPosition, CursorColor);
|
||||||
}
|
}
|
||||||
else if (Alignment == Align_Right)
|
else if (Alignment == Align_Right)
|
||||||
{
|
{
|
||||||
|
@ -359,6 +377,7 @@ struct ui_interface
|
||||||
|
|
||||||
// A per-frame string of the characters which have been typed
|
// A per-frame string of the characters which have been typed
|
||||||
gs_const_string TempInputString;
|
gs_const_string TempInputString;
|
||||||
|
u64 CursorPosition;
|
||||||
|
|
||||||
render_command_buffer* RenderBuffer;
|
render_command_buffer* RenderBuffer;
|
||||||
|
|
||||||
|
@ -980,6 +999,11 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
|
||||||
{
|
{
|
||||||
Result.Clicked = true;
|
Result.Clicked = true;
|
||||||
Interface->ActiveWidget = Widget->Id;
|
Interface->ActiveWidget = Widget->Id;
|
||||||
|
|
||||||
|
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable))
|
||||||
|
{
|
||||||
|
Interface->CursorPosition = Widget->String.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,11 +1037,12 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
|
||||||
{
|
{
|
||||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||||
|
|
||||||
|
Interface->CursorPosition = Clamp(0, Interface->CursorPosition, State->EditString.Length);
|
||||||
for (u32 i = 0; i < Interface->TempInputString.Length; i++)
|
for (u32 i = 0; i < Interface->TempInputString.Length; i++)
|
||||||
{
|
{
|
||||||
if (Interface->TempInputString.Str[i] == '\b')
|
if (Interface->TempInputString.Str[i] == '\b')
|
||||||
{
|
{
|
||||||
if (State->EditString.Length > 0)
|
if (Interface->CursorPosition > 0)
|
||||||
{
|
{
|
||||||
State->EditString.Length -= 1;
|
State->EditString.Length -= 1;
|
||||||
}
|
}
|
||||||
|
@ -1030,71 +1055,6 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// if you can click it
|
|
||||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Clickable))
|
|
||||||
{
|
|
||||||
// updating hot widget, and handling mouse clicks
|
|
||||||
if (PointIsInRect(Widget->Parent->Bounds, Interface->Mouse.Pos) &&
|
|
||||||
PointIsInRect(Widget->Bounds, Interface->Mouse.Pos))
|
|
||||||
{
|
|
||||||
if (ui_WidgetIdsEqual(Interface->HotWidget, Widget->Id) && MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState))
|
|
||||||
{
|
|
||||||
Result.Clicked = true;
|
|
||||||
Interface->ActiveWidget = Widget->Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Interface->HotWidget = Widget->Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// click and drag
|
|
||||||
if (MouseButtonHeldDown(Interface->Mouse.LeftButtonState) &&
|
|
||||||
PointIsInRect(Widget->Bounds, Interface->Mouse.DownPos))
|
|
||||||
{
|
|
||||||
Result.Held = true;
|
|
||||||
Result.DragDelta = Interface->Mouse.Pos - Interface->Mouse.DownPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this is the active widget (its been clicked)
|
|
||||||
if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id))
|
|
||||||
{
|
|
||||||
// if you can select it
|
|
||||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Selectable))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState) &&
|
|
||||||
!PointIsInRect(Widget->Bounds, Interface->Mouse.Pos))
|
|
||||||
{
|
|
||||||
Interface->ActiveWidget = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable) &&
|
|
||||||
Interface->TempInputString.Length > 0)
|
|
||||||
{
|
|
||||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
|
||||||
|
|
||||||
// TODO(pjs): Backspace?
|
|
||||||
for (u32 i = 0; i < Interface->TempInputString.Length; i++)
|
|
||||||
{
|
|
||||||
if (Interface->TempInputString.Str[i] == '\b')
|
|
||||||
{
|
|
||||||
State->EditString.Length -= 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OutChar(&State->EditString, Interface->TempInputString.Str[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (MouseButtonTransitionedUp(Interface->Mouse.LeftButtonState))
|
|
||||||
{
|
|
||||||
Interface->ActiveWidget = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Assert(Widget->Parent != 0);
|
Assert(Widget->Parent != 0);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1522,54 +1522,91 @@ Substring(gs_const_string String, u64 First, u64 Last)
|
||||||
Result.Length = Min(Last - First, String.Length);
|
Result.Length = Min(Last - First, String.Length);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
internal u64
|
internal gs_const_string
|
||||||
|
Substring(gs_string String, u64 First, u64 Last)
|
||||||
|
{
|
||||||
|
return Substring(String.ConstString, First, Last);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal s64
|
||||||
FindFirst(gs_const_string String, u64 StartIndex, char C)
|
FindFirst(gs_const_string String, u64 StartIndex, char C)
|
||||||
{
|
{
|
||||||
u64 Result = StartIndex;
|
s64 Result = -1;
|
||||||
for(; Result < String.Length && C != String.Str[Result]; Result++);
|
for(u64 i = StartIndex; i < String.Length; i++)
|
||||||
|
{
|
||||||
|
if (String.Str[i] == C) {
|
||||||
|
Result = (s64)i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
internal u64
|
internal s64
|
||||||
FindFirst(gs_const_string String, char C)
|
FindFirst(gs_const_string String, char C)
|
||||||
{
|
{
|
||||||
return FindFirst(String, 0, C);
|
return FindFirst(String, 0, C);
|
||||||
}
|
}
|
||||||
|
internal s64
|
||||||
internal u64
|
FindFirst(gs_string String, u64 StartIndex, char C)
|
||||||
FindLast(gs_const_string String, u64 StartIndex, char C)
|
|
||||||
{
|
{
|
||||||
s64 Result = StartIndex;
|
return FindFirst(String.ConstString, StartIndex, C);
|
||||||
for(; Result >= 0 && C != String.Str[Result]; Result--);
|
}
|
||||||
return (u64)Result;
|
internal s64
|
||||||
|
FindFirst(gs_string String, char C)
|
||||||
|
{
|
||||||
|
return FindFirst(String.ConstString, 0, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u64
|
internal s64
|
||||||
|
FindLast(gs_const_string String, u64 StartIndex, char C)
|
||||||
|
{
|
||||||
|
s64 Result = -1;
|
||||||
|
for(s64 i= StartIndex; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (String.Str[i] == C) {
|
||||||
|
Result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (u64)Result;
|
||||||
|
}
|
||||||
|
internal s64
|
||||||
FindLast(gs_const_string String, char C)
|
FindLast(gs_const_string String, char C)
|
||||||
{
|
{
|
||||||
return FindLast(String, String.Length - 1, C);
|
return FindLast(String, String.Length - 1, C);
|
||||||
}
|
}
|
||||||
|
internal s64
|
||||||
|
FindLast(gs_string String, u64 StartIndex, char C)
|
||||||
|
{
|
||||||
|
return FindLast(String.ConstString, StartIndex, C);
|
||||||
|
}
|
||||||
|
internal s64
|
||||||
|
FindLast(gs_string String, char C)
|
||||||
|
{
|
||||||
|
return FindLast(String.ConstString, String.Length - 1, C);
|
||||||
|
}
|
||||||
|
|
||||||
internal u64
|
internal s64
|
||||||
FindFirstFromSet(gs_const_string String, char* SetArray)
|
FindFirstFromSet(gs_const_string String, char* SetArray)
|
||||||
{
|
{
|
||||||
gs_const_string Set = ConstString(SetArray);
|
gs_const_string Set = ConstString(SetArray);
|
||||||
u64 Result = String.Length - 1;
|
s64 Result = -1;
|
||||||
for(u64 At = 0; At < String.Length; At++)
|
|
||||||
{
|
s64 CurrMin = String.Length;
|
||||||
char CharAt = String.Str[At];
|
|
||||||
for (u64 SetAt = 0; SetAt < Set.Length; SetAt++)
|
for (u64 SetAt = 0; SetAt < Set.Length; SetAt++)
|
||||||
{
|
{
|
||||||
if (CharAt == Set.Str[SetAt])
|
s64 Index = FindFirst(String, Set.Str[SetAt]);
|
||||||
|
if (Index >= 0 && Index < CurrMin)
|
||||||
{
|
{
|
||||||
Result = At;
|
CurrMin = Index;
|
||||||
// NOTE(Peter): The alternative to this goto is a break in the inner loop
|
|
||||||
// followed by an if check in the outer loop, that must be evaluated
|
|
||||||
// every character you check. This is more efficient
|
|
||||||
goto find_last_from_set_complete;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CurrMin < (s64)String.Length)
|
||||||
|
{
|
||||||
|
Result = CurrMin;
|
||||||
}
|
}
|
||||||
find_last_from_set_complete:
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1648,6 +1685,12 @@ StringEqualsCharArray(gs_const_string A, char* B, u64 Length)
|
||||||
return StringsEqual(A, BStr);
|
return StringsEqual(A, BStr);
|
||||||
}
|
}
|
||||||
internal bool
|
internal bool
|
||||||
|
StringEqualsCharArray(gs_const_string A, char* B)
|
||||||
|
{
|
||||||
|
u64 Length = CStringLength(B);
|
||||||
|
return StringEqualsCharArray(A, B, Length);
|
||||||
|
}
|
||||||
|
internal bool
|
||||||
StringsEqualUpToLength(gs_string A, gs_string B, u64 Length)
|
StringsEqualUpToLength(gs_string A, gs_string B, u64 Length)
|
||||||
{
|
{
|
||||||
return StringsEqualUpToLength(A.ConstString, B.ConstString, Length);
|
return StringsEqualUpToLength(A.ConstString, B.ConstString, Length);
|
||||||
|
@ -1660,8 +1703,12 @@ StringsEqual(gs_string A, gs_string B)
|
||||||
internal bool
|
internal bool
|
||||||
StringEqualsCharArray(gs_string A, char* B, u64 Length)
|
StringEqualsCharArray(gs_string A, char* B, u64 Length)
|
||||||
{
|
{
|
||||||
gs_string BStr = MakeString(B, Length);
|
return StringEqualsCharArray(A.ConstString, B, Length);
|
||||||
return StringsEqual(A, BStr);
|
}
|
||||||
|
internal bool
|
||||||
|
StringEqualsCharArray(gs_string A, char* B)
|
||||||
|
{
|
||||||
|
return StringEqualsCharArray(A.ConstString, B);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u64
|
internal u64
|
||||||
|
@ -1907,6 +1954,39 @@ AppendString(gs_string* Base, gs_string Appendix)
|
||||||
{
|
{
|
||||||
return AppendString(Base, Appendix.ConstString);
|
return AppendString(Base, Appendix.ConstString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
InsertAt(gs_string* Str, u64 Index, char C)
|
||||||
|
{
|
||||||
|
if (Str->Length > Index)
|
||||||
|
{
|
||||||
|
for (u64 i = Str->Length; i > Index; i--)
|
||||||
|
{
|
||||||
|
Str->Str[i] = Str->Str[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index < Str->Size)
|
||||||
|
{
|
||||||
|
Str->Str[Index] = C;
|
||||||
|
Str->Length += 1;
|
||||||
|
Assert(Str->Length < Str->Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
RemoveAt(gs_string* Str, u64 Index)
|
||||||
|
{
|
||||||
|
if (Str->Length > 0 && Index < Str->Length)
|
||||||
|
{
|
||||||
|
for (u64 i = Index; i < Str->Length - 1; i++)
|
||||||
|
{
|
||||||
|
Str->Str[i] = Str->Str[i + 1];
|
||||||
|
}
|
||||||
|
Str->Length -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
NullTerminate(gs_string* String)
|
NullTerminate(gs_string* String)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,15 @@ gs_memory_arena Scratch = {};
|
||||||
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
|
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
|
||||||
void Free(void* Ptr, u64 Size) { return free(Ptr); }
|
void Free(void* Ptr, u64 Size) { return free(Ptr); }
|
||||||
|
|
||||||
|
bool StringTest (gs_const_string StrA, gs_const_string StrB)
|
||||||
|
{
|
||||||
|
return StringsEqual(StrA, StrB);
|
||||||
|
}
|
||||||
|
bool StringTest (gs_string StrA, gs_string StrB)
|
||||||
|
{
|
||||||
|
return StringsEqual(StrA, StrB);
|
||||||
|
}
|
||||||
|
|
||||||
bool PathTest (char* In, char* Out) {
|
bool PathTest (char* In, char* Out) {
|
||||||
return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out));
|
return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out));
|
||||||
}
|
}
|
||||||
|
@ -24,6 +33,59 @@ int main (int ArgCount, char** Args)
|
||||||
{
|
{
|
||||||
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free));
|
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free));
|
||||||
|
|
||||||
|
Test("gs_string")
|
||||||
|
{
|
||||||
|
gs_string TestString = PushStringF(&Scratch, 256, "Hello there, Sailor!");
|
||||||
|
|
||||||
|
NullTerminate(&TestString);
|
||||||
|
TestResult(IsNullTerminated(TestString));
|
||||||
|
|
||||||
|
TestResult(StringTest(GetStringPrefix(TestString.ConstString, 5), ConstString("Hello")));
|
||||||
|
TestResult(StringTest(GetStringPostfix(TestString.ConstString, 5), ConstString("ilor!")));
|
||||||
|
TestResult(StringTest(GetStringAfter(TestString.ConstString, 13), ConstString("Sailor!")));
|
||||||
|
TestResult(StringTest(GetStringBefore(TestString.ConstString, 5), ConstString("Hello")));
|
||||||
|
TestResult(StringTest(Substring(TestString.ConstString, 5, 11), ConstString(" there")));
|
||||||
|
|
||||||
|
TestResult(FindFirst(TestString, 5, 'l') == 16);
|
||||||
|
TestResult(FindFirst(TestString, 0, 'k') == -1);
|
||||||
|
TestResult(FindLast(TestString, 10, 'l') == 3);
|
||||||
|
TestResult(FindLast(TestString, 'k') == -1);
|
||||||
|
|
||||||
|
TestResult(FindFirstFromSet(TestString.ConstString, "re") == 1);
|
||||||
|
TestResult(FindFirstFromSet(TestString.ConstString, "er") == 1);
|
||||||
|
TestResult(FindFirstFromSet(TestString.ConstString, "bk") == -1);
|
||||||
|
TestResult(FindFirstFromSet(TestString.ConstString, "ek") == 1);
|
||||||
|
|
||||||
|
TestResult(FindLastFromSet(TestString.ConstString, "re") == 18);
|
||||||
|
TestResult(FindLastFromSet(TestString.ConstString, "er") == 18);
|
||||||
|
TestResult(FindLastFromSet(TestString.ConstString, "bk") == -1);
|
||||||
|
TestResult(FindLastFromSet(TestString.ConstString, "rk") == 18);
|
||||||
|
|
||||||
|
TestResult(StringContains(TestString.ConstString, ','));
|
||||||
|
TestResult(!StringContains(TestString.ConstString, '@'));
|
||||||
|
TestResult(StringsEqual(TestString, TestString));
|
||||||
|
|
||||||
|
TestResult(StringEqualsCharArray(TestString, "Hello there, Sailor!"));
|
||||||
|
TestResult(!StringEqualsCharArray(TestString, "Hello there, Sailor"));
|
||||||
|
TestResult(!StringEqualsCharArray(TestString, "Foobar"));
|
||||||
|
|
||||||
|
ReverseStringInPlace(&TestString);
|
||||||
|
TestResult(StringTest(TestString, MakeString("!roliaS ,ereht olleH")));
|
||||||
|
ReverseStringInPlace(&TestString);
|
||||||
|
|
||||||
|
TestResult(ParseUInt(ConstString("532")) == 532);
|
||||||
|
TestResult(ParseInt(ConstString("-1234567890")) == -1234567890);
|
||||||
|
TestResult(ParseFloat(ConstString("-12345.6789")) == -12345.6789);
|
||||||
|
|
||||||
|
TestString.Length = 0;
|
||||||
|
U64ToASCII(&TestString, 53298, 10);
|
||||||
|
TestResult(StringTest(TestString.ConstString, ConstString("53298")));
|
||||||
|
|
||||||
|
TestString.Length = 0;
|
||||||
|
R64ToASCII(&TestString, 145732.321, 2);
|
||||||
|
TestResult(StringTest(TestString.ConstString, ConstString("145732.32")));
|
||||||
|
}
|
||||||
|
|
||||||
Test("gs_path.h")
|
Test("gs_path.h")
|
||||||
{
|
{
|
||||||
TestResult(PathTest(".", "."));
|
TestResult(PathTest(".", "."));
|
||||||
|
|
Loading…
Reference in New Issue