Switched to hybrid iterator and while loop grid processor. Still hairy but much more managable. Not finished compiling yet.
This commit is contained in:
parent
c9584a9d0c
commit
9d063ae6d8
1 changed files with 143 additions and 72 deletions
|
@ -1,6 +1,7 @@
|
||||||
mod terminal_layout_context;
|
mod terminal_layout_context;
|
||||||
|
|
||||||
use alacritty_terminal::{
|
use alacritty_terminal::{
|
||||||
|
ansi::{Color::Named, NamedColor},
|
||||||
grid::{Dimensions, GridIterator, Indexed, Scroll},
|
grid::{Dimensions, GridIterator, Indexed, Scroll},
|
||||||
index::{Column as GridCol, Line as GridLine, Point, Side},
|
index::{Column as GridCol, Line as GridLine, Point, Side},
|
||||||
selection::{Selection, SelectionRange, SelectionType},
|
selection::{Selection, SelectionRange, SelectionType},
|
||||||
|
@ -55,11 +56,6 @@ pub struct TerminalEl {
|
||||||
pub struct CellWidth(f32);
|
pub struct CellWidth(f32);
|
||||||
pub struct LineHeight(f32);
|
pub struct LineHeight(f32);
|
||||||
|
|
||||||
struct LayoutLine {
|
|
||||||
cells: Vec<LayoutCell>,
|
|
||||||
highlighted_range: Option<Range<usize>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
///New type pattern to ensure that we use adjusted mouse positions throughout the code base, rather than
|
///New type pattern to ensure that we use adjusted mouse positions throughout the code base, rather than
|
||||||
struct PaneRelativePos(Vector2F);
|
struct PaneRelativePos(Vector2F);
|
||||||
|
|
||||||
|
@ -68,26 +64,11 @@ fn relative_pos(mouse_position: Vector2F, origin: Vector2F) -> PaneRelativePos {
|
||||||
PaneRelativePos(mouse_position.sub(origin)) //Avoid the extra allocation by mutating
|
PaneRelativePos(mouse_position.sub(origin)) //Avoid the extra allocation by mutating
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
struct LayoutCell {
|
|
||||||
point: Point<i32, i32>,
|
|
||||||
text: Line, //NOTE TO SELF THIS IS BAD PERFORMANCE RN!
|
|
||||||
background_color: Color,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LayoutCell {
|
|
||||||
fn new(point: Point<i32, i32>, text: Line, background_color: Color) -> LayoutCell {
|
|
||||||
LayoutCell {
|
|
||||||
point,
|
|
||||||
text,
|
|
||||||
background_color,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///The information generated during layout that is nescessary for painting
|
///The information generated during layout that is nescessary for painting
|
||||||
pub struct LayoutState {
|
pub struct LayoutState {
|
||||||
layout_lines: Vec<LayoutLine>,
|
cells: Vec<LayoutCell>,
|
||||||
|
rects: Vec<LayoutRect>,
|
||||||
|
highlights: Vec<RelativeHighlightedRange>,
|
||||||
line_height: LineHeight,
|
line_height: LineHeight,
|
||||||
em_width: CellWidth,
|
em_width: CellWidth,
|
||||||
cursor: Option<Cursor>,
|
cursor: Option<Cursor>,
|
||||||
|
@ -225,19 +206,9 @@ impl Element for TerminalEl {
|
||||||
|
|
||||||
let content = term.renderable_content();
|
let content = term.renderable_content();
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO for layouts:
|
|
||||||
* - Refactor this whole process to produce 'text cells', 'background rects', and 'selections' which know
|
|
||||||
* how to paint themselves
|
|
||||||
* - Rather than doing everything per cell, map each cell into a tuple and then unzip the streams
|
|
||||||
* - For efficiency:
|
|
||||||
* - filter out all background colored background rects
|
|
||||||
* - filter out all text cells which just contain ' '
|
|
||||||
* - Smoosh together rectangles on same line
|
|
||||||
|
|
||||||
*/
|
|
||||||
//Layout grid cells
|
//Layout grid cells
|
||||||
let layout_lines = layout_lines(
|
|
||||||
|
let (cells, rects, highlights) = layout_grid(
|
||||||
content.display_iter,
|
content.display_iter,
|
||||||
&tcx.text_style,
|
&tcx.text_style,
|
||||||
tcx.terminal_theme,
|
tcx.terminal_theme,
|
||||||
|
@ -267,12 +238,14 @@ impl Element for TerminalEl {
|
||||||
(
|
(
|
||||||
constraint.max,
|
constraint.max,
|
||||||
LayoutState {
|
LayoutState {
|
||||||
layout_lines,
|
|
||||||
line_height: tcx.line_height,
|
line_height: tcx.line_height,
|
||||||
em_width: tcx.cell_width,
|
em_width: tcx.cell_width,
|
||||||
cursor,
|
cursor,
|
||||||
background_color,
|
background_color,
|
||||||
selection_color: tcx.selection_color,
|
selection_color: tcx.selection_color,
|
||||||
|
cells,
|
||||||
|
rects,
|
||||||
|
highlights,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -310,7 +283,7 @@ impl Element for TerminalEl {
|
||||||
});
|
});
|
||||||
|
|
||||||
//Draw cell backgrounds
|
//Draw cell backgrounds
|
||||||
for layout_line in &layout.layout_lines {
|
for layout_line in &layout.layout_cells {
|
||||||
for layout_cell in &layout_line.cells {
|
for layout_cell in &layout_line.cells {
|
||||||
let position = vec2f(
|
let position = vec2f(
|
||||||
(origin.x() + layout_cell.point.column as f32 * layout.em_width.0)
|
(origin.x() + layout_cell.point.column as f32 * layout.em_width.0)
|
||||||
|
@ -333,7 +306,7 @@ impl Element for TerminalEl {
|
||||||
cx.paint_layer(clip_bounds, |cx| {
|
cx.paint_layer(clip_bounds, |cx| {
|
||||||
let mut highlight_y = None;
|
let mut highlight_y = None;
|
||||||
let highlight_lines = layout
|
let highlight_lines = layout
|
||||||
.layout_lines
|
.layout_cells
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|line| {
|
.filter_map(|line| {
|
||||||
if let Some(range) = &line.highlighted_range {
|
if let Some(range) = &line.highlighted_range {
|
||||||
|
@ -370,7 +343,7 @@ impl Element for TerminalEl {
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.paint_layer(clip_bounds, |cx| {
|
cx.paint_layer(clip_bounds, |cx| {
|
||||||
for layout_line in &layout.layout_lines {
|
for layout_line in &layout.layout_cells {
|
||||||
for layout_cell in &layout_line.cells {
|
for layout_cell in &layout_line.cells {
|
||||||
let point = layout_cell.point;
|
let point = layout_cell.point;
|
||||||
|
|
||||||
|
@ -549,57 +522,155 @@ fn make_new_size(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_lines(
|
#[derive(Clone, Debug, Default)]
|
||||||
|
struct LayoutCell {
|
||||||
|
point: Point<i32, i32>,
|
||||||
|
text: Line,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutCell {
|
||||||
|
fn new(point: Point<i32, i32>, text: Line) -> LayoutCell {
|
||||||
|
LayoutCell { point, text }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
struct LayoutRect {
|
||||||
|
pos: Point<i32, i32>,
|
||||||
|
num_of_cells: usize,
|
||||||
|
color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutRect {
|
||||||
|
fn new(pos: Point<i32, i32>, num_of_cells: usize, color: Color) -> LayoutRect {
|
||||||
|
LayoutRect {
|
||||||
|
pos,
|
||||||
|
num_of_cells,
|
||||||
|
color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extend(&mut self) {
|
||||||
|
self.num_of_cells += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RelativeHighlightedRange {
|
||||||
|
line_index: usize,
|
||||||
|
range: Range<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelativeHighlightedRange {
|
||||||
|
fn new(line_index: usize, range: Range<usize>) -> Self {
|
||||||
|
RelativeHighlightedRange { line_index, range }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout_grid(
|
||||||
grid: GridIterator<Cell>,
|
grid: GridIterator<Cell>,
|
||||||
text_style: &TextStyle,
|
text_style: &TextStyle,
|
||||||
terminal_theme: &TerminalStyle,
|
terminal_theme: &TerminalStyle,
|
||||||
text_layout_cache: &TextLayoutCache,
|
text_layout_cache: &TextLayoutCache,
|
||||||
modal: bool,
|
modal: bool,
|
||||||
selection_range: Option<SelectionRange>,
|
selection_range: Option<SelectionRange>,
|
||||||
) -> Vec<LayoutLine> {
|
) -> (
|
||||||
let lines = grid.group_by(|i| i.point.line);
|
Vec<LayoutCell>,
|
||||||
lines
|
Vec<LayoutRect>,
|
||||||
.into_iter()
|
Vec<RelativeHighlightedRange>,
|
||||||
.enumerate()
|
) {
|
||||||
.map(|(line_index, (_, line))| {
|
let mut cells = vec![];
|
||||||
let mut highlighted_range = None;
|
let mut rects = vec![];
|
||||||
let cells = line
|
let mut highlight_ranges = vec![];
|
||||||
.enumerate()
|
|
||||||
.map(|(x_index, indexed_cell)| {
|
let mut cur_rect: Option<LayoutRect> = None;
|
||||||
if selection_range
|
let mut cur_alac_color = None;
|
||||||
.map(|range| range.contains(indexed_cell.point))
|
let mut highlighted_range = None;
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
let linegroups = grid.group_by(|i| i.point.line);
|
||||||
let mut range = highlighted_range.take().unwrap_or(x_index..x_index);
|
for (line_index, (_, line)) in linegroups.into_iter().enumerate() {
|
||||||
range.end = range.end.max(x_index);
|
for (x_index, cell) in line.enumerate() {
|
||||||
highlighted_range = Some(range);
|
//Increase selection range
|
||||||
|
{
|
||||||
|
if selection_range
|
||||||
|
.map(|range| range.contains(cell.point))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
let mut range = highlighted_range.take().unwrap_or(x_index..x_index);
|
||||||
|
range.end = range.end.max(x_index);
|
||||||
|
highlighted_range = Some(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Expand background rect range
|
||||||
|
{
|
||||||
|
match (cell.bg, cur_alac_color) {
|
||||||
|
(Named(NamedColor::Background), Some(_)) => {
|
||||||
|
//Skip color, end background
|
||||||
|
cur_alac_color = None;
|
||||||
|
rects.push(cur_rect.take().unwrap());
|
||||||
}
|
}
|
||||||
|
(bg, Some(cur_color)) => {
|
||||||
|
//If they're the same, extend the match
|
||||||
|
if bg == cur_color {
|
||||||
|
cur_rect.unwrap().extend()
|
||||||
|
} else {
|
||||||
|
//If they differ, end background and restart
|
||||||
|
cur_alac_color = None;
|
||||||
|
rects.push(cur_rect.take().unwrap());
|
||||||
|
|
||||||
let cell_text = &indexed_cell.c.to_string();
|
cur_alac_color = Some(bg);
|
||||||
|
cur_rect = Some(LayoutRect::new(
|
||||||
|
Point::new(line_index as i32, cell.point.column.0 as i32),
|
||||||
|
1,
|
||||||
|
convert_color(&bg, &terminal_theme.colors, modal),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(bg, None) if !matches!(bg, Named(NamedColor::Background)) => {
|
||||||
|
//install new background
|
||||||
|
cur_alac_color = Some(bg);
|
||||||
|
cur_rect = Some(LayoutRect::new(
|
||||||
|
Point::new(line_index as i32, cell.point.column.0 as i32),
|
||||||
|
1,
|
||||||
|
convert_color(&bg, &terminal_theme.colors, modal),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
(_, _) => {} //Only happens when bg is NamedColor::Background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let cell_style = cell_style(&indexed_cell, terminal_theme, text_style, modal);
|
//Layout current cell text
|
||||||
|
{
|
||||||
|
let cell_text = &cell.c.to_string();
|
||||||
|
if cell_text != " " {
|
||||||
|
let cell_style = cell_style(&cell, terminal_theme, text_style, modal);
|
||||||
|
|
||||||
//This is where we might be able to get better performance
|
|
||||||
let layout_cell = text_layout_cache.layout_str(
|
let layout_cell = text_layout_cache.layout_str(
|
||||||
cell_text,
|
cell_text,
|
||||||
text_style.font_size,
|
text_style.font_size,
|
||||||
&[(cell_text.len(), cell_style)],
|
&[(cell_text.len(), cell_style)],
|
||||||
);
|
);
|
||||||
|
|
||||||
LayoutCell::new(
|
cells.push(LayoutCell::new(
|
||||||
Point::new(line_index as i32, indexed_cell.point.column.0 as i32),
|
Point::new(line_index as i32, cell.point.column.0 as i32),
|
||||||
layout_cell,
|
layout_cell,
|
||||||
convert_color(&indexed_cell.bg, &terminal_theme.colors, modal),
|
))
|
||||||
)
|
}
|
||||||
})
|
};
|
||||||
.collect::<Vec<LayoutCell>>();
|
}
|
||||||
|
|
||||||
LayoutLine {
|
if highlighted_range.is_some() {
|
||||||
cells,
|
highlight_ranges.push(RelativeHighlightedRange::new(
|
||||||
highlighted_range,
|
line_index,
|
||||||
}
|
highlighted_range.take().unwrap(),
|
||||||
})
|
))
|
||||||
.collect::<Vec<LayoutLine>>()
|
}
|
||||||
|
|
||||||
|
if cur_rect.is_some() {
|
||||||
|
rects.push(cur_rect.take().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(cells, rects, highlight_ranges)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the cursor position and expected block width, may return a zero width if x_for_index returns
|
// Compute the cursor position and expected block width, may return a zero width if x_for_index returns
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue