Scrollbar
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user