Scrollbar

This commit is contained in:
Krzosa Karol
2024-07-22 09:59:52 +02:00
parent 254407e89e
commit b2d9688fbe
5 changed files with 121 additions and 50 deletions

View File

@@ -36,8 +36,11 @@ Color GruvboxFadedPurple = {0x8f, 0x3f, 0x71, 0xff};
Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff};
Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff};
Color ColorText = GruvboxDark0Hard;
Color ColorBackground = GruvboxLight0Hard;
Color ColorText = GruvboxDark0Hard;
Color ColorBackground = GruvboxLight0Hard;
Color ColorScrollbarBackground = GruvboxLight2;
Color ColorScrollbarScroller = GruvboxLight1;
Color ColorScrollbarScrollerSelected = GruvboxLight0Hard;
Color ColorLineHighlight = GruvboxLight1;
Color ColorMainCaret = GruvboxBrightRed;

View File

@@ -84,7 +84,8 @@ int main(void) {
while (!WindowShouldClose()) {
ProfileScope(game_loop);
view.rect = GetScreenRect();
view.rect = GetScreenRect();
view.scrollbar_rect = CutRight(&view.rect, 10);
BeginDrawing();
ClearBackground(ColorBackground);

View File

@@ -5,14 +5,24 @@ struct View {
Int line_spacing;
Int char_spacing;
Rect2I rect;
Rect2I scrollbar_rect;
Vec2I scroll;
bool mouse_selecting;
bool mouse_selecting_scrollbar;
Range selection_anchor;
Vec2I scroll;
Buffer *buffer;
Array<Caret> carets;
Rect2I rect;
};
Rect2I GetVisibleCells(const View &view);
void AfterEdit(View *view, Array<Edit> edits);
struct Scroller {
Rect2 rect;
double begin;
double end;
};
Rect2I GetVisibleCells(const View &view);
void AfterEdit(View *view, Array<Edit> edits);
Scroller ComputeScrollerRect(const View &view);

View File

@@ -287,53 +287,73 @@ void HandleKeybindings(View *_view) {
{
ProfileScope(mouse);
Vec2 _mouse = GetMousePosition();
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.rect));
Vec2I mouse = ToVec2I(_mouse);
Vec2 _mouse = GetMousePosition();
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.rect));
bool mouse_in_scrollbar = CheckCollisionPointRec(_mouse, ToRectangle(view.scrollbar_rect));
Vec2I mouse = ToVec2I(_mouse);
if (!view.mouse_selecting) {
if (mouse_in_view) {
SetMouseCursor(MOUSE_CURSOR_IBEAM);
} else {
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
}
}
Vec2I mworld = mouse - view.rect.min + view.scroll;
Vec2I pos = mworld / Vec2I{view.char_spacing, view.line_spacing};
XY xy = {(Int)(pos.x), (Int)(pos.y)};
Int p = XYToPosWithoutNL(buf, xy);
if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
if (!IsKeyDown(KEY_LEFT_CONTROL)) {
view.carets.len = 0;
if (!(mouse_in_scrollbar || view.mouse_selecting_scrollbar) && (mouse_in_view || view.mouse_selecting)) {
if (!view.mouse_selecting) {
if (mouse_in_view) {
SetMouseCursor(MOUSE_CURSOR_IBEAM);
} else {
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
}
Add(&view.carets, MakeCaret(p, p));
view.selection_anchor = GetLast(view.carets)->range;
if (IsDoubleClick()) {
Caret *c = GetLast(view.carets);
c->range = EncloseWord(buf, p);
view.selection_anchor = c->range;
}
Vec2I mworld = mouse - view.rect.min + view.scroll;
Vec2I pos = mworld / Vec2I{view.char_spacing, view.line_spacing};
XY xy = {(Int)(pos.x), (Int)(pos.y)};
Int p = XYToPosWithoutNL(buf, xy);
if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
if (!IsKeyDown(KEY_LEFT_CONTROL)) {
view.carets.len = 0;
}
Add(&view.carets, MakeCaret(p, p));
view.selection_anchor = GetLast(view.carets)->range;
if (IsDoubleClick()) {
Caret *c = GetLast(view.carets);
c->range = EncloseWord(buf, p);
view.selection_anchor = c->range;
}
MergeCarets(&view.carets);
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
view.mouse_selecting = true;
}
MergeCarets(&view.carets);
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
view.mouse_selecting = true;
}
}
if (view.mouse_selecting) {
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) view.mouse_selecting = false;
Caret &caret = *GetLast(view.carets);
if (view.selection_anchor.min > p) {
caret = MakeCaret(p, view.selection_anchor.max);
} else if (view.selection_anchor.max < p) {
caret = MakeCaret(p, view.selection_anchor.min);
} else {
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
if (view.mouse_selecting) {
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) view.mouse_selecting = false;
Caret &caret = *GetLast(view.carets);
if (view.selection_anchor.min > p) {
caret = MakeCaret(p, view.selection_anchor.max);
} else if (view.selection_anchor.max < p) {
caret = MakeCaret(p, view.selection_anchor.min);
} else {
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
}
MergeCarets(&view.carets, &view.selection_anchor);
}
} else if (!(mouse_in_view || view.mouse_selecting) && mouse_in_scrollbar || view.mouse_selecting_scrollbar) {
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
view.mouse_selecting_scrollbar = true;
} else if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
view.mouse_selecting_scrollbar = false;
}
if (view.mouse_selecting_scrollbar) {
double delta = GetMouseDelta().y;
Scroller s = ComputeScrollerRect(view);
double line_count = (double)view.buffer->line_starts.len;
double size_y = (double)GetSize(view.scrollbar_rect).y;
double v = delta / size_y;
view.scroll.y += (Int)(v * line_count * view.line_spacing);
}
MergeCarets(&view.carets, &view.selection_anchor);
}
}

View File

@@ -19,6 +19,22 @@ Rect2I GetVisibleCells(const View &view) {
return result;
}
Scroller ComputeScrollerRect(const View &view) {
Vec2I size = GetSize(view.scrollbar_rect);
Int line_count = view.buffer->line_starts.len;
Rect2I vis = GetVisibleCells(view);
double begin = (double)vis.min.y / (double)line_count;
double end = (double)vis.max.y / (double)line_count;
Rect2 rect = {
{(float)view.scrollbar_rect.min.x, (float)view.scrollbar_rect.min.y + (float)((double)size.y * begin)},
{(float)view.scrollbar_rect.max.x, (float)view.scrollbar_rect.min.y + (float)((double)size.y * end)},
};
Scroller result = {rect, begin, end};
return result;
}
void DrawVisibleText(const View &view) {
ProfileFunction();
Color tint = ColorText;
@@ -70,7 +86,10 @@ void DrawCaret(const View &view, XY xy, float size, Color color) {
void DrawLineHighlight(const View &view, XY fxy, Color color) {
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
w -= view.scroll;
Rect2I rect = Rect2IFromSize(w, {GetRenderWidth(), view.line_spacing});
Rect2I rect = {
{ 0, w.y},
{GetRenderWidth(), w.y + view.line_spacing}
};
DrawRectangleRec(ToRectangle(rect), color);
}
@@ -118,6 +137,8 @@ void DrawSelection(const View &view, Caret &it) {
void DrawView(View &view) {
Buffer &buf = *view.buffer;
BeginScissorMode((int)view.rect.min.x, (int)view.rect.min.y, (int)view.rect.max.x - (int)view.rect.min.x, (int)view.rect.max.y - (int)view.rect.min.y);
For(view.carets) {
Int front = GetFront(it);
XY fxy = PosToXY(buf, front);
@@ -136,4 +157,20 @@ void DrawView(View &view) {
bool main_caret = &it == &view.carets.data[0];
DrawCaret(view, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
}
}
EndScissorMode();
// Draw scrollbar
{
Vec2 mouse = GetMousePosition();
bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(view.scrollbar_rect));
DrawRectangleRec(ToRectangle(view.scrollbar_rect), ColorScrollbarBackground);
Scroller scroller = ComputeScrollerRect(view);
Rect2 rect = Shrink(scroller.rect, 2);
Color color = ColorScrollbarScroller;
if (!view.mouse_selecting && (view.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
color = ColorScrollbarScrollerSelected;
}
DrawRectangleRec(ToRectangle(rect), color);
}
}