diff options
Diffstat (limited to 'kscurses/ui')
| -rw-r--r-- | kscurses/ui/button.jai | 25 | ||||
| -rw-r--r-- | kscurses/ui/element.jai | 156 | ||||
| -rw-r--r-- | kscurses/ui/group.jai | 44 | ||||
| -rw-r--r-- | kscurses/ui/line_input.jai | 122 | ||||
| -rw-r--r-- | kscurses/ui/links.jai | 94 | ||||
| -rw-r--r-- | kscurses/ui/master.jai | 105 | ||||
| -rw-r--r-- | kscurses/ui/parent.jai | 33 | ||||
| -rw-r--r-- | kscurses/ui/popup_manager.jai | 65 | ||||
| -rw-r--r-- | kscurses/ui/progress_bar.jai | 37 | ||||
| -rw-r--r-- | kscurses/ui/scalable_group.jai | 88 | ||||
| -rw-r--r-- | kscurses/ui/scene_manager.jai | 48 | ||||
| -rw-r--r-- | kscurses/ui/select_list.jai | 79 | ||||
| -rw-r--r-- | kscurses/ui/style.jai | 118 | ||||
| -rw-r--r-- | kscurses/ui/table.jai | 87 | ||||
| -rw-r--r-- | kscurses/ui/text_buf.jai | 15 | ||||
| -rw-r--r-- | kscurses/ui/tilemap.jai | 20 |
16 files changed, 0 insertions, 1136 deletions
diff --git a/kscurses/ui/button.jai b/kscurses/ui/button.jai deleted file mode 100644 index 3866e03..0000000 --- a/kscurses/ui/button.jai +++ /dev/null @@ -1,25 +0,0 @@ -UI_Button :: struct { - #as using base : UI_Elem = .{type = .BUTTON}; - text := ""; - on_click : struct { - proc := (data : *void){}; - data : *void; - }; -} - -handle_key_button :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using cast(*UI_Button) ui_elem; - assert(cursor_state == .ON); - assert(!links.inner); - if key == .ENTER { - on_click.proc(on_click.data); - return true; - } - return false; -} -c_draw_button :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Button) ui_elem; - mode := ifx cursor_state == .ON && box_type == .NONE then style.text.cursor else style.text.default; - c_draw_line_ascii(canvas, text, zone, .{(zone.width - xx text.count) / 2, xx ((zone.height - 1) / 2)}, mode); - return true; -} diff --git a/kscurses/ui/element.jai b/kscurses/ui/element.jai deleted file mode 100644 index 3db8fcb..0000000 --- a/kscurses/ui/element.jai +++ /dev/null @@ -1,156 +0,0 @@ -UI_Elem :: struct { - type : enum u8 { - NONE :: 0; - BUTTON :: 1; - TEXT_BUF :: 2; - GROUP :: 3; - SELECT_LIST :: 4; - SCENE_MANAGER :: 5; - POPUP_MANAGER :: 6; - LINE_INPUT :: 7; - SCALABLE_GROUP :: 8; - TABLE :: 9; - PROGRESS_BAR :: 10; - } = .NONE; - - using visual_data : struct { - cursor_state : enum u8 { OUTSIDE :: 0; ON :: 1; IN :: 2; } = .OUTSIDE; - box_type : enum u8 { NONE :: 0; BORDER :: 1; NO_BORDER :: 2; } = .BORDER; - description_pos : enum u8 { TOP_LEFT :: 0; TOP_CENTER :: 1; TOP_RIGHT :: 2; BOTTOM_LEFT :: 4; BOTTOM_CENTER :: 5; BOTTOM_RIGHT :: 6; } = .TOP_LEFT; - description := ""; - } - - using links : struct { - left, right, bottom, top, inner, outer : *UI_Elem; - parent : *UI_Parent; - } - - extra_handler : struct { - proc : (key : Key, data : *void) -> bool = null; - data : *void; - } -} - - -vtable_c_draw : []#type (*Canvas, *UI_Elem, Ibox2, *UI_Style) -> (bool) = .[ - c_draw_default, - c_draw_button, - c_draw_textbuf, - c_draw_group, - c_draw_select_list, - c_draw_scene_manager, - c_draw_popup_manager, - c_draw_line_input, - c_draw_scalable_group, - c_draw_table, - c_draw_progress_bar -]; -c_draw :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - ok := box_type == .NONE || c_box(canvas, zone, ifx cursor_state == .ON && __ui_master.blink_stage != 1 then style.box.cursor else style.box.default, box_type == .BORDER); - if !ok return false; - ok = c_draw_description(canvas, ui_elem, zone, style); - if !ok return false; - - content_zone := ifx box_type == .BORDER then cut_border(zone, 1) else zone; - - c_draw_proc := vtable_c_draw[xx ui_elem.type]; - assert(xx c_draw_proc); - return c_draw_proc(canvas, ui_elem, content_zone, style); -} -c_draw_default :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { return true; }; - -intersection_line :: (box : Ibox2, _line : string, _start : ivec2) -> line:string, start:ivec2 { - line, start := _line, _start; - if start.x < box.left { - line.count += start.x - box.left; - start.x = box.left; - } - if start.x + line.count > box.left + box.width { - line.count = box.left + box.width - start.x; - } - return line, start; -} - -c_draw_line_ascii_raw :: (canvas : *Canvas, line : string, start : ivec2, mode : Graphics_Mode) { - for x : 0..line.count-1 c_putchar(canvas, .{code = xx line[x], mode = mode}, start + ivec2.{xx x, 0}); -} - -c_draw_line_ascii :: (canvas : *Canvas, _line : string, _start : ivec2, mode : Graphics_Mode) { - line, start := intersection_line(canvas.zone, _line, _start); - c_draw_line_ascii_raw(canvas, line, start, mode); -} -c_draw_line_ascii :: (canvas : *Canvas, _line : string, bounds : Ibox2, offset : ivec2, mode : Graphics_Mode) { - assert(inside(bounds, canvas.zone)); - line, start := intersection_line(bounds, _line, bounds.corner + offset); - c_draw_line_ascii_raw(canvas, line, start, mode); -} -c_draw_description :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - if !description return true; - if description.count > zone.width - 2 return false; - - top_or_bottom := !(description_pos & 4); - y := ifx top_or_bottom then zone.top else zone.top + zone.height - 1; - - mode := style.text.default; - if description_pos & 3 == { - case 0; c_draw_line_ascii(canvas, description, .{zone.left + 1, y}, mode); - case 1; c_draw_line_ascii(canvas, description, .{xx (zone.left + (zone.width - description.count) / 2), y}, mode); - case 2; c_draw_line_ascii(canvas, description, .{xx (zone.left + zone.width - description.count - 1), y}, mode); - case; assert(false); - } - return true; -} - -vtable_handle_key : []#type (*UI_Elem, Key) -> (bool) = .[ - handle_key_none, - handle_key_button, - handle_key_none, - handle_key_group, - handle_key_select_list, - handle_key_scene_manager, - handle_key_popup_manager, - handle_key_line_input, - handle_key_scalable_group, - handle_key_table, - handle_key_none -]; -handle_key :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool { - handle_proc := vtable_handle_key[ui_elem.type]; - assert(xx handle_proc); - - handled := handle_proc(ui_elem, key); - // assert(cursor_state == .ON || cursor_state == .IN); - if !handled && cursor_state == .ON { - handled = handle_key_move(ui_elem, key); - } - - if !handled && extra_handler.proc { - handled = extra_handler.proc(key, extra_handler.data); - } - return handled; -} -handle_key_none :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool { return false; } -handle_key_move :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool { - __ui_master.blink_stage = 0; - restart_clock_cycle(); - - active_elem := ui_elem; - assert(active_elem.cursor_state == .ON); - try_move :: (new_elem : *UI_Elem) #expand { - if new_elem { - unset_active_recursive(`active_elem); - set_active_recursive(new_elem); - `active_elem = new_elem; - } - } - if key == { - case .LEFT; try_move(links.left); - case .RIGHT; try_move(links.right); - case .UP; try_move(links.top); - case .DOWN; try_move(links.bottom); - case .ESCAPE; try_move(links.outer); - case .ENTER; try_move(links.inner);; - } - assert(active_elem.cursor_state == .ON); - return ui_elem != active_elem; -}
\ No newline at end of file diff --git a/kscurses/ui/group.jai b/kscurses/ui/group.jai deleted file mode 100644 index 366c513..0000000 --- a/kscurses/ui/group.jai +++ /dev/null @@ -1,44 +0,0 @@ -UI_Group :: struct { - #as using base_parent : UI_Parent = .{type = .GROUP}; - - Element :: struct { - ptr : *UI_Elem; - zone : Ibox2; - } - - elements : []Element; -} -set_sub_elements :: (group : *UI_Group, elements : ..UI_Group.Element) { - group.elements = elements; - for e : elements { - e.ptr.parent = group; - } -} -c_draw_group :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Group) ui_elem; - for e : elements { - e_zone := e.zone; - if !inside(e_zone, zone.size) return false; - e_zone.corner += zone.corner; - if !c_draw(canvas, e.ptr, e_zone, style) return false; - } - return true; -} -handle_key_group :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using cast(*UI_Group) ui_elem; - assert(cursor_state == .ON || cursor_state == .OUTSIDE); - - handled := false; - if cursor_state == .OUTSIDE { - assert(xx active_element); - { - ok := false; - for e : elements if e.ptr == active_element ok = true; - assert(ok); - } - handled = handle_key(active_element, key); - } else { - assert(xx !active_element); - } - return handled; -}
\ No newline at end of file diff --git a/kscurses/ui/line_input.jai b/kscurses/ui/line_input.jai deleted file mode 100644 index 17823db..0000000 --- a/kscurses/ui/line_input.jai +++ /dev/null @@ -1,122 +0,0 @@ -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 diff --git a/kscurses/ui/links.jai b/kscurses/ui/links.jai deleted file mode 100644 index dc8c667..0000000 --- a/kscurses/ui/links.jai +++ /dev/null @@ -1,94 +0,0 @@ -link_lr :: (el : *UI_Elem, er : *UI_Elem) { - el.right = er; - er.left = el; -} -link_tb :: (et : *UI_Elem, eb : *UI_Elem) { - et.bottom = eb; - eb.top = et; -} -link_oi :: (eo : *UI_Elem, ei : *UI_Elem) { - eo.inner = ei; - ei.outer = eo; -} - -link_grid :: (size : ivec2, elements : ..*UI_Elem) { - assert(size.x * size.y == elements.count); - for y : 0..size.y-1 { - for x : 0..size.x-2 { - i := x + size.x * y; - link_lr(elements[i], elements[i + 1]); - } - } - for y : 0..size.y-2 { - for x : 0..size.x-1 { - i := x + size.x * y; - link_tb(elements[i], elements[i + size.x]); - } - } -} -link_grid :: (size : ivec2, elements : []UI_Elem) { - assert(size.x * size.y == elements.count); - for y : 0..size.y-1 { - for x : 0..size.x-2 { - i := x + size.x * y; - link_lr(*elements[i], *elements[i + 1]); - } - } - for y : 0..size.y-2 { - for x : 0..size.x-1 { - i := x + size.x * y; - link_tb(*elements[i], *elements[i + size.x]); - } - } -} -link_row :: (elements : ..*UI_Elem) { - for i : 0..elements.count-2 { - link_lr(elements[i], elements[i + 1]); - } -} -link_column :: (elements : ..*UI_Elem) { - for i : 0..elements.count-2 { - link_tb(elements[i], elements[i + 1]); - } -} -link_to_outer :: (eo : *UI_Elem, ei : ..*UI_Elem) { - if ei.count > 0 { - for ei { - it.outer = eo; - } - eo.inner = ei[0]; - } - -} -link_to_bottom :: (eb : *UI_Elem, et : ..*UI_Elem) { - if et.count > 0 { - for et { - it.bottom = eb; - } - eb.top = et[0]; - } -} -link_to_top :: (et : *UI_Elem, eb : ..*UI_Elem) { - if eb.count > 0 { - for eb { - it.top = et; - } - et.bottom = eb[0]; - } -} -link_to_right :: (er : *UI_Elem, el : ..*UI_Elem) { - if el.count > 0 { - for el { - it.right = er; - } - er.left = el[0]; - } -} -link_to_left :: (el : *UI_Elem, er : ..*UI_Elem) { - if er.count > 0 { - for er { - it.left = el; - } - el.right = er[0]; - } -}
\ No newline at end of file diff --git a/kscurses/ui/master.jai b/kscurses/ui/master.jai deleted file mode 100644 index 9cb0702..0000000 --- a/kscurses/ui/master.jai +++ /dev/null @@ -1,105 +0,0 @@ -UI_Master :: struct { - style : UI_Style; - canvas : Canvas; - root : *UI_Elem; - should_exit := false; - - blink_stage := 0; - - before_draw : struct { - proc := (data : *void) { }; - data : *void; - }; - extra_handle : struct { - proc := (e : Event, data : *void) { }; - data : *void; - }; -} -__ui_master : UI_Master; - - -set_main_scene :: (scene : UI_Scene) { - __ui_master.root = scene.root; - set_active_recursive(scene.entry); -} -run_singlethread_ui :: () { - use_default_winch_handler(); - using __ui_master; - while 1 { - before_draw.proc(before_draw.data); - if should_exit break; - draw(*__ui_master); - reset_temporary_storage(); - handle_key(*__ui_master, ks_getch(block = false)); - if should_exit break; - } - deinit(*__ui_master); -} -run_multithread_ui :: () { - use_events(tick_duration_ms = 530); - __event_handler = .{ - proc = (e : Event, __data : *void) { - using __ui_master; - if e.type == { - case .KEY; - handle_key(*__ui_master, e.key); - case .TICK; - #if ENABLE_UI_BLINKING __ui_master.blink_stage = xx !__ui_master.blink_stage; - } - extra_handle.proc(e, extra_handle.data); - }, - data = null - }; defer __event_handler = .{}; - - using __ui_master; - - while 1 { - before_draw.proc(before_draw.data); - if should_exit break; - processed := wait_and_process_events(); - if should_exit break; - if processed { - draw(*__ui_master); - reset_temporary_storage(); - } - } - deinit(*__ui_master); -} - -#scope_file -draw :: (using ui_master : *UI_Master) { - new_zone := Ibox2.{size = terminal_state.size}; - builder : String_Builder; - - if new_zone != canvas.zone { - resize_clear(*canvas, new_zone); - } - ok := c_draw(*canvas, root, canvas.zone, *style); - if ok { - ks_draw_canvas(*canvas); - } else { - b_mode_set(*builder, style.text.default); - b_clear_screen(*builder); - b_print(*builder, .{0, 0}, style.text.debug, "screen to small: %x%", terminal_state.size.x, terminal_state.size.y); - } - b_cursor_set_visibility(*builder, terminal_state.cursor != ivec2.{-1, -1}); - if terminal_state.cursor != ivec2.{-1, -1} then b_move_cursor(*builder, terminal_state.cursor); - - ks_write(builder_to_string(*builder, allocator = temp)); -} -handle_key :: (using ui_master : *UI_Master, key : Key) { - handled := handle_key(root, key); - if handled return; - - if key == { - case .ESCAPE; { - should_exit = true; - unset_active_recursive(__last_set); - } - case; if key != .READ_ERROR ui_bell(); - } -} -deinit :: (using ui_master : *UI_Master) { - deinit(*canvas); - __ui_master = .{}; -}
\ No newline at end of file diff --git a/kscurses/ui/parent.jai b/kscurses/ui/parent.jai deleted file mode 100644 index af459de..0000000 --- a/kscurses/ui/parent.jai +++ /dev/null @@ -1,33 +0,0 @@ -UI_Parent :: struct { - #as using base : UI_Elem; - active_element : *UI_Elem; -} - -__last_set : *UI_Elem; - -set_active_recursive :: (ui_elem : *UI_Elem) { - assert(!__last_set); __last_set = ui_elem; - assert(ui_elem.cursor_state == .OUTSIDE); ui_elem.cursor_state = .ON; - - current := ui_elem; - while 1 { - parent := current.parent; - if !parent break; - assert(!parent.active_element); - parent.active_element = current; - current = xx parent; - } -} -unset_active_recursive :: (ui_elem : *UI_Elem) { - assert(__last_set == ui_elem); __last_set = null; - assert(ui_elem.cursor_state == .ON); ui_elem.cursor_state = .OUTSIDE; - - current := ui_elem; - while 1 { - parent := current.parent; - if !parent break; - assert(parent.active_element == current); - parent.active_element = null; - current = xx parent; - } -}
\ No newline at end of file diff --git a/kscurses/ui/popup_manager.jai b/kscurses/ui/popup_manager.jai deleted file mode 100644 index 704ad49..0000000 --- a/kscurses/ui/popup_manager.jai +++ /dev/null @@ -1,65 +0,0 @@ -MAX_POPUP_LEVES :: 10; - -UI_Popup_Manager :: struct { - #as using base_parent : UI_Parent = .{type = .POPUP_MANAGER, box_type = .NONE}; - - layers : [MAX_POPUP_LEVES]UI_Popup; - - layers_count := 0; -} - -set_background :: (using ui_popup_manager : *UI_Popup_Manager, scene : UI_Scene) { - assert(layers_count == 0); - layers[0] = .{root = scene.root, entry = scene.entry}; - scene.root.parent = xx ui_popup_manager; - layers_count = 1; -} - -handle_key_popup_manager :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using ui_popup_manager := cast(*UI_Popup_Manager) ui_elem; - assert(layers_count > 0, "0 layers in popup manager"); - if !handle_key(active_element, key) { - if key == .ESCAPE && layers_count > 1 { - pop(ui_popup_manager); - return true; - } else { - return false; - } - } else { - return true; - } -} - -c_draw_popup_manager :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using ui_popup_manager := cast(*UI_Popup_Manager) ui_elem; - assert(layers_count > 0, "0 layers in popup manager"); - for i : 0..layers_count-1 { - popup_zone := zone; - ok : bool; - if layers[i].size != .{-1, -1} then { - popup_zone, ok = fit_in_center(zone, layers[i].size); - if !ok return false; - } - if !c_draw(canvas, layers[i].root, popup_zone, style) return false; - } - return true; -} - -pop :: (using ui_popup_manager : *UI_Popup_Manager) { - assert(layers_count > 1, "can't pop background"); - layers_count -= 1; - unset_active_recursive(__last_set); - layers[layers_count].root.parent = null; - set_active_recursive(layers[layers_count - 1].entry); - -} -push :: (using ui_popup_manager : *UI_Popup_Manager, scene : UI_Popup) { - assert(layers_count < MAX_POPUP_LEVES, "too much popup layers"); - unset_active_recursive(__last_set); - - layers[layers_count] = scene; - scene.root.parent = xx ui_popup_manager; - set_active_recursive(layers[layers_count].entry); - - layers_count += 1; -}
\ No newline at end of file diff --git a/kscurses/ui/progress_bar.jai b/kscurses/ui/progress_bar.jai deleted file mode 100644 index 23d7dc9..0000000 --- a/kscurses/ui/progress_bar.jai +++ /dev/null @@ -1,37 +0,0 @@ -UI_Progress_Bar :: struct { - #as using base : UI_Elem = .{type = .PROGRESS_BAR}; - - value : float; - value_ptr : *float; - - draw_proc := (percent : float, pix_coord : float) -> Vector3 { return ifx pix_coord < percent then Vector3.{0, 1, 0} else .{0, 0, 0}; } - show_percent := true; -} - -set_value :: (progress_bar : *UI_Progress_Bar, value : float) { - progress_bar.value = value; - progress_bar.value_ptr = null; -} -set_value_ptr :: (progress_bar : *UI_Progress_Bar, value_ptr : *float) { - progress_bar.value_ptr = value_ptr; -} - -c_draw_progress_bar :: (canvas : *Canvas, ui_elem : *UI_Elem, _zone : Ibox2, style : *UI_Style) -> bool { - using progress_bar := cast(*UI_Progress_Bar) ui_elem; - value_current := ifx value_ptr then <<value_ptr else value; - zone := _zone; - if zone.width < 6 return false; - if show_percent { - percent_str := tprint("%1%%", formatFloat(value_current * 100, width = 4, trailing_width = 1, zero_removal = .NO)); - c_draw_line_ascii(canvas, percent_str, zone, .{zone.width - 5, zone.height / 2}, style.text.default); - zone.width -= 5; - } - for x : 0..zone.width-1 { - pix_coord := (x + .5) / zone.width; - char := find_best_char(draw_proc(value_current, pix_coord), true); - for y : 0..zone.height-1 { - c_putchar(canvas, char, zone.corner + ivec2.{x, y}); - } - } - return true; -} diff --git a/kscurses/ui/scalable_group.jai b/kscurses/ui/scalable_group.jai deleted file mode 100644 index 6c12bcc..0000000 --- a/kscurses/ui/scalable_group.jai +++ /dev/null @@ -1,88 +0,0 @@ -UI_Scalable_Group :: struct { - #as using base_parent : UI_Parent = .{type = .SCALABLE_GROUP}; - - Scale_Params :: struct { - // using metrics : struct { - x1, y1, x2, y2 : s32; - #place x1; v1 : ivec2; - #place x2; v2 : ivec2; - // }; - scale_mode : enum u8 { - ANCHOR_TL :: 0; // v1 - size, v2 - offset from corner (both positive) - ANCHOR_TR :: 1; - ANCHOR_BL :: 2; - ANCHOR_BR :: 3; - - STRETCH_T :: 4; // x1/2 - left/right offset, y1 - top offset, y2 - height - STRETCH_B :: 5; // x1/2 - left/right offset, y1 - bottom offset, y2 - height - STRETCH_L :: 6; // y1/2 - top/bottom offset, x1 - left offset, x2 - width - STRETCH_R :: 7; // y1/2 - top/bottom offset, x1 - right offset, x2 - width - - STRETCH_C :: 8; // v1 - top-left offset, v2 - bottom-right offset - CENTERIZE :: 9; // v1 - size, v2 - offset from center(signed) - - FIT_EXACT :: 10; //TODO - FIT_ROUGH :: 11; - } = .ANCHOR_TL; - } - - Element :: struct { - ptr : *UI_Elem; - scale_params : Scale_Params; - } - - elements : []Element; -} - -get_zone :: (using zone : Ibox2, using scale_params : UI_Scalable_Group.Scale_Params) -> Ibox2 { - if scale_mode == { - case .ANCHOR_TL; return .{corner = corner + v2, size = v1}; - case .ANCHOR_TR; return .{corner = .{left + width - x2 - x1, top + y2}, size = v1}; - case .ANCHOR_BL; return .{corner = .{left + x2, top + height - y2 - y1}, size = v1}; - case .ANCHOR_BR; return .{corner = .{left + width - x2 - x1, top + height - y2 - y1}, size = v1}; - - case .STRETCH_T; return .{corner = .{left + x1, top + y1}, size = .{width - x1 - x2, y2}}; - case .STRETCH_B; return .{corner = .{left + x1, top + height - y1 - y2}, size = .{width - x1 - x2, y2}}; - case .STRETCH_L; return .{corner = .{left + x1, top + y1}, size = .{x2, height - y1 - y2}}; - case .STRETCH_R; return .{corner = .{left + width - x1 - x2, top + y1}, size = .{x2, height - y1 - y2}}; - - case .STRETCH_C; return .{corner = corner + v1, size = size - v1 - v2}; - case .CENTERIZE; return .{corner = corner + (size - v1) / 2 + v2 , size = v1}; - } - assert(false); - return .{}; -} - -set_sub_elements :: (group : *UI_Scalable_Group, elements : ..UI_Scalable_Group.Element) { - group.elements = elements; - for e : elements { - e.ptr.parent = group; - } -} -c_draw_scalable_group :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Scalable_Group) ui_elem; - for e : elements { - e_zone := get_zone(zone, e.scale_params); - if !inside(e_zone, zone) return false; - if !c_draw(canvas, e.ptr, e_zone, style) return false; - } - return true; -} -handle_key_scalable_group :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using cast(*UI_Scalable_Group) ui_elem; - assert(cursor_state == .ON || cursor_state == .OUTSIDE); - - handled := false; - if cursor_state == .OUTSIDE { - assert(xx active_element); - { - ok := false; - for e : elements if e.ptr == active_element ok = true; - assert(ok); - } - handled = handle_key(active_element, key); - } else { - assert(xx !active_element); - } - return handled; -}
\ No newline at end of file diff --git a/kscurses/ui/scene_manager.jai b/kscurses/ui/scene_manager.jai deleted file mode 100644 index 1caff8b..0000000 --- a/kscurses/ui/scene_manager.jai +++ /dev/null @@ -1,48 +0,0 @@ -UI_Scene :: struct { - root : *UI_Elem; - entry : *UI_Elem; -} -UI_Popup :: struct { - root : *UI_Elem; - entry : *UI_Elem; - size : ivec2 = .{-1, -1}; -} - -UI_Scene_Manager :: struct { - #as using base_parent : UI_Parent = .{type = .SCENE_MANAGER, box_type = .NONE}; - scenes : []UI_Scene; -} - -set_sub_elements :: (ui_scene_manager : *UI_Scene_Manager, scenes : ..UI_Scene) { - ui_scene_manager.scenes = scenes; - for ui_scene_manager.scenes it.root.parent = ui_scene_manager; -} - -handle_key_scene_manager :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using cast(*UI_Scene_Manager) ui_elem; - assert(cursor_state == .ON || cursor_state == .OUTSIDE); - - handled := false; - if cursor_state == .OUTSIDE { - assert(xx active_element); - { - ok := false; - for s : scenes if s.root == active_element ok = true; - assert(ok); - } - handled = handle_key(active_element, key); - } else { - assert(xx !active_element); - } - return handled; -} - -c_draw_scene_manager :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Scene_Manager) ui_elem; - return c_draw(canvas, active_element, zone, style); -} - -switch_scene :: (using ui_scene_manager : *UI_Scene_Manager, id : int) { - unset_active_recursive(__last_set); - set_active_recursive(scenes[id].entry); -} diff --git a/kscurses/ui/select_list.jai b/kscurses/ui/select_list.jai deleted file mode 100644 index 8c338c6..0000000 --- a/kscurses/ui/select_list.jai +++ /dev/null @@ -1,79 +0,0 @@ -UI_Select_List :: struct { - #as using base : UI_Elem = .{type = .SELECT_LIST}; - only_one := true; - options : []string; - selected : []bool; - - selected_id := -1; - cursor, offset := 0, 0; - - prefix_default := "[ ]"; - prefix_selected := "[+]"; -} -handle_key_select_list :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - using cast(*UI_Select_List) ui_elem; - assert(cursor_state != .OUTSIDE); - if cursor_state == .ON { - if key == .ENTER { - cursor_state = .IN; - return true; - } - } else { - if key == { - case .DOWN; - if cursor < options.count - 1 then cursor += 1; - case .UP; - if cursor > 0 then cursor -= 1; - case .ESCAPE; - cursor_state = .ON; - case .ENTER; - if only_one { - if cursor == selected_id { - selected_id = -1; - } else { - selected_id = cursor; - } - } else { - selected[cursor] ^= true; - } - case; - return false; - } - return true; - } - return false; -} -init :: (select_list : *UI_Select_List, only_one := true) { - select_list.only_one = only_one; - if !only_one select_list.selected = NewArray(select_list.options.count, bool); -} -deinit :: (using select_list : *UI_Select_List) { - array_free(selected); -} -c_draw_select_list :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Select_List) ui_elem; - rows := min(cast(int) zone.height, options.count - offset); - - fix_offset :: () #expand { - if cursor - offset < 0 { - offset = cursor; - } else if cursor - offset >= zone.height { - offset = cursor - zone.height + 1; - } - } - fix_offset(); - - for y : 0..rows-1 { - i := y + offset; - is_selected := ifx only_one then i == selected_id else selected[i]; - prefix := ifx is_selected then prefix_selected else prefix_default; - mode := ifx i == cursor && cursor_state == .IN - ifx is_selected style.text.cursor_and_selection else style.text.cursor - else - ifx is_selected style.text.selection else style.text.default; - - c_draw_line_ascii(canvas, prefix, zone, .{0, xx y}, mode); - c_draw_line_ascii(canvas, options[i], zone, .{xx prefix.count, xx y}, mode); - } - return true; -}
\ No newline at end of file diff --git a/kscurses/ui/style.jai b/kscurses/ui/style.jai deleted file mode 100644 index 4715860..0000000 --- a/kscurses/ui/style.jai +++ /dev/null @@ -1,118 +0,0 @@ -mode_black_and_white :: #run make_graphics_mode(foreground = .BRIGHT_WHITE, background = .BLACK); - -Box_Style :: struct { - c, tb, lr, tl, tr, bl, br, tbl, tbr, tlr, blr, tblr : u32; - mode_border, mode_space, mode_no_border := mode_black_and_white; -} - -box_style_active :: Box_Style.{ - c = #run utf8(" "), - tb = #run utf8("║"), - lr = #run utf8("═"), - tl = #run utf8("╝"), - tr = #run utf8("╚"), - bl = #run utf8("╗"), - br = #run utf8("╔"), - tbl = #run utf8("╣"), - tbr = #run utf8("╠"), - tlr = #run utf8("╩"), - blr = #run utf8("╦"), - tblr = #run utf8("╬"), - mode_no_border = #run make_graphics_mode(foreground = .BRIGHT_WHITE, background = .BRIGHT_BLACK) -}; -box_style_passive :: Box_Style.{ - c = #run utf8(" "), - tb = #run utf8("│"), - lr = #run utf8("─"), - tl = #run utf8("┘"), - tr = #run utf8("└"), - bl = #run utf8("┐"), - br = #run utf8("┌"), - tbl = #run utf8("┤"), - tbr = #run utf8("├"), - tlr = #run utf8("┴"), - blr = #run utf8("┬"), - tblr = #run utf8("┼") -}; - -UI_Style :: struct { - box : struct { - default := box_style_passive; - cursor := box_style_active; - } - - mode_main := mode_black_and_white; - - text : struct { - default := mode_black_and_white; - cursor := #run make_graphics_mode(background = .BRIGHT_BLACK); - selection := #run make_graphics_mode(background = .YELLOW); - cursor_and_selection := #run make_graphics_mode(background = .BRIGHT_YELLOW); - - debug := #run make_graphics_mode(foreground = .BLACK, background = .BRIGHT_GREEN); - } -} - -c_box :: (canvas : *Canvas, zone : Ibox2, using box_style : Box_Style, border := true) -> bool { - if !inside(ifx border then ivec2.{2, 2} else ivec2.{0, 0}, zone.size) return false; - assert(inside(zone, canvas.zone)); - charset : [9]u32; - if border { - charset[0], charset[1], charset[2], charset[3], charset[4], charset[5], charset[6], charset[7], charset[8] = br, lr, bl, tb, c, tb, tr, lr, tl; - } else { - charset[0], charset[1], charset[2], charset[3], charset[4], charset[5], charset[6], charset[7], charset[8] = c, c, c, c, c, c, c, c, c; - } - - for y : 0..zone.height-1 { - yi := ifx y == 0 then 0 else ifx y == zone.height - 1 then 2 else 1; - for x : 0..zone.width-1 { - xi := ifx x == 0 then 0 else ifx x == zone.width - 1 then 2 else 1; - i := yi * 3 + xi; - c_putchar(canvas, .{code = charset[i], mode = mode_border}, zone.corner + ivec2.{xx x, xx y}); - } - } - return true; -} - -b_box :: (builder : *String_Builder, zone : Ibox2, using charset := box_style_passive, mode := Graphics_Mode.{}, clear_center := true, border := true) { - //assert(inside(zone, terminal_state.size)); - - charset : [9]u32; - if border { - charset = .[br, lr, bl, tb, c, tb, tr, lr, tl]; - } else { - charset = .[c, c, c, c, c, c, c, c, c]; - } - - b_move_cursor(builder, zone.corner); - b_mode_set(builder, mode); - - for y : 0..zone.height-1 { - yi := ifx y == 0 then 0 else ifx y == zone.height - 1 then 2 else 1; - b_move_cursor(builder, .{zone.corner.x, zone.corner.y + y}); - - if !clear_center && yi == 1 { - b_putchar(builder, charset[3]); - b_move_cursor(builder, .{zone.corner.x + zone.width - 1, zone.corner.y + y}); - b_putchar(builder, charset[5]); - } else { - for x : 0..zone.width-1 { - xi := ifx x == 0 then 0 else ifx x == zone.width - 1 then 2 else 1; - i := yi * 3 + xi; - b_putchar(builder, charset[i]); - } - } - - } -} -t_box :: (zone : Ibox2, charset := box_style_passive, clear_center := false) -> string { - builder := String_Builder.{allocator=temp}; - b_box(*builder, zone, charset, make_graphics_mode(), clear_center); - return builder_to_string(*builder, temp); -} -ks_box :: (zone : Ibox2, charset := box_style_passive, clear_center := false) { - ks_write(t_box(zone, charset, clear_center)); -} - - - diff --git a/kscurses/ui/table.jai b/kscurses/ui/table.jai deleted file mode 100644 index dadc1c3..0000000 --- a/kscurses/ui/table.jai +++ /dev/null @@ -1,87 +0,0 @@ -UI_Table :: struct { - #as using base : UI_Elem = .{type = .TABLE}; - - // auto_scale := false; - // metrics : []int; - columns := 0; - rows := 0; - - // description : []string; - content : [..]string; - - cursor, offset := 0; - show_cursor := false; -} - -handle_key_table :: (ui_elem : *UI_Elem, key : Key) -> handled:bool { - return false; -} - -c_draw_table_content :: (canvas : *Canvas, using ui_table : *UI_Table, zone : Ibox2, style : *UI_Style, rows_visible : int) -> bool { - for y : 0..zone.height-1 { - is_selected := y == cursor && show_cursor; - mode := ifx is_selected then style.text.selection else style.text.default; - separator_char := Char.{code = style.box.default.tb, mode = mode}; - - if zone.width < columns { - for x : 0..zone.width { - c_putchar(canvas, separator_char, zone.corner + ivec2.{xx x, xx y}); - } - } else { - i := y + offset; - for x : 0..columns-1 { - l := (zone.width + 1) * x / columns; - r := (zone.width + 1) * (x + 1) / columns - 1; - if y < rows_visible { - field_content := content[i * columns + x]; - field_content.count = min(field_content.count, r - l); - c_draw_line_ascii(canvas, field_content, zone, .{xx l, xx y}, mode); - } - if x != columns-1 c_putchar(canvas, separator_char, zone.corner + ivec2.{xx r, xx y}); - } - } - } - return true; -} - -c_draw_table :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using ui_table := cast(*UI_Table) ui_elem; - assert(rows * columns == content.count); - - rows_visible := min(cast(int) zone.height, rows - offset); - - fix_offset :: () #expand { - if cursor - offset < 0 { - offset = cursor; - } else if cursor - offset >= zone.height { - offset = cursor - zone.height + 1; - } - } - fix_offset(); - - ok := c_draw_table_content(canvas, ui_table, zone, style, rows_visible); - return ok; -} -init :: (table : *UI_Table, description : []string) { - table.columns = description.count; - table.description = description; -} -init :: (table : *UI_Table, columns : int) { - table.columns = columns; -} - -add_line :: (using table : *UI_Table, line : ..string) { - assert(line.count == columns); - array_add(*content, ..line); - rows += 1; -} -deinit :: (using table : *UI_Table) { - array_free(content); -} - -// TODO -// variadic columns count, different content types -// empty separator -// automatic scale, as option -// description -// align content left/right/center
\ No newline at end of file diff --git a/kscurses/ui/text_buf.jai b/kscurses/ui/text_buf.jai deleted file mode 100644 index 689bb98..0000000 --- a/kscurses/ui/text_buf.jai +++ /dev/null @@ -1,15 +0,0 @@ -UI_Text_Buf :: struct { - #as using base : UI_Elem = .{type = .TEXT_BUF}; - lines : []string; - lines_dynamic : *[]string; -} -c_draw_textbuf :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { - using cast(*UI_Text_Buf) ui_elem; - - lines_to_draw := ifx lines_dynamic then <<lines_dynamic else lines; - for l, y : lines_to_draw { - if y >= zone.height break; - c_draw_line_ascii(canvas, l, zone, .{0, xx y}, style.text.default); - } - return true; -} diff --git a/kscurses/ui/tilemap.jai b/kscurses/ui/tilemap.jai deleted file mode 100644 index 73f96e5..0000000 --- a/kscurses/ui/tilemap.jai +++ /dev/null @@ -1,20 +0,0 @@ -UI_Tilemap :: struct { - #as using base : UI_Elem = .{type = .TILEMAP}; - - map_size : ivec2; - map : []u64; - tileset : *Tileset; - - background : Char; // if not set, then box's filler instead -} -Tileset :: struct { - tile_size : ivec2; - tiles_count : int; - data : []Char; - // code = 0 -> skip entire character - // fcol/bcol = .DEFAULT -> skip foreground/background -} -c_draw_tile :: (canvas : *Canvas, tileset : *Tileset, offset : ivec2, id : u64, cutoff : Ibox2) { - -} - |
