Scrollbar
This commit is contained in:
@@ -36,8 +36,11 @@ Color GruvboxFadedPurple = {0x8f, 0x3f, 0x71, 0xff};
|
|||||||
Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff};
|
Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff};
|
||||||
Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff};
|
Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff};
|
||||||
|
|
||||||
Color ColorText = GruvboxDark0Hard;
|
Color ColorText = GruvboxDark0Hard;
|
||||||
Color ColorBackground = GruvboxLight0Hard;
|
Color ColorBackground = GruvboxLight0Hard;
|
||||||
|
Color ColorScrollbarBackground = GruvboxLight2;
|
||||||
|
Color ColorScrollbarScroller = GruvboxLight1;
|
||||||
|
Color ColorScrollbarScrollerSelected = GruvboxLight0Hard;
|
||||||
|
|
||||||
Color ColorLineHighlight = GruvboxLight1;
|
Color ColorLineHighlight = GruvboxLight1;
|
||||||
Color ColorMainCaret = GruvboxBrightRed;
|
Color ColorMainCaret = GruvboxBrightRed;
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ int main(void) {
|
|||||||
|
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
ProfileScope(game_loop);
|
ProfileScope(game_loop);
|
||||||
view.rect = GetScreenRect();
|
view.rect = GetScreenRect();
|
||||||
|
view.scrollbar_rect = CutRight(&view.rect, 10);
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(ColorBackground);
|
ClearBackground(ColorBackground);
|
||||||
|
|||||||
@@ -5,14 +5,24 @@ struct View {
|
|||||||
Int line_spacing;
|
Int line_spacing;
|
||||||
Int char_spacing;
|
Int char_spacing;
|
||||||
|
|
||||||
|
Rect2I rect;
|
||||||
|
Rect2I scrollbar_rect;
|
||||||
|
Vec2I scroll;
|
||||||
|
|
||||||
bool mouse_selecting;
|
bool mouse_selecting;
|
||||||
|
bool mouse_selecting_scrollbar;
|
||||||
Range selection_anchor;
|
Range selection_anchor;
|
||||||
|
|
||||||
Vec2I scroll;
|
|
||||||
Buffer *buffer;
|
Buffer *buffer;
|
||||||
Array<Caret> carets;
|
Array<Caret> carets;
|
||||||
Rect2I rect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rect2I GetVisibleCells(const View &view);
|
struct Scroller {
|
||||||
void AfterEdit(View *view, Array<Edit> edits);
|
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);
|
ProfileScope(mouse);
|
||||||
|
|
||||||
Vec2 _mouse = GetMousePosition();
|
Vec2 _mouse = GetMousePosition();
|
||||||
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.rect));
|
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.rect));
|
||||||
Vec2I mouse = ToVec2I(_mouse);
|
bool mouse_in_scrollbar = CheckCollisionPointRec(_mouse, ToRectangle(view.scrollbar_rect));
|
||||||
|
Vec2I mouse = ToVec2I(_mouse);
|
||||||
|
|
||||||
if (!view.mouse_selecting) {
|
if (!(mouse_in_scrollbar || view.mouse_selecting_scrollbar) && (mouse_in_view || view.mouse_selecting)) {
|
||||||
if (mouse_in_view) {
|
if (!view.mouse_selecting) {
|
||||||
SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
if (mouse_in_view) {
|
||||||
} else {
|
SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
||||||
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
|
} 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;
|
|
||||||
}
|
}
|
||||||
Add(&view.carets, MakeCaret(p, p));
|
}
|
||||||
view.selection_anchor = GetLast(view.carets)->range;
|
|
||||||
if (IsDoubleClick()) {
|
Vec2I mworld = mouse - view.rect.min + view.scroll;
|
||||||
Caret *c = GetLast(view.carets);
|
Vec2I pos = mworld / Vec2I{view.char_spacing, view.line_spacing};
|
||||||
c->range = EncloseWord(buf, p);
|
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||||
view.selection_anchor = c->range;
|
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 (view.mouse_selecting) {
|
||||||
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) view.mouse_selecting = false;
|
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) view.mouse_selecting = false;
|
||||||
Caret &caret = *GetLast(view.carets);
|
Caret &caret = *GetLast(view.carets);
|
||||||
if (view.selection_anchor.min > p) {
|
if (view.selection_anchor.min > p) {
|
||||||
caret = MakeCaret(p, view.selection_anchor.max);
|
caret = MakeCaret(p, view.selection_anchor.max);
|
||||||
} else if (view.selection_anchor.max < p) {
|
} else if (view.selection_anchor.max < p) {
|
||||||
caret = MakeCaret(p, view.selection_anchor.min);
|
caret = MakeCaret(p, view.selection_anchor.min);
|
||||||
} else {
|
} else {
|
||||||
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
|
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;
|
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) {
|
void DrawVisibleText(const View &view) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Color tint = ColorText;
|
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) {
|
void DrawLineHighlight(const View &view, XY fxy, Color color) {
|
||||||
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
||||||
w -= view.scroll;
|
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);
|
DrawRectangleRec(ToRectangle(rect), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +137,8 @@ void DrawSelection(const View &view, Caret &it) {
|
|||||||
|
|
||||||
void DrawView(View &view) {
|
void DrawView(View &view) {
|
||||||
Buffer &buf = *view.buffer;
|
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) {
|
For(view.carets) {
|
||||||
Int front = GetFront(it);
|
Int front = GetFront(it);
|
||||||
XY fxy = PosToXY(buf, front);
|
XY fxy = PosToXY(buf, front);
|
||||||
@@ -136,4 +157,20 @@ void DrawView(View &view) {
|
|||||||
bool main_caret = &it == &view.carets.data[0];
|
bool main_caret = &it == &view.carets.data[0];
|
||||||
DrawCaret(view, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
|
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