aboutsummaryrefslogtreecommitdiff
path: root/kscurses/ui/line_input.jai
diff options
context:
space:
mode:
Diffstat (limited to 'kscurses/ui/line_input.jai')
-rw-r--r--kscurses/ui/line_input.jai122
1 files changed, 122 insertions, 0 deletions
diff --git a/kscurses/ui/line_input.jai b/kscurses/ui/line_input.jai
new file mode 100644
index 0000000..17823db
--- /dev/null
+++ b/kscurses/ui/line_input.jai
@@ -0,0 +1,122 @@
+Char_Type :: u8;
+UI_Line_Input :: struct {
+ #as using base : UI_Elem = .{type = .LINE_INPUT};
+ buffer : []Char_Type;
+
+ // resizeable := false;
+ ptr_left, ptr_right : int;
+ offset : int;
+}
+
+handle_key_line_input :: (ui_elem : *UI_Elem, key : Key) -> bool {
+ using ui_line_input := cast(*UI_Line_Input) ui_elem;
+
+ handle_inner :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
+ if is_printable(key) {
+ return add_char(ui_line_input, xx key);
+ } else if key == {
+ case .LEFT; #through;
+ case .RIGHT;
+ return move_ptr(ui_line_input, key);
+ case .BACKSPACE;
+ return remove_char_left(ui_line_input);
+ case .ESCAPE;
+ cursor_state = .ON;
+ return true;
+ }
+ return false;
+ }
+
+ if cursor_state == .IN {
+ return handle_inner(ui_line_input, key);
+ } else if cursor_state == .ON && key == .ENTER {
+ cursor_state = .IN;
+ return true;
+ }
+
+ return false;
+}
+c_draw_line_input :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
+ using cast(*UI_Line_Input) ui_elem;
+
+ fix_offset :: () #expand {
+ if ptr_left - offset < 0 {
+ offset = ptr_left;
+ } else if ptr_left - offset >= zone.width {
+ offset = ptr_left - zone.width + 1;
+ }
+ }
+ fix_offset();
+
+ left_part, right_part : string;
+ left_part.data, left_part.count = buffer.data, ptr_left;
+
+ right_part.data, right_part.count = buffer.data + ptr_right + 1, (buffer.count - ptr_right - 1);
+
+ c_draw_line_ascii(canvas, left_part, zone, .{xx -offset, 0}, style.text.default);
+ c_draw_line_ascii(canvas, right_part, zone, .{xx (ptr_left - offset), 0}, style.text.default);
+
+ terminal_state.cursor = ifx cursor_state == .IN then zone.corner + ivec2.{xx(ptr_left - offset), 0} else .{-1, -1};
+
+ return true;
+}
+
+init :: (using ui_line_input : *UI_Line_Input, max_length := 100) {
+ buffer = NewArray(max_length, Char_Type);
+ ptr_left, ptr_right = 0, max_length - 1;
+}
+add_char :: (using ui_line_input : *UI_Line_Input, c : Char_Type) -> bool {
+ if ptr_left > ptr_right return false;
+ buffer[ptr_left] = c;
+ ptr_left += 1;
+ return true;
+}
+remove_char_left :: (using ui_line_input : *UI_Line_Input) -> bool {
+ if ptr_left == 0 return false;
+ ptr_left -= 1;
+ return true;
+}
+move_ptr :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
+ if key == {
+ case .LEFT;
+ if ptr_left > 0 {
+ ptr_left -= 1;
+ buffer[ptr_right] = buffer[ptr_left];
+ ptr_right -= 1;
+ return true;
+ }
+ case .RIGHT;
+ if ptr_right < buffer.count-1 {
+ ptr_right += 1;
+ buffer[ptr_left] = buffer[ptr_right];
+ ptr_left += 1;
+ return true;
+ }
+ case;
+ assert(false);
+ }
+ return false;
+}
+deinit :: (using ui_line_input : *UI_Line_Input) {
+ array_free(buffer);
+}
+
+is_printable :: (key : Key) -> bool {
+ code := cast(u64) key;
+ return (code >= #char" " && code <= #char"~");
+}
+
+get_string :: (using ui_line_input : *UI_Line_Input, allocator := context.allocator) -> string {
+ result : string;
+ size := ptr_left + (buffer.count - ptr_right - 1);
+ result.count = size;
+ result.data = alloc(size, allocator);
+
+ memcpy(result.data, buffer.data, ptr_left);
+ memcpy(result.data + ptr_left, buffer.data + ptr_right + 1, buffer.count - ptr_right - 1);
+ return result;
+}
+reset :: (using ui_line_input : *UI_Line_Input) {
+ ptr_left = 0;
+ ptr_right = buffer.count - 1;
+} \ No newline at end of file