term.ui: render to the alternate buffer (#6832)
parent
b96a0246b5
commit
1ead130eed
|
@ -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 {
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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 {}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue