Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158//! A View is effectively an "oversized" Window that can be written to and rendered in pieces.
const std = @import("std");const mem = std.mem;
const View = @This();
const gw = @import("../gwidth.zig");
const Screen = @import("../Screen.zig");const Window = @import("../Window.zig");const unicode = @import("../unicode.zig");const Cell = @import("../Cell.zig");
/// View Allocatoralloc: mem.Allocator,
/// Underlying Screenscreen: Screen,
/// View Initialization Configpub const Config = struct { width: u16, height: u16,};
/// Initialize a new Viewpub fn init(alloc: mem.Allocator, config: Config) mem.Allocator.Error!View { return .{ .alloc = alloc, .screen = try Screen.init(alloc, .{ .cols = config.width, .rows = config.height, .x_pixel = 0, .y_pixel = 0, }), };}
pub fn window(self: *View) Window { return .{ .x_off = 0, .y_off = 0, .parent_x_off = 0, .parent_y_off = 0, .width = self.screen.width, .height = self.screen.height, .screen = &self.screen, };}
/// Deinitialize this Viewpub fn deinit(self: *View) void { self.screen.deinit(self.alloc);}
pub const DrawOptions = struct { x_off: u16 = 0, y_off: u16 = 0,};
pub fn draw(self: *View, win: Window, opts: DrawOptions) void { if (opts.x_off >= self.screen.width) return; if (opts.y_off >= self.screen.height) return;
const width = @min(win.width, self.screen.width - opts.x_off); const height = @min(win.height, self.screen.height - opts.y_off);
for (0..height) |_row| { const row: i17 = @intCast(_row); const src_start: usize = @intCast(opts.x_off + ((row + opts.y_off) * self.screen.width)); const src_end: usize = @intCast(src_start + width); const dst_start: usize = @intCast(win.x_off + ((row + win.y_off) * win.screen.width)); const dst_end: usize = @intCast(dst_start + width); @memcpy(win.screen.buf[dst_start..dst_end], self.screen.buf[src_start..src_end]); }}
/// Render Config for `toWin()`pub const RenderConfig = struct { x: u16 = 0, y: u16 = 0, width: Extent = .fit, height: Extent = .fit,
pub const Extent = union(enum) { fit, max: u16, };};
/// Render a portion of this View to the provided Window (`win`)./// This will return the bounded X (col), Y (row) coordinates based on the rendering.pub fn toWin(self: *View, win: Window, config: RenderConfig) !struct { u16, u16 } { var x = @min(self.screen.width - 1, config.x); var y = @min(self.screen.height - 1, config.y); const width = width: { var width = switch (config.width) { .fit => win.width, .max => |w| @min(win.width, w), }; width = @min(width, self.screen.width); break :width @min(width, self.screen.width -| 1 -| x +| win.width); }; const height = height: { var height = switch (config.height) { .fit => win.height, .max => |h| @min(win.height, h), }; height = @min(height, self.screen.height); break :height @min(height, self.screen.height -| 1 -| y +| win.height); }; x = @min(x, self.screen.width -| width); y = @min(y, self.screen.height -| height); const child = win.child(.{ .width = width, .height = height, }); self.draw(child, .{ .x_off = x, .y_off = y }); return .{ x, y };}
/// Writes a cell to the location in the Viewpub fn writeCell(self: *View, col: u16, row: u16, cell: Cell) void { self.screen.writeCell(col, row, cell);}
/// Reads a cell at the location in the Viewpub fn readCell(self: *const View, col: u16, row: u16) ?Cell { return self.screen.readCell(col, row);}
/// Fills the View with the default cellpub fn clear(self: View) void { self.fill(.{ .default = true });}
/// Returns the width of the grapheme. This depends on the terminal capabilitiespub fn gwidth(self: View, str: []const u8) u16 { return gw.gwidth(str, self.screen.width_method);}
/// Fills the View with the provided cellpub fn fill(self: View, cell: Cell) void { @memset(self.screen.buf, cell);}
/// Prints segments to the View. Returns true if the text overflowed with the/// given wrap strategy and size.pub fn print(self: *View, segments: []const Cell.Segment, opts: Window.PrintOptions) Window.PrintResult { return self.window().print(segments, opts);}
/// Print a single segment. This is just a shortcut for print(&.{segment}, opts)pub fn printSegment(self: *View, segment: Cell.Segment, opts: Window.PrintOptions) Window.PrintResult { return self.print(&.{segment}, opts);}