mod layout;
#[cfg(test)]
mod layout_tests;
mod navigation;
mod render;
mod run;
use std::fmt;
use crate::TxtViewConfig;
use layout::LayoutGeometry;
#[derive(Clone)]
pub struct TxtView {
lines: Vec<String>,
display: Vec<String>,
offset: usize,
max_offset: usize,
config: TxtViewConfig,
drag_grab_offset: Option<usize>,
scrollbar_active: bool,
display_geometry: Option<LayoutGeometry>,
}
impl fmt::Debug for TxtView {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TxtView")
.field("line_count", &self.lines.len())
.field("display_rows", &self.display.len())
.field("offset", &self.offset)
.field("max_offset", &self.max_offset)
.field("scrollbar_active", &self.scrollbar_active)
.field("config", &self.config)
.finish()
}
}
impl TxtView {
pub fn new(input: impl AsRef<str>) -> Self {
let lines: Vec<String> = input.as_ref().lines().map(String::from).collect();
let mut view = TxtView {
lines,
display: Vec::new(),
offset: 0,
max_offset: 0,
config: TxtViewConfig::default(),
drag_grab_offset: None,
scrollbar_active: false,
display_geometry: None,
};
view.refresh_bounds();
view
}
#[must_use]
pub fn with_config(mut self, config: TxtViewConfig) -> Self {
self.config = config;
self.refresh_bounds();
self
}
pub fn line_count(&self) -> usize {
self.lines.len()
}
pub fn config(&self) -> &TxtViewConfig {
&self.config
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_reports_counts_instead_of_the_document() {
let viewer = TxtView::new("alpha\nbeta\ngamma");
let out = format!("{viewer:?}");
assert!(
out.contains("line_count: 3"),
"must report the line count: {out}"
);
assert!(
out.contains("display_rows:"),
"must report the wrapped rows: {out}"
);
assert!(!out.contains("alpha"), "must not dump the document: {out}");
}
}
#[cfg(test)]
mod test_metrics {
use std::cell::Cell;
thread_local! {
static REBUILDS: Cell<usize> = const { Cell::new(0) };
static WRAPS: Cell<usize> = const { Cell::new(0) };
}
pub(crate) fn reset() {
REBUILDS.with(|c| c.set(0));
WRAPS.with(|c| c.set(0));
}
pub(crate) fn bump_rebuild() {
REBUILDS.with(|c| c.set(c.get() + 1));
}
pub(crate) fn bump_wrap() {
WRAPS.with(|c| c.set(c.get() + 1));
}
pub(crate) fn rebuilds() -> usize {
REBUILDS.with(Cell::get)
}
pub(crate) fn wraps() -> usize {
WRAPS.with(Cell::get)
}
}