diff options
| -rw-r--r-- | src/ui_elements/TextEditor.c | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c index e114080..13401d8 100644 --- a/src/ui_elements/TextEditor.c +++ b/src/ui_elements/TextEditor.c @@ -5,6 +5,7 @@ #include "../resources/resources.h" #include <ctype.h> #include <raylib.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -22,6 +23,30 @@ float GetCursorXPos(TextArea *ta) { return x_position; } +// Returns the position the cursor should be in on the given offset. +size_t GetCharIdxByOffset(TextArea *ta, int line, float offset) { + if (ta == NULL) return 0; + TextNode *node = ta->StartNode; + for (int i = 0; i < line; i++) { + node = node->NextNode; + if (node == NULL) return 0; + } + + for (int i = 0; i < node->len; i++) { + char original_char = node->text[i + 1]; + node->text[i + 1] = '\0'; + + float width = MeasureTextEx(*ta->DisplayParams->font, + node->text, + ta->DisplayParams->font_size, + ta->DisplayParams->spacing).x; + + node->text[i + 1] = original_char; + if (width > offset) return i; + } + return node->len; +} + /// We pass x_position not to call GetCursorXPos twice (it's expencive) void DrawCursor(TextArea *ta, Vector2 lineStartPos, float x_position) { DrawLine(lineStartPos.x + x_position, lineStartPos.y, @@ -284,6 +309,31 @@ void MoveCursorHome(TextArea *ta) { ta->CursorPosition.x = 0; } +// Moves cursor to the position +void MoveCursorTo(TextArea *ta, int x, int y) { + // Making sure we are in bounds + if (y >= ta->NodeLenth) y = ta->NodeLenth - 1; + if (y < 0) y = 0; + if (x < 0) x = 0; + + if (ta->CursorPosition.y < y) { + int diff = y - ta->CursorPosition.y; + for (int i = 0; i < diff; i++) { + ta->CurrentNode = ta->CurrentNode->NextNode; + } + } else if (ta->CursorPosition.y > y) { + int diff = ta->CursorPosition.y - y; + for (int i = 0; i < diff; i++) { + ta->CurrentNode = ta->CurrentNode->PrevNode; + } + } + + ta->CursorPosition.y = y; + // We could't make sure that was the case before + if (x > ta->CurrentNode->len) x = ta->CurrentNode->len; + ta->CursorPosition.x = x; +} + size_t GetStartingSpaces(char *string) { if (string == NULL) return 0; size_t idx = 0, len = strlen(string); @@ -479,6 +529,16 @@ void PrintAllLines(TextArea *ta) { } } +/// Returns the position on the text field excluding onscreen offset and scroll +Vector2 absolutePosToTextPos(TextArea *ta, Rectangle *rec, Vector2 pos) { + if (ta == NULL || ta->DisplayParams == NULL || rec == NULL) + return (Vector2){0, 0}; + return (Vector2) { + .x = pos.x - rec->x + ta->DisplayParams->scroll_h, + .y = pos.y - rec->y + ta->DisplayParams->scroll_v, + }; +} + /// Assumes that control is pressed void HandleControlComands(TextArea *ta) { if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRightWord(ta); @@ -563,19 +623,34 @@ void HandleScroll(TextArea *ta, Rectangle rec) { // lazy eval caching } else { int text_height = ta->NodeLenth * ta->DisplayParams->font_size; - int max_scroll = text_height - rec.height; + int max_scroll = text_height - ta->DisplayParams->font_size * 2; ta->DisplayParams->scroll_v -= scroll; if (ta->DisplayParams->scroll_v < 0) ta->DisplayParams->scroll_v = 0; - if (text_height > rec.height && ta->DisplayParams->scroll_v > max_scroll) + if (max_scroll > 0 && ta->DisplayParams->scroll_v > max_scroll) ta->DisplayParams->scroll_v = max_scroll; } } +void HandleMouseEvents(TextArea *ta, Rectangle *rec) { + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + Vector2 mousePos = GetMousePosition(); + Vector2 onTextPos = absolutePosToTextPos(ta, rec, mousePos); + int cursorLine = (int)(onTextPos.y / ta->DisplayParams->font_size); + size_t cursorChar = GetCharIdxByOffset(ta, cursorLine, onTextPos.x); + // TraceLog(LOG_INFO, "Mouse pos: { %d; %d }", (int)mousePos.x, (int)mousePos.y); + // TraceLog(LOG_INFO, "OnScreen pos: { %d; %d }", (int)onTextPos.x, (int)onTextPos.y); + // TraceLog(LOG_INFO, "Line: %d", cursorLine); + // TraceLog(LOG_INFO, "Char: %zu", cursorChar); + MoveCursorTo(ta, cursorChar, cursorLine); + } +} + void UpdateTextArea(TextArea *ta, Rectangle rec) { HandleKeyboard(ta); if (IsMouseInRec(rec)) { HandleScroll(ta, rec); + HandleMouseEvents(ta, &rec); } } |
