Skip to main content

Screen

Struct Screen 

Source
pub struct Screen { /* private fields */ }
Expand description

The grid of cells, and the styles they use.

The style table only grows as cells are written; a screen kept between frames drops the styles no cell uses any more with compact_styles (a Painter does it for the screen it paints with Painter::compact), so a picture whose colours change every frame does not pile them up.

Implementations§

Source§

impl Screen

Source

pub fn new(width: u16, height: u16) -> Screen

Source

pub fn scrolled(&self) -> &[(Rect, u16)]

The scrolls scroll_up made since the last forget_scrolls: each rectangle and how many rows it moved up.

Source

pub fn forget_scrolls(&mut self)

Forget the scrolls made so far: after a frame is painted.

Source

pub fn area(&self) -> Rect

Source

pub fn cell(&self, x: u16, y: u16) -> &Cell

Source

pub fn get(&self, x: u16, y: u16) -> Option<&Cell>

The cell at x, y, if it is on the screen; its style is style of its id.

use rich::{Segment, Style};
use rich_ext::surface::{Rect, Screen};

let mut screen = Screen::new(4, 1);
let bold = Style::parse("bold").unwrap();
screen.write_lines(Rect::new(0, 0, 4, 1), &[vec![Segment::new("ab", Some(bold.clone()))]]);
let cell = screen.get(1, 0).unwrap();
assert_eq!((cell.text(), screen.style(cell.style)), ("b", Some(&bold)));
assert!(screen.get(4, 0).is_none());
Source

pub fn style(&self, id: StyleId) -> Option<&Style>

Source

pub fn style_count(&self) -> usize

How many styles the screen’s table holds, counting “no style”: what its cells use, and what they used before the last compact_styles.

Source

pub fn intern(&mut self, style: Option<&Style>) -> StyleId

Intern style for use in this screen’s cells.

Source

pub fn styles_piled_up(&self) -> bool

Whether the style table has grown well past what the cells used when it was last compacted: time for compact_styles.

Source

pub fn compact_styles(&mut self) -> StyleRemap

Drop the styles no cell uses, and renumber the rest. The result maps the old ids to the new, for whatever kept an id of this screen’s between frames: a Painter that painted it is moved over with Painter::remap_styles (or compacts it itself with Painter::compact). The cells keep their styles; only the ids change.

use rich::{Color, Style};
use rich_ext::surface::Screen;

let mut screen = Screen::new(2, 1);
for n in 0..=255u8 {
    screen.put_rgb(0, 0, '▀', Some([n, 0, 0]), Some([0, 0, n]));
}
assert_eq!(screen.style_count(), 257);
screen.compact_styles();
// "No style" (the blank cell) and the last colour pair.
assert_eq!(screen.style_count(), 2);
let cell = screen.cell(0, 0);
let last = Style::from_color(Some(Color::from_rgb(255, 0, 0)), Some(Color::from_rgb(0, 0, 255)));
assert_eq!(screen.style(cell.style), Some(&last));
Source

pub fn put_rgb( &mut self, x: u16, y: u16, ch: char, fg: Option<Rgb>, bg: Option<Rgb>, )

Set the cell at x, y to ch with foreground fg and background bg in true colour (either missing), without building a Segment or, unless the pair is new, a Style: the fast way to draw a picture a cell at a time (half blocks, quadrants, Braille). The cell takes the style Style::from_color of the two Color::from_rgbs would give. Off the screen, nothing is written.

ch takes one cell: a wide or zero-width character becomes a space, and a terminal control its visible stand-in (see control_picture). A wide grapheme the cell was half of becomes a space.

use rich::{Color, Style};
use rich_ext::surface::Screen;

let mut screen = Screen::new(2, 1);
screen.put_rgb(1, 0, '▀', Some([255, 0, 0]), Some([0, 0, 255]));
let cell = screen.cell(1, 0);
let style = Style::from_color(
    Some(Color::from_rgb(255, 0, 0)),
    Some(Color::from_rgb(0, 0, 255)),
);
assert_eq!((cell.text(), screen.style(cell.style)), ("▀", Some(&style)));
Source

pub fn put(&mut self, x: u16, y: u16, ch: char, style: StyleId)

Set the cell at x, y to ch in the style style (an id from intern on this screen), as put_rgb does: for many cells in one style, interned once.

use rich::Style;
use rich_ext::surface::Screen;

let mut screen = Screen::new(3, 1);
let bold = screen.intern(Some(&Style::parse("bold").unwrap()));
for x in 0..3 {
    screen.put(x, 0, '#', bold);
}
assert_eq!(screen.plain(), ["###"]);
Source

pub fn clear(&mut self, rect: Rect)

Clear rect to blank cells.

Source

pub fn write_lines(&mut self, rect: Rect, lines: &[Vec<Segment>])

Write rendered lines into rect, replacing what was there: rows and columns the lines do not reach are cleared. Terminal controls in the text become visible symbols; a wide grapheme that would cross the rectangle’s right edge becomes a space.

Source

pub fn write_runs<'t, L: AsRef<[TextRun<'t>]>>( &mut self, rect: Rect, lines: &[L], )

The fast path’s write_lines: rows of TextRuns, each a borrowed text and a style already interned in this screen, written into rect as write_lines writes the same text in the same styles, without a Segment or a Style a run. Rows and columns the runs do not reach are cleared. A run with a line break falls back to write_lines (its text cannot be one row).

use rich::{Segment, Style};
use rich_ext::frame::StyleId;
use rich_ext::surface::{Rect, Screen, TextRun};

let mut fast = Screen::new(6, 1);
let bold = fast.intern(Some(&Style::parse("bold").unwrap()));
fast.write_runs(
    Rect::new(0, 0, 6, 1),
    &[vec![TextRun::new("ab", bold), TextRun::new("c", StyleId::NONE)]],
);
// The same cells as rich's path.
let mut slow = Screen::new(6, 1);
slow.write_lines(
    Rect::new(0, 0, 6, 1),
    &[vec![Segment::new("ab", Some(Style::parse("bold").unwrap())), Segment::new("c", None)]],
);
assert_eq!(fast.lines(), slow.lines());
Source

pub fn underlay(&mut self, x: u16, y: u16, style: &Style)

Lay style under the cell at x, y: it takes what the cell’s own style leaves unset (a stylesheet’s colours, as CSS inherits them).

Source

pub fn restyle(&mut self, x: u16, y: u16, style: &Style)

Lay style over the cell at x, y (a selection’s highlight).

Source

pub fn blit(&mut self, source: &Screen, from: Rect, x: u16, y: u16)

Copy the cells of from in source to this screen at x, y, clipped to this screen. A wide character cut by either edge of from, or by this screen’s right edge, becomes a space.

Source

pub fn scroll_up(&mut self, rect: Rect, rows: u16)

Move the rows of rect up by rows, dropping the top ones; the rows that open at the bottom are cleared.

Source

pub fn lines(&self) -> Vec<Vec<Segment>>

Each row as rendered segments, a run of cells in one style per segment: what any rich renderer takes, so a frame can be drawn somewhere else (into a ratatui buffer with rs-rich-ratatui’s lines_to_buffer, for one).

Source

pub fn to_svg(&self, options: &SvgOptions<'_>) -> String

The screen as an SVG picture of a terminal, through Frame::to_svg: each row’s runs of cells in their styles, as wide as the screen. A screenshot of an app, or a snapshot to review.

use rich::{Segment, Style};
use rich_ext::frame::SvgOptions;
use rich_ext::surface::{Rect, Screen};

let mut screen = Screen::new(20, 3);
let red = Style::parse("bold red").unwrap();
screen.write_lines(Rect::new(0, 0, 20, 1), &[vec![Segment::new("hi", Some(red))]]);
let svg = screen.to_svg(&SvgOptions::default().title("demo"));
assert!(svg.starts_with("<svg"));
assert!(svg.contains("font-weight: bold"));
Source

pub fn plain(&self) -> Vec<String>

Each row as plain text (continuation cells skipped).

Trait Implementations§

Source§

impl Clone for Screen

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Screen

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more