diff --git a/examples/term.ui/cursor_chaser.v b/examples/term.ui/cursor_chaser.v index 386226e2c3..72b51f6166 100644 --- a/examples/term.ui/cursor_chaser.v +++ b/examples/term.ui/cursor_chaser.v @@ -1,10 +1,5 @@ import term.ui as tui -struct Point { - x int - y int -} - const ( colors = [ tui.Color{33, 150, 243} @@ -16,6 +11,11 @@ const ( ] ) +struct Point { + x int + y int +} + struct App { mut: tui &tui.Context = 0 @@ -33,11 +33,11 @@ fn frame(x voidptr) { if app.points.len > 0 { app.tui.set_bg_color(app.color) mut last := app.points[0] - for segment in app.points { - // if the cursor moveds quickly enough, different events are not + for point in app.points { + // if the cursor moves quickly enough, different events are not // necessarily touching, so we need to draw a line between them - app.tui.draw_line(last.x, last.y, segment.x, segment.y) - last = segment + app.tui.draw_line(last.x, last.y, point.x, point.y) + last = point } app.tui.reset() @@ -62,8 +62,6 @@ fn event(e &tui.Event, x voidptr) { .key_down { match e.code { .escape { - app.tui.set_cursor_position(0, 0) - app.tui.flush() exit(0) } .space, .enter { diff --git a/examples/term.ui/event_viewer.v b/examples/term.ui/event_viewer.v index 73abffe4b6..d78bf372c5 100644 --- a/examples/term.ui/event_viewer.v +++ b/examples/term.ui/event_viewer.v @@ -32,6 +32,7 @@ app.tui = tui.init( hide_cursor: true capture_events: true frame_rate: 60 + use_alternate_buffer: false ) println('V term.ui event viewer (press `esc` to exit)\n\n') diff --git a/examples/term.ui/term_drawing.v b/examples/term.ui/term_drawing.v index 42eb7ad570..cec69ab59a 100644 --- a/examples/term.ui/term_drawing.v +++ b/examples/term.ui/term_drawing.v @@ -87,19 +87,20 @@ const ( struct App { mut: - tui &tui.Context = 0 - header_text []string - mouse_pos Point - msg string - msg_hide_tick int - primary_color tui.Color = colors[1][6] - secondary_color tui.Color = colors[1][9] - bg_color tui.Color = tui.Color{0, 0, 0} - color_index int - drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}} - size int = 1 - should_redraw bool = true - is_dragging bool + tui &tui.Context = 0 + header_text []string + mouse_pos Point + msg string + msg_hide_tick int + primary_color tui.Color = colors[1][6] + secondary_color tui.Color = colors[1][9] + primary_color_idx int = 25 + secondary_color_idx int = 28 + bg_color tui.Color = tui.Color{0, 0, 0} + drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}} + size int = 1 + should_redraw bool = true + is_dragging bool } struct Point { @@ -169,10 +170,17 @@ fn event(event &tui.Event, x voidptr) { x: event.x y: event.y } - if event.direction == .down { - app.inc_size() + d := event.direction == .down + if event.modifiers & tui.ctrl != 0 { + p := event.modifiers & tui.shift == 0 + c := if d { + if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 } + } else { + if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 } + } + app.select_color(p, c) } else { - app.dec_size() + if d { app.inc_size() } else { app.dec_size() } } } .key_down { @@ -217,28 +225,22 @@ fn event(event &tui.Event, x voidptr) { app.mouse_pos.x += 2 } .t { - mut c := if event.modifiers & tui.shift != 0 { app.color_index - 19 } else { app.color_index + - 19 } - if c < 0 { - c = 0 + p := event.modifiers & tui.alt == 0 + c := if event.modifiers & tui.shift != 0 { + if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 } + } else { + if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 } } - cx := c % 19 - cy := (c / 19) % 3 - color := colors[cy][cx] - app.primary_color = color - app.color_index = c % (19 * 3) + app.select_color(p, c) } .r { - mut c := if event.modifiers & tui.shift != 0 { app.color_index - 1 } else { app.color_index + - 1 } - if c < 0 { - c = 0 + p := event.modifiers & tui.alt == 0 + c := if event.modifiers & tui.shift != 0 { + if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 } + } else { + if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 } } - cx := c % 19 - cy := (c / 19) % 3 - color := colors[cy][cx] - app.primary_color = color - app.color_index = c % (19 * 3) + app.select_color(p, c) } .plus { app.inc_size() @@ -272,6 +274,22 @@ fn (mut app App) render(paint_only bool) { app.tui.flush() } +fn (mut app App) select_color(primary bool, idx int) { + c := (idx + 57) % 57 + cx := c % 19 + cy := (c / 19) % 3 + color := colors[cy][cx] + if primary { + app.primary_color_idx = c % (19 * 3) + app.primary_color = color + } else { + app.secondary_color_idx = c % (19 * 3) + app.secondary_color = color + } + c_str := if primary { 'primary' } else { 'secondary' } + app.show_msg('set $c_str color idx: $idx', 1) +} + fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) { // Term coords start at 1, and adjust for the header x, y := x_ - 1, y_ - 4 @@ -285,6 +303,9 @@ fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) { } fn (mut app App) paint(event &tui.Event) { + if event.y < 4 || app.tui.window_height - event.y < 4 { + return + } x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2 color := match event.button { .left { app.primary_color } @@ -374,10 +395,6 @@ fn (mut app App) draw_header() { app.tui.horizontal_separator(3) } -fn (mut app App) current_color(x int, y int) bool { - return app.color_index == x + (y * 19) -} - fn (mut app App) draw_footer() { _, wh := app.tui.window_width, app.tui.window_height app.tui.horizontal_separator(wh - 4) @@ -386,8 +403,12 @@ fn (mut app App) draw_footer() { x := j * 3 + 19 y := wh - 3 + i app.tui.set_bg_color(color) - if app.current_color(j, i) { - app.tui.set_color(tui.Color{0, 0, 0}) + if app.primary_color_idx == j + (i * 19) { + app.tui.set_color(r: 0, g: 0, b: 0) + app.tui.draw_text(x, y, '><') + app.tui.reset_color() + } else if app.secondary_color_idx == j + (i * 19) { + app.tui.set_color(r: 255, g: 255, b: 255) app.tui.draw_text(x, y, '><') app.tui.reset_color() } else { @@ -397,9 +418,6 @@ fn (mut app App) draw_footer() { } app.tui.reset_bg_color() app.tui.draw_text(3, wh - 3, select_color) - app.tui.set_bg_color(app.primary_color) - app.tui.draw_text(3 + select_color.len, wh - 3, ' ') - app.tui.reset_bg_color() app.tui.bold() app.tui.draw_text(3, wh - 1, '$select_size $app.size') app.tui.reset() @@ -414,7 +432,7 @@ fn (mut app App) draw_footer() { [inline] fn (mut app App) inc_size() { - if app.size < 20 { + if app.size < 30 { app.size++ } app.show_msg('inc. size: $app.size', 1) @@ -444,13 +462,7 @@ fn (mut app App) footer_click(event &tui.Event) { } idx := footer_y * 19 - 6 + event.x / 3 if idx < 0 || idx > 56 { return } - color := colors[idx / 19][idx % 19] - if event.button == .left { - app.primary_color = color - } else if event.button == .right { - app.secondary_color = color - } - app.show_msg('set $event.button.str().to_lower() color idx: $idx', 1) + app.select_color(event.button == .left, idx) } else {} } diff --git a/examples/term.ui/text_editor.v b/examples/term.ui/text_editor.v index 005788bd9c..a92c23a66b 100644 --- a/examples/term.ui/text_editor.v +++ b/examples/term.ui/text_editor.v @@ -397,7 +397,6 @@ fn (mut a App) init_file() { a.ed = &Buffer{} mut init_y := 0 mut init_x := 0 - eprintln('> a.files: $a.files | a.current_file: $a.current_file') if a.files.len > 0 && a.current_file < a.files.len && a.files[a.current_file].len > 0 { if !os.is_file(a.files[a.current_file]) && a.files[a.current_file].contains(':') { // support the file:line:col: format @@ -454,8 +453,6 @@ fn event(e &tui.Event, x voidptr) { if e.typ == .key_down { match e.code { .escape { - a.tui.set_cursor_position(0, 0) - a.tui.flush() exit(0) } .backspace { diff --git a/vlib/term/ui/input.v b/vlib/term/ui/input.v index 555d68e150..d43b3f3f9e 100644 --- a/vlib/term/ui/input.v +++ b/vlib/term/ui/input.v @@ -167,8 +167,7 @@ mut: termios C.termios read_buf []byte print_buf []byte - // init_called bool - // quit_ordered bool + paused bool pub mut: frame_count u64 window_width int @@ -190,6 +189,7 @@ pub struct Config { window_title string hide_cursor bool capture_events bool + use_alternate_buffer bool = true // All kill signals reset []int = [1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19] } diff --git a/vlib/term/ui/termios_nix.c.v b/vlib/term/ui/termios_nix.c.v index fd675a3efe..fa6043c583 100644 --- a/vlib/term/ui/termios_nix.c.v +++ b/vlib/term/ui/termios_nix.c.v @@ -45,9 +45,10 @@ fn restore_terminal_state() { termios_reset() mut c := ctx_ptr if c != 0 { + c.paused = true c.load_title() } - println('') + os.flush() } fn (mut ctx Context) termios_setup() { @@ -79,9 +80,10 @@ fn (mut ctx Context) termios_setup() { termios.c_cc[C.VMIN] = 0 C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios) print('\x1b[?1003h\x1b[?1006h') - + if ctx.cfg.use_alternate_buffer { + print('\x1b[?1049h') + } ctx.termios = termios - ctx.window_height, ctx.window_width = get_terminal_size() // Reset console on exit @@ -97,6 +99,7 @@ fn (mut ctx Context) termios_setup() { width: c.window_width height: c.window_height } + c.paused = false c.event(event) } }) @@ -123,11 +126,17 @@ fn (mut ctx Context) termios_setup() { c.event(event) } }) + os.flush() } fn termios_reset() { C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup) - print('\x1b[?1003l\x1b[?1015l\x1b[?1006l\x1b[0J\x1b[?25h') + print('\x1b[?1003l\x1b[?1006l\x1b[?25h') + c := ctx_ptr + if c != 0 && c.cfg.use_alternate_buffer { + print('\x1b[?1049l') + } + os.flush() } /////////////////////////////////////////// @@ -147,20 +156,22 @@ fn (mut ctx Context) termios_loop() { if sleep_len > 0 { time.usleep(sleep_len) } - sw.restart() - if ctx.cfg.event_fn != voidptr(0) { - len := C.read(C.STDIN_FILENO, ctx.read_buf.data, ctx.read_buf.cap - ctx.read_buf.len) - if len > 0 { - ctx.resize_arr(len) - ctx.parse_events() + if !ctx.paused { + sw.restart() + if ctx.cfg.event_fn != voidptr(0) { + len := C.read(C.STDIN_FILENO, ctx.read_buf.data, ctx.read_buf.cap - ctx.read_buf.len) + if len > 0 { + ctx.resize_arr(len) + ctx.parse_events() + } } - } - ctx.frame() - sw.pause() - e := sw.elapsed().microseconds() - sleep_len = frame_time - int(e) + ctx.frame() + sw.pause() + e := sw.elapsed().microseconds() + sleep_len = frame_time - int(e) - ctx.frame_count++ + ctx.frame_count++ + } } }