Line highlights
This commit is contained in:
@@ -28,6 +28,11 @@ struct History {
|
||||
int debug_edit_phase;
|
||||
};
|
||||
|
||||
struct ColoredString {
|
||||
Range range;
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct Window {
|
||||
Font font;
|
||||
float font_size;
|
||||
@@ -46,8 +51,9 @@ struct Window {
|
||||
Buffer buffer;
|
||||
History history;
|
||||
|
||||
Arena layout_arena;
|
||||
Layout layout;
|
||||
Array<ColoredString> colored_strings;
|
||||
Arena layout_arena;
|
||||
Layout layout;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
// @todo: highlight all occurences of selected word
|
||||
// @todo: systematic way of coloring words
|
||||
// @todo: line wrapping
|
||||
// @todo: search for word
|
||||
// @todo: context menu
|
||||
// @todo: toy around with acme ideas
|
||||
// @todo: undo tree
|
||||
// @todo: resize font, reload font
|
||||
// @todo: add clipboard history?
|
||||
#include "rect2.cpp"
|
||||
#include "buffer.cpp"
|
||||
@@ -85,6 +87,7 @@ int main() {
|
||||
window.font = font;
|
||||
window.font_size = font_size;
|
||||
window.font_spacing;
|
||||
window.colored_strings.allocator = FrameArena;
|
||||
InitArena(&window.layout_arena);
|
||||
InitBuffer(GetSystemAllocator(), &window.buffer);
|
||||
|
||||
@@ -294,6 +297,18 @@ int main() {
|
||||
it.range.min = it.range.max = line.max_without_new_line;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_PAGE_UP) || IsKeyPressedRepeat(KEY_PAGE_UP)) {
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_PAGE_DOWN) || IsKeyPressedRepeat(KEY_PAGE_DOWN)) {
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) {
|
||||
@@ -411,6 +426,16 @@ int main() {
|
||||
ApplyEdits(focused_window, edits);
|
||||
AfterEdit(focused_window, edits);
|
||||
}
|
||||
|
||||
{
|
||||
int64_t index = 0;
|
||||
String buffer_string = GetString(focused_window->buffer);
|
||||
if (Seek(buffer_string, "number", &index)) {
|
||||
Range range = {index, index + 6};
|
||||
focused_window->colored_strings.add({range, RED});
|
||||
}
|
||||
}
|
||||
|
||||
EventRecording_SimulateGetCharPressed(focused_window);
|
||||
}
|
||||
|
||||
@@ -427,7 +452,9 @@ int main() {
|
||||
// Draw and layout window overlay
|
||||
Vec2 mouse = GetMousePosition();
|
||||
{
|
||||
// @todo: why are we drawing this here??
|
||||
DrawRectangleRec(ToRectangle(window.rect), WHITE);
|
||||
DrawRectangleRec(ToRectangle(line_number_rect), WHITE);
|
||||
|
||||
Vec2 size = GetSize(window.rect);
|
||||
Vec2 min = window.scroll / (window.layout.buffer_world_pixel_size + size);
|
||||
@@ -613,34 +640,34 @@ int main() {
|
||||
Vec2 window_rect_size = GetSize(window.rect);
|
||||
BeginScissorMode((int)window.rect.min.x, (int)window.rect.min.y, (int)window_rect_size.x, (int)window_rect_size.y);
|
||||
|
||||
Range visible_line_range = CalculateVisibleLineRange(window);
|
||||
for (int64_t line = visible_line_range.min; line < visible_line_range.max; line += 1) {
|
||||
LayoutRow &row = window.layout.rows[line];
|
||||
Array<LayoutColumn> visible_columns = CalculateVisibleColumns(&FrameArena, window);
|
||||
Range visible_line_range = CalculateVisibleLineRange(window);
|
||||
|
||||
ForItem(col, row.columns) {
|
||||
Rect2 rect = {col.rect.min + window.rect.min - window.scroll, col.rect.max + window.rect.min - window.scroll};
|
||||
|
||||
if (!CheckCollisionRecs(ToRectangle(rect), ToRectangle(window.rect))) {
|
||||
continue; // Clip everything that is outside the window and screen
|
||||
}
|
||||
|
||||
if (col.codepoint == '\n') {
|
||||
DrawTextEx(font, "\\n", rect.min, font_size, font_spacing, GRAY);
|
||||
} else if (col.codepoint == '\0') {
|
||||
DrawTextEx(font, "\\0", rect.min, font_size, font_spacing, {255, 0, 0, 150});
|
||||
} else if ((col.codepoint != ' ') && (col.codepoint != '\t')) {
|
||||
DrawTextCodepoint(font, col.codepoint, rect.min, font_size, BLACK);
|
||||
}
|
||||
ForItem(col, visible_columns) {
|
||||
Rect2 rect = {col.rect.min + window.rect.min - window.scroll, col.rect.max + window.rect.min - window.scroll};
|
||||
if (col.codepoint == '\n') {
|
||||
DrawTextEx(font, "\\n", rect.min, font_size, font_spacing, GRAY);
|
||||
} else if (col.codepoint == '\0') {
|
||||
DrawTextEx(font, "\\0", rect.min, font_size, font_spacing, {255, 0, 0, 150});
|
||||
} else if ((col.codepoint != ' ') && (col.codepoint != '\t')) {
|
||||
DrawTextCodepoint(font, col.codepoint, rect.min, font_size, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
Array<LayoutColumn> visible_columns = CalculateVisibleColumns(&FrameArena, window);
|
||||
|
||||
// Draw cursor stuff
|
||||
Array<LayoutRow *> lines_to_highlight = {FrameArena};
|
||||
ForItem(cursor, window.cursors) {
|
||||
auto front = GetRowCol(window, GetFront(cursor));
|
||||
auto back = GetRowCol(window, GetBack(cursor));
|
||||
Tuple<LayoutRow *, LayoutColumn *> front = GetRowCol(window, GetFront(cursor));
|
||||
Tuple<LayoutRow *, LayoutColumn *> back = GetRowCol(window, GetBack(cursor));
|
||||
|
||||
// Line highlight
|
||||
lines_to_highlight.add(front.a);
|
||||
if (GetRangeSize(cursor.range) == 0) {
|
||||
Rect2 rect = front.a->rect + window.rect.min - window.scroll;
|
||||
DrawRectangleRec(ToRectangle(rect), {0, 0, 0, 30});
|
||||
}
|
||||
|
||||
// Selection
|
||||
For(visible_columns) {
|
||||
if (it.pos >= cursor.range.min && it.pos < cursor.range.max) {
|
||||
Rect2 rect = it.rect + window.rect.min - window.scroll;
|
||||
@@ -648,6 +675,7 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Cursor blocks
|
||||
if (front.b) {
|
||||
Rect2 rect = front.b->rect + window.rect.min - window.scroll;
|
||||
rect = CutLeft(&rect, 4);
|
||||
@@ -664,12 +692,19 @@ int main() {
|
||||
|
||||
// Draw line numbers
|
||||
{
|
||||
Rect2 rect = line_number_rect;
|
||||
BeginScissorMode((int)rect.min.x, (int)rect.min.y, (int)(rect.max.x - rect.min.x), (int)(rect.max.y - rect.min.y));
|
||||
BeginScissorMode((int)line_number_rect.min.x, (int)line_number_rect.min.y, (int)(line_number_rect.max.x - line_number_rect.min.x), (int)(line_number_rect.max.y - line_number_rect.min.y));
|
||||
for (int64_t line = visible_line_range.min; line < visible_line_range.max; line += 1) {
|
||||
LayoutRow &row = window.layout.rows[line];
|
||||
|
||||
Vec2 pos = {rect.min.x, row.rect.min.y + rect.min.y - window.scroll.y};
|
||||
Vec2 pos = {line_number_rect.min.x, row.rect.min.y + line_number_rect.min.y - window.scroll.y};
|
||||
For(lines_to_highlight) {
|
||||
if (it == &row) {
|
||||
Rect2 r = {pos, pos};
|
||||
r.max.x = line_number_rect.max.x;
|
||||
r.max.y += GetSize(row.rect).y;
|
||||
DrawRectangleRec(ToRectangle(r), {0, 0, 0, 30});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String line_num_string = Format(FrameArena, "%lld", (long long)line);
|
||||
DrawTextEx(font, line_num_string.data, pos, font_size, font_spacing, LIGHTGRAY);
|
||||
|
||||
@@ -14,6 +14,63 @@ Rectangle ToRectangle(Rect2 r) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; }
|
||||
Rect2 operator+(Rect2 r, Rect2 value) { return { r.min.x + value.min.x, r.min.y + value.min.y, r.max.x + value.max.x, r.max.y + value.max.y }; }
|
||||
Rect2 operator*(Rect2 r, Rect2 value) { return { r.min.x * value.min.x, r.min.y * value.min.y, r.max.x * value.max.x, r.max.y * value.max.y }; }
|
||||
Rect2 operator/(Rect2 r, Rect2 value) { return { r.min.x / value.min.x, r.min.y / value.min.y, r.max.x / value.max.x, r.max.y / value.max.y }; }
|
||||
|
||||
Rect2 operator-(Rect2 r, Vec2 value) { return { r.min.x - value.x, r.min.y - value.y, r.max.x - value.x, r.max.y - value.y }; }
|
||||
Rect2 operator+(Rect2 r, Vec2 value) { return { r.min.x + value.x, r.min.y + value.y, r.max.x + value.x, r.max.y + value.y }; }
|
||||
Rect2 operator*(Rect2 r, Vec2 value) { return { r.min.x * value.x, r.min.y * value.y, r.max.x * value.x, r.max.y * value.y }; }
|
||||
Rect2 operator/(Rect2 r, Vec2 value) { return { r.min.x / value.x, r.min.y / value.y, r.max.x / value.x, r.max.y / value.y }; }
|
||||
|
||||
Rect2 operator-(Rect2 r, float value) { return { r.min.x - value, r.min.y - value, r.max.x - value, r.max.y - value }; }
|
||||
Rect2 operator+(Rect2 r, float value) { return { r.min.x + value, r.min.y + value, r.max.x + value, r.max.y + value }; }
|
||||
Rect2 operator*(Rect2 r, float value) { return { r.min.x * value, r.min.y * value, r.max.x * value, r.max.y * value }; }
|
||||
Rect2 operator/(Rect2 r, float value) { return { r.min.x / value, r.min.y / value, r.max.x / value, r.max.y / value }; }
|
||||
|
||||
Rect2 operator-=(Rect2 &r, Rect2 value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, Rect2 value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, Rect2 value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, Rect2 value) { r = r / value; return r; }
|
||||
Rect2 operator-=(Rect2 &r, Vec2 value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, Vec2 value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, Vec2 value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, Vec2 value) { r = r / value; return r; }
|
||||
Rect2 operator-=(Rect2 &r, float value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, float value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, float value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, float value) { r = r / value; return r; }
|
||||
|
||||
Vec2 operator-(Vec2 a, Vec2 b) { return {a.x - b.x, a.y - b.y}; }
|
||||
Vec2 operator+(Vec2 a, Vec2 b) { return {a.x + b.x, a.y + b.y}; }
|
||||
Vec2 operator*(Vec2 a, Vec2 b) { return {a.x * b.x, a.y * b.y}; }
|
||||
Vec2 operator/(Vec2 a, Vec2 b) { return {a.x / b.x, a.y / b.y}; }
|
||||
|
||||
Vec2 operator-(Vec2 a, float b) { return {a.x - b, a.y - b}; }
|
||||
Vec2 operator+(Vec2 a, float b) { return {a.x + b, a.y + b}; }
|
||||
Vec2 operator*(Vec2 a, float b) { return {a.x * b, a.y * b}; }
|
||||
Vec2 operator/(Vec2 a, float b) { return {a.x / b, a.y / b}; }
|
||||
|
||||
Vec2 operator-=(Vec2 &a, Vec2 b) { a = a - b; return a; }
|
||||
Vec2 operator+=(Vec2 &a, Vec2 b) { a = a + b; return a; }
|
||||
Vec2 operator*=(Vec2 &a, Vec2 b) { a = a * b; return a; }
|
||||
Vec2 operator/=(Vec2 &a, Vec2 b) { a = a / b; return a; }
|
||||
Vec2 operator-=(Vec2 &a, float b) { a = a - b; return a; }
|
||||
Vec2 operator+=(Vec2 &a, float b) { a = a + b; return a; }
|
||||
Vec2 operator*=(Vec2 &a, float b) { a = a * b; return a; }
|
||||
Vec2 operator/=(Vec2 &a, float b) { a = a / b; return a; }
|
||||
|
||||
// clang-format on
|
||||
|
||||
Rect2 Rect2FromSize(Vec2 pos, Vec2 size) {
|
||||
Rect2 result = {};
|
||||
result.min = pos;
|
||||
result.max = pos + size;
|
||||
return result;
|
||||
}
|
||||
|
||||
Rect2 Shrink(Rect2 result, float v) {
|
||||
result.min.x += v;
|
||||
result.max.x -= v;
|
||||
@@ -71,53 +128,3 @@ Rect2 CutTop(Rect2 *r, float value) {
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; }
|
||||
Rect2 operator+(Rect2 r, Rect2 value) { return { r.min.x + value.min.x, r.min.y + value.min.y, r.max.x + value.max.x, r.max.y + value.max.y }; }
|
||||
Rect2 operator*(Rect2 r, Rect2 value) { return { r.min.x * value.min.x, r.min.y * value.min.y, r.max.x * value.max.x, r.max.y * value.max.y }; }
|
||||
Rect2 operator/(Rect2 r, Rect2 value) { return { r.min.x / value.min.x, r.min.y / value.min.y, r.max.x / value.max.x, r.max.y / value.max.y }; }
|
||||
|
||||
Rect2 operator-(Rect2 r, Vec2 value) { return { r.min.x - value.x, r.min.y - value.y, r.max.x - value.x, r.max.y - value.y }; }
|
||||
Rect2 operator+(Rect2 r, Vec2 value) { return { r.min.x + value.x, r.min.y + value.y, r.max.x + value.x, r.max.y + value.y }; }
|
||||
Rect2 operator*(Rect2 r, Vec2 value) { return { r.min.x * value.x, r.min.y * value.y, r.max.x * value.x, r.max.y * value.y }; }
|
||||
Rect2 operator/(Rect2 r, Vec2 value) { return { r.min.x / value.x, r.min.y / value.y, r.max.x / value.x, r.max.y / value.y }; }
|
||||
|
||||
Rect2 operator-(Rect2 r, float value) { return { r.min.x - value, r.min.y - value, r.max.x - value, r.max.y - value }; }
|
||||
Rect2 operator+(Rect2 r, float value) { return { r.min.x + value, r.min.y + value, r.max.x + value, r.max.y + value }; }
|
||||
Rect2 operator*(Rect2 r, float value) { return { r.min.x * value, r.min.y * value, r.max.x * value, r.max.y * value }; }
|
||||
Rect2 operator/(Rect2 r, float value) { return { r.min.x / value, r.min.y / value, r.max.x / value, r.max.y / value }; }
|
||||
|
||||
Rect2 operator-=(Rect2 &r, Rect2 value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, Rect2 value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, Rect2 value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, Rect2 value) { r = r / value; return r; }
|
||||
Rect2 operator-=(Rect2 &r, Vec2 value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, Vec2 value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, Vec2 value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, Vec2 value) { r = r / value; return r; }
|
||||
Rect2 operator-=(Rect2 &r, float value) { r = r - value; return r; }
|
||||
Rect2 operator+=(Rect2 &r, float value) { r = r + value; return r; }
|
||||
Rect2 operator*=(Rect2 &r, float value) { r = r * value; return r; }
|
||||
Rect2 operator/=(Rect2 &r, float value) { r = r / value; return r; }
|
||||
|
||||
Vec2 operator-(Vec2 a, Vec2 b) { return {a.x - b.x, a.y - b.y}; }
|
||||
Vec2 operator+(Vec2 a, Vec2 b) { return {a.x + b.x, a.y + b.y}; }
|
||||
Vec2 operator*(Vec2 a, Vec2 b) { return {a.x * b.x, a.y * b.y}; }
|
||||
Vec2 operator/(Vec2 a, Vec2 b) { return {a.x / b.x, a.y / b.y}; }
|
||||
|
||||
Vec2 operator-(Vec2 a, float b) { return {a.x - b, a.y - b}; }
|
||||
Vec2 operator+(Vec2 a, float b) { return {a.x + b, a.y + b}; }
|
||||
Vec2 operator*(Vec2 a, float b) { return {a.x * b, a.y * b}; }
|
||||
Vec2 operator/(Vec2 a, float b) { return {a.x / b, a.y / b}; }
|
||||
|
||||
Vec2 operator-=(Vec2 &a, Vec2 b) { a = a - b; return a; }
|
||||
Vec2 operator+=(Vec2 &a, Vec2 b) { a = a + b; return a; }
|
||||
Vec2 operator*=(Vec2 &a, Vec2 b) { a = a * b; return a; }
|
||||
Vec2 operator/=(Vec2 &a, Vec2 b) { a = a / b; return a; }
|
||||
Vec2 operator-=(Vec2 &a, float b) { a = a - b; return a; }
|
||||
Vec2 operator+=(Vec2 &a, float b) { a = a + b; return a; }
|
||||
Vec2 operator*=(Vec2 &a, float b) { a = a * b; return a; }
|
||||
Vec2 operator/=(Vec2 &a, float b) { a = a / b; return a; }
|
||||
|
||||
// clang-format on
|
||||
|
||||
Reference in New Issue
Block a user