Experimenting with key bindings
This commit is contained in:
@@ -249,7 +249,7 @@ struct Slice {
|
||||
|
||||
template <class T>
|
||||
Slice<T> Copy(Allocator alo, Slice<T> array) {
|
||||
Slice<T> result = {alo};
|
||||
Slice<T> result = {};
|
||||
result.data = AllocArray(alo, T, array.len);
|
||||
memcpy(result.data, array.data, sizeof(T) * array.len);
|
||||
result.len = array.len;
|
||||
@@ -824,7 +824,7 @@ struct Table {
|
||||
size_t old_cap = cap;
|
||||
|
||||
values = (Entry *)AllocSize(allocator, sizeof(Entry) * size);
|
||||
for (int64_t i = 0; i < size; i += 1) values[i] = {};
|
||||
for (size_t i = 0; i < size; i += 1) values[i] = {};
|
||||
cap = size;
|
||||
|
||||
Assert(!(old_values == 0 && len != 0));
|
||||
|
||||
@@ -38,7 +38,7 @@ Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff};
|
||||
|
||||
Color ColorText = GruvboxDark0Hard;
|
||||
Color ColorBackground = GruvboxLight0Hard;
|
||||
Color ColorSelection = GruvboxLight3;
|
||||
Color ColorLineHighlight = GruvboxLight2;
|
||||
Color ColorSelection = GruvboxLight1;
|
||||
Color ColorLineHighlight = GruvboxLight1;
|
||||
Color ColorMainCaret = GruvboxBrightRed;
|
||||
Color ColorSubCaret = GruvboxGray245;
|
||||
@@ -28,8 +28,6 @@
|
||||
- Ctrl + Alt + Down - duplicate line down
|
||||
- Shify + Alt + Down - make a cursor below
|
||||
- Mouse anchor point and double click
|
||||
- Mouse cursor changes
|
||||
- Color new lines and end of buffer
|
||||
- Scrollbars
|
||||
- Line numbers
|
||||
- Colored strings
|
||||
|
||||
@@ -163,12 +163,171 @@ void MultiCursorReplace(View *view, String16 string) {
|
||||
AfterEdit(view, edits);
|
||||
}
|
||||
|
||||
union KeyEncode {
|
||||
struct {
|
||||
U32 key;
|
||||
U8 ctrl : 1;
|
||||
U8 alt : 1;
|
||||
U8 shift : 1;
|
||||
};
|
||||
U64 u64;
|
||||
};
|
||||
typedef void CommandProc(View *view);
|
||||
Table<CommandProc *> RegisteredBindings;
|
||||
|
||||
KeyEncode Key(int key) {
|
||||
KeyEncode result = {};
|
||||
result.key = key;
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEncode KeyControl(int key) {
|
||||
KeyEncode result = {};
|
||||
result.key = key;
|
||||
result.ctrl = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEncode KeyShiftControl(int key) {
|
||||
KeyEncode result = {};
|
||||
result.key = key;
|
||||
result.ctrl = true;
|
||||
result.shift = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEncode KeyControlAlt(int key) {
|
||||
KeyEncode result = {};
|
||||
result.key = key;
|
||||
result.ctrl = true;
|
||||
result.alt = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEncode KeyShiftAlt(int key) {
|
||||
KeyEncode result = {};
|
||||
result.key = key;
|
||||
result.shift = true;
|
||||
result.alt = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void RegisterBinding(CommandProc *proc, KeyEncode key) {
|
||||
RegisteredBindings.insert(key.u64, proc);
|
||||
}
|
||||
|
||||
void CommandClearCarets(View *view) {
|
||||
view->carets.len = 1;
|
||||
}
|
||||
|
||||
void HandleKeybindings(View *_view) {
|
||||
ProfileFunction();
|
||||
View &view = *_view;
|
||||
Buffer &buf = *view.buffer;
|
||||
Caret main_caret_on_begin_frame = view.carets[0];
|
||||
|
||||
if (RegisteredBindings.cap == 0) {
|
||||
RegisterBinding(CommandClearCarets, Key(KEY_ESCAPE));
|
||||
}
|
||||
|
||||
{
|
||||
KeyEncode key = {};
|
||||
key.ctrl = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);
|
||||
key.alt = IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT);
|
||||
key.shift = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
|
||||
|
||||
int keys[] = {
|
||||
KEY_APOSTROPHE,
|
||||
KEY_COMMA,
|
||||
KEY_MINUS,
|
||||
KEY_PERIOD,
|
||||
KEY_SLASH,
|
||||
KEY_ZERO,
|
||||
KEY_ONE,
|
||||
KEY_TWO,
|
||||
KEY_THREE,
|
||||
KEY_FOUR,
|
||||
KEY_FIVE,
|
||||
KEY_SIX,
|
||||
KEY_SEVEN,
|
||||
KEY_EIGHT,
|
||||
KEY_NINE,
|
||||
KEY_SEMICOLON,
|
||||
KEY_EQUAL,
|
||||
KEY_A,
|
||||
KEY_B,
|
||||
KEY_C,
|
||||
KEY_D,
|
||||
KEY_E,
|
||||
KEY_F,
|
||||
KEY_G,
|
||||
KEY_H,
|
||||
KEY_I,
|
||||
KEY_J,
|
||||
KEY_K,
|
||||
KEY_L,
|
||||
KEY_M,
|
||||
KEY_N,
|
||||
KEY_O,
|
||||
KEY_P,
|
||||
KEY_Q,
|
||||
KEY_R,
|
||||
KEY_S,
|
||||
KEY_T,
|
||||
KEY_U,
|
||||
KEY_V,
|
||||
KEY_W,
|
||||
KEY_X,
|
||||
KEY_Y,
|
||||
KEY_Z,
|
||||
KEY_LEFT_BRACKET,
|
||||
KEY_BACKSLASH,
|
||||
KEY_RIGHT_BRACKET,
|
||||
KEY_GRAVE,
|
||||
KEY_SPACE,
|
||||
KEY_ESCAPE,
|
||||
KEY_ENTER,
|
||||
KEY_TAB,
|
||||
KEY_BACKSPACE,
|
||||
KEY_INSERT,
|
||||
KEY_DELETE,
|
||||
KEY_RIGHT,
|
||||
KEY_LEFT,
|
||||
KEY_DOWN,
|
||||
KEY_UP,
|
||||
KEY_PAGE_UP,
|
||||
KEY_PAGE_DOWN,
|
||||
KEY_HOME,
|
||||
KEY_END,
|
||||
KEY_CAPS_LOCK,
|
||||
KEY_SCROLL_LOCK,
|
||||
KEY_NUM_LOCK,
|
||||
KEY_PRINT_SCREEN,
|
||||
KEY_PAUSE,
|
||||
KEY_F1,
|
||||
KEY_F2,
|
||||
KEY_F3,
|
||||
KEY_F4,
|
||||
KEY_F5,
|
||||
KEY_F6,
|
||||
KEY_F7,
|
||||
KEY_F8,
|
||||
KEY_F9,
|
||||
KEY_F10,
|
||||
KEY_F11,
|
||||
KEY_F12,
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(keys); i += 1) {
|
||||
bool press = IsKeyPressed(keys[i]) || IsKeyPressedRepeat(keys[i]);
|
||||
if (!press) continue;
|
||||
key.key = keys[i];
|
||||
|
||||
CommandProc *proc = RegisteredBindings.get(key.u64, NULL);
|
||||
if (proc) proc(&view);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_F1)) {
|
||||
view.scroll.x -= (Int)(GetMouseWheelMove() * 48);
|
||||
} else {
|
||||
@@ -183,11 +342,43 @@ void HandleKeybindings(View *_view) {
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_ESCAPE)) {
|
||||
if (IsKeyPressed(KEY_ESCAPE) || IsKeyPressedRepeat(KEY_ESCAPE)) {
|
||||
view.carets.len = 1;
|
||||
}
|
||||
|
||||
{
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_LEFT_ALT) && (IsKeyPressed(KEY_DOWN) || IsKeyPressedRepeat(KEY_DOWN))) {
|
||||
For(view.carets) it = MakeCaret(GetFront(it));
|
||||
MergeCarets(&view.carets);
|
||||
|
||||
Scratch scratch;
|
||||
Array<Edit> edits = {scratch};
|
||||
For(view.carets) {
|
||||
Int line = PosToLine(buf, it.range.min);
|
||||
Range range = GetLineRange(buf, line);
|
||||
String16 string = Copy(scratch, GetString(buf, range));
|
||||
AddEdit(&edits, {range.max, range.max}, string);
|
||||
}
|
||||
ApplyEdits(&buf, edits);
|
||||
AfterEdit(&view, edits);
|
||||
|
||||
For(view.carets) it = MakeCaret(MoveCaret(buf, it.range.min, 2, false));
|
||||
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_LEFT_ALT) && (IsKeyPressed(KEY_UP) || IsKeyPressedRepeat(KEY_UP))) {
|
||||
For(view.carets) it = MakeCaret(GetFront(it));
|
||||
MergeCarets(&view.carets);
|
||||
|
||||
Scratch scratch;
|
||||
Array<Edit> edits = {scratch};
|
||||
For(view.carets) {
|
||||
Int line = PosToLine(buf, it.range.min);
|
||||
Range range = GetLineRange(buf, line);
|
||||
String16 string = Copy(scratch, GetString(buf, range));
|
||||
AddEdit(&edits, {range.min, range.min}, string);
|
||||
}
|
||||
ApplyEdits(&buf, edits);
|
||||
AfterEdit(&view, edits);
|
||||
|
||||
For(view.carets) it = MakeCaret(MoveCaret(buf, it.range.min, 3, false));
|
||||
} else {
|
||||
int keys[4] = {KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP};
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
if (IsKeyPressed(keys[i]) || IsKeyPressedRepeat(keys[i])) {
|
||||
@@ -277,10 +468,19 @@ void HandleKeybindings(View *_view) {
|
||||
|
||||
{
|
||||
ProfileScope(mouse);
|
||||
|
||||
Vec2 _mouse = GetMousePosition();
|
||||
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.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)};
|
||||
|
||||
@@ -19,10 +19,12 @@ Rect2I GetVisibleCells(const View &view) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawVisibleCells(const View &view) {
|
||||
void DrawVisibleText(const View &view) {
|
||||
ProfileFunction();
|
||||
Color tint = ColorText;
|
||||
Rect2I visible = GetVisibleCells(view);
|
||||
Color tint = ColorText;
|
||||
Color space_color = tint;
|
||||
space_color.a = 50;
|
||||
Rect2I visible = GetVisibleCells(view);
|
||||
for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < view.buffer->line_starts.len; line_index += 1) {
|
||||
Range line_range = GetLineRange(*view.buffer, line_index);
|
||||
String16 line_string = GetString(*view.buffer, line_range);
|
||||
@@ -37,7 +39,9 @@ void DrawVisibleCells(const View &view) {
|
||||
|
||||
if (codepoint == '\n') {
|
||||
DrawCircle((int)pos.x + (int)text_offset_x + (int)view.char_spacing / 2, (int)pos.y + (int)view.line_spacing / 2, (float)view.font_size / 10.f, tint);
|
||||
} else if ((codepoint != ' ') && (codepoint != '\t')) {
|
||||
} else if (codepoint == ' ') {
|
||||
DrawCircle((int)pos.x + (int)text_offset_x + (int)view.char_spacing / 2, (int)pos.y + (int)view.line_spacing / 2, (float)view.font_size / 10.f, space_color);
|
||||
} else if (codepoint != '\t') {
|
||||
DrawTextCodepoint(view.font, codepoint, {(float)pos.x + text_offset_x, (float)pos.y}, (float)view.font_size, tint);
|
||||
}
|
||||
|
||||
@@ -118,11 +122,14 @@ void DrawView(View &view) {
|
||||
Int back = GetBack(it);
|
||||
XY bxy = PosToXY(buf, back);
|
||||
|
||||
DrawLineHighlight(view, fxy, ColorLineHighlight);
|
||||
DrawSelection(view, it);
|
||||
if (GetSize(it.range)) {
|
||||
DrawSelection(view, it);
|
||||
} else {
|
||||
DrawLineHighlight(view, fxy, ColorLineHighlight);
|
||||
}
|
||||
}
|
||||
|
||||
DrawVisibleCells(view);
|
||||
DrawVisibleText(view);
|
||||
|
||||
For(view.carets) {
|
||||
Int front = GetFront(it);
|
||||
|
||||
Reference in New Issue
Block a user