Pass surface as part of RenderCtx

gui
Blaž Hrastnik 3 years ago
parent 3c0e11d69e
commit d7b1c40452
No known key found for this signature in database
GPG Key ID: 1238B9C4AD889640

@ -26,6 +26,7 @@ pub struct Context<'a> {
pub struct RenderContext<'a> { pub struct RenderContext<'a> {
pub editor: &'a Editor, pub editor: &'a Editor,
pub surface: &'a mut Surface,
pub scroll: Option<usize>, pub scroll: Option<usize>,
} }
@ -34,7 +35,6 @@ pub trait Component: Any + AnyComponent {
fn handle_event(&mut self, _event: Event, _ctx: &mut Context) -> EventResult { fn handle_event(&mut self, _event: Event, _ctx: &mut Context) -> EventResult {
EventResult::Ignored(None) EventResult::Ignored(None)
} }
// , args: ()
/// Should redraw? Useful for saving redraw cycles if we know component didn't change. /// Should redraw? Useful for saving redraw cycles if we know component didn't change.
fn should_update(&self) -> bool { fn should_update(&self) -> bool {
@ -42,7 +42,7 @@ pub trait Component: Any + AnyComponent {
} }
/// Render the component onto the provided surface. /// Render the component onto the provided surface.
fn render(&mut self, area: Rect, frame: &mut Surface, ctx: &mut RenderContext); fn render(&mut self, area: Rect, ctx: &mut RenderContext);
/// Get cursor position and cursor kind. /// Get cursor position and cursor kind.
fn cursor(&self, _area: Rect, _ctx: &Editor) -> (Option<Position>, CursorKind) { fn cursor(&self, _area: Rect, _ctx: &Editor) -> (Option<Position>, CursorKind) {
@ -185,13 +185,14 @@ impl Compositor {
// let area = *surface.area(); // let area = *surface.area();
let mut cx = RenderContext { let mut render_cx = RenderContext {
editor: cx.editor, editor: cx.editor,
surface,
scroll: None, scroll: None,
}; };
for layer in &mut self.layers { for layer in &mut self.layers {
layer.render(area, surface, &mut cx); layer.render(area, &mut render_cx);
} }
let (pos, kind) = self.cursor(area, cx.editor); let (pos, kind) = self.cursor(area, cx.editor);

@ -1,7 +1,6 @@
use crate::compositor::{Component, Context, EventResult, RenderContext}; use crate::compositor::{Component, Context, EventResult, RenderContext};
use crossterm::event::{Event, KeyCode, KeyEvent}; use crossterm::event::{Event, KeyCode, KeyEvent};
use helix_view::editor::CompleteAction; use helix_view::editor::CompleteAction;
use tui::buffer::Buffer as Surface;
use std::borrow::Cow; use std::borrow::Cow;
@ -301,8 +300,8 @@ impl Component for Completion {
self.popup.required_size(viewport) self.popup.required_size(viewport)
} }
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
self.popup.render(area, surface, cx); self.popup.render(area, cx);
// if we have a selection, render a markdown popup on top/below with info // if we have a selection, render a markdown popup on top/below with info
if let Some(option) = self.popup.contents().selection() { if let Some(option) = self.popup.contents().selection() {
@ -403,8 +402,8 @@ impl Component for Completion {
// clear area // clear area
let background = cx.editor.theme.get("ui.popup"); let background = cx.editor.theme.get("ui.popup");
surface.clear_with(area, background); cx.surface.clear_with(area, background);
markdown_doc.render(area, surface, cx); markdown_doc.render(area, cx);
} }
} }
} }

@ -1287,20 +1287,21 @@ impl Component for EditorView {
} }
} }
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
// clear with background color // clear with background color
surface.set_style(area, cx.editor.theme.get("ui.background")); cx.surface
.set_style(area, cx.editor.theme.get("ui.background"));
let config = cx.editor.config(); let config = cx.editor.config();
for (view, is_focused) in cx.editor.tree.views() { for (view, is_focused) in cx.editor.tree.views() {
let doc = cx.editor.document(view.doc).unwrap(); let doc = cx.editor.document(view.doc).unwrap();
self.render_view(cx.editor, doc, view, area, surface, is_focused); self.render_view(cx.editor, doc, view, area, cx.surface, is_focused);
} }
if config.auto_info { if config.auto_info {
// TODO: drop &mut self on render // TODO: drop &mut self on render
if let Some(mut info) = cx.editor.autoinfo.clone() { if let Some(mut info) = cx.editor.autoinfo.clone() {
info.render(area, surface, cx); info.render(area, cx);
// cx.editor.autoinfo = Some(info) // cx.editor.autoinfo = Some(info)
} }
} }
@ -1318,7 +1319,7 @@ impl Component for EditorView {
cx.editor.theme.get("ui.text") cx.editor.theme.get("ui.text")
}; };
surface.set_string( cx.surface.set_string(
area.x, area.x,
area.y + area.height.saturating_sub(1), area.y + area.height.saturating_sub(1),
status_msg, status_msg,
@ -1348,7 +1349,7 @@ impl Component for EditorView {
} else { } else {
0 0
}; };
surface.set_string( cx.surface.set_string(
area.x + area.width.saturating_sub(key_width + macro_width), area.x + area.width.saturating_sub(key_width + macro_width),
area.y + area.height.saturating_sub(1), area.y + area.height.saturating_sub(1),
disp.get(disp.len().saturating_sub(key_width as usize)..) disp.get(disp.len().saturating_sub(key_width as usize)..)
@ -1360,7 +1361,7 @@ impl Component for EditorView {
let style = style let style = style
.fg(helix_view::graphics::Color::Yellow) .fg(helix_view::graphics::Color::Yellow)
.add_modifier(Modifier::BOLD); .add_modifier(Modifier::BOLD);
surface.set_string( cx.surface.set_string(
area.x + area.width.saturating_sub(3), area.x + area.width.saturating_sub(3),
area.y + area.height.saturating_sub(1), area.y + area.height.saturating_sub(1),
&disp, &disp,
@ -1370,7 +1371,7 @@ impl Component for EditorView {
} }
if let Some(completion) = self.completion.as_mut() { if let Some(completion) = self.completion.as_mut() {
completion.render(area, surface, cx); completion.render(area, cx);
} }
} }

@ -1,11 +1,10 @@
use crate::compositor::{Component, RenderContext}; use crate::compositor::{Component, RenderContext};
use helix_view::graphics::{Margin, Rect}; use helix_view::graphics::{Margin, Rect};
use helix_view::info::Info; use helix_view::info::Info;
use tui::buffer::Buffer as Surface;
use tui::widgets::{Block, Borders, Paragraph, Widget}; use tui::widgets::{Block, Borders, Paragraph, Widget};
impl Component for Info { impl Component for Info {
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, viewport: Rect, cx: &mut RenderContext<'_>) {
let text_style = cx.editor.theme.get("ui.text.info"); let text_style = cx.editor.theme.get("ui.text.info");
let popup_style = cx.editor.theme.get("ui.popup.info"); let popup_style = cx.editor.theme.get("ui.popup.info");
@ -20,7 +19,7 @@ impl Component for Info {
width, width,
height, height,
)); ));
surface.clear_with(area, popup_style); cx.surface.clear_with(area, popup_style);
let block = Block::default() let block = Block::default()
.title(self.title.as_str()) .title(self.title.as_str())
@ -32,10 +31,10 @@ impl Component for Info {
horizontal: 1, horizontal: 1,
}; };
let inner = block.inner(area).inner(&margin); let inner = block.inner(area).inner(&margin);
block.render(area, surface); block.render(area, cx.surface);
Paragraph::new(self.text.as_str()) Paragraph::new(self.text.as_str())
.style(text_style) .style(text_style)
.render(inner, surface); .render(inner, cx.surface);
} }
} }

@ -1,8 +1,5 @@
use crate::compositor::{Component, RenderContext}; use crate::compositor::{Component, RenderContext};
use tui::{ use tui::text::{Span, Spans, Text};
buffer::Buffer as Surface,
text::{Span, Spans, Text},
};
use std::sync::Arc; use std::sync::Arc;
@ -259,7 +256,7 @@ impl Markdown {
} }
impl Component for Markdown { impl Component for Markdown {
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
use tui::widgets::{Paragraph, Widget, Wrap}; use tui::widgets::{Paragraph, Widget, Wrap};
let text = self.parse(Some(&cx.editor.theme)); let text = self.parse(Some(&cx.editor.theme));
@ -272,7 +269,7 @@ impl Component for Markdown {
vertical: 1, vertical: 1,
horizontal: 1, horizontal: 1,
}; };
par.render(area.inner(&margin), surface); par.render(area.inner(&margin), cx.surface);
} }
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {

@ -3,7 +3,7 @@ use crate::{
ctrl, key, shift, ctrl, key, shift,
}; };
use crossterm::event::Event; use crossterm::event::Event;
use tui::{buffer::Buffer as Surface, widgets::Table}; use tui::widgets::Table;
pub use tui::widgets::{Cell, Row}; pub use tui::widgets::{Cell, Row};
@ -265,7 +265,7 @@ impl<T: Item + 'static> Component for Menu<T> {
Some(self.size) Some(self.size)
} }
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
let theme = &cx.editor.theme; let theme = &cx.editor.theme;
let style = theme let style = theme
.try_get("ui.menu") .try_get("ui.menu")
@ -307,7 +307,7 @@ impl<T: Item + 'static> Component for Menu<T> {
table.render_table( table.render_table(
area, area,
surface, cx.surface,
&mut TableState { &mut TableState {
offset: scroll, offset: scroll,
selected: self.cursor, selected: self.cursor,
@ -320,7 +320,7 @@ impl<T: Item + 'static> Component for Menu<T> {
let is_marked = i >= scroll_line && i < scroll_line + scroll_height; let is_marked = i >= scroll_line && i < scroll_line + scroll_height;
if !fits && is_marked { if !fits && is_marked {
let cell = &mut surface[(area.x + area.width - 2, area.y + i as u16)]; let cell = &mut cx.surface[(area.x + area.width - 2, area.y + i as u16)];
cell.set_symbol("▐"); cell.set_symbol("▐");
// cell.set_style(selected); // cell.set_style(selected);
// cell.set_style(if is_marked { selected } else { style }); // cell.set_style(if is_marked { selected } else { style });

@ -4,7 +4,6 @@ use helix_view::{
graphics::{CursorKind, Rect}, graphics::{CursorKind, Rect},
Editor, Editor,
}; };
use tui::buffer::Buffer;
use crate::compositor::{Component, Context, EventResult, RenderContext}; use crate::compositor::{Component, Context, EventResult, RenderContext};
@ -44,9 +43,9 @@ fn clip_rect_relative(rect: Rect, percent_horizontal: u8, percent_vertical: u8)
} }
impl<T: Component + 'static> Component for Overlay<T> { impl<T: Component + 'static> Component for Overlay<T> {
fn render(&mut self, area: Rect, frame: &mut Buffer, ctx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, ctx: &mut RenderContext<'_>) {
let dimensions = (self.calc_child_size)(area); let dimensions = (self.calc_child_size)(area);
self.content.render(dimensions, frame, ctx) self.content.render(dimensions, ctx)
} }
fn required_size(&mut self, (width, height): (u16, u16)) -> Option<(u16, u16)> { fn required_size(&mut self, (width, height): (u16, u16)) -> Option<(u16, u16)> {

@ -4,10 +4,7 @@ use crate::{
ui::{self, EditorView}, ui::{self, EditorView},
}; };
use crossterm::event::Event; use crossterm::event::Event;
use tui::{ use tui::widgets::{Block, BorderType, Borders};
buffer::Buffer as Surface,
widgets::{Block, BorderType, Borders},
};
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher; use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
use fuzzy_matcher::FuzzyMatcher; use fuzzy_matcher::FuzzyMatcher;
@ -164,7 +161,7 @@ impl<T> FilePicker<T> {
} }
impl<T: 'static> Component for FilePicker<T> { impl<T: 'static> Component for FilePicker<T> {
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
// +---------+ +---------+ // +---------+ +---------+
// |prompt | |preview | // |prompt | |preview |
// +---------+ | | // +---------+ | |
@ -177,7 +174,7 @@ impl<T: 'static> Component for FilePicker<T> {
// clear area // clear area
let background = cx.editor.theme.get("ui.background"); let background = cx.editor.theme.get("ui.background");
let text = cx.editor.theme.get("ui.text"); let text = cx.editor.theme.get("ui.text");
surface.clear_with(area, background); cx.surface.clear_with(area, background);
let picker_width = if render_preview { let picker_width = if render_preview {
area.width / 2 area.width / 2
@ -186,7 +183,7 @@ impl<T: 'static> Component for FilePicker<T> {
}; };
let picker_area = area.with_width(picker_width); let picker_area = area.with_width(picker_width);
self.picker.render(picker_area, surface, cx); self.picker.render(picker_area, cx);
if !render_preview { if !render_preview {
return; return;
@ -205,7 +202,7 @@ impl<T: 'static> Component for FilePicker<T> {
horizontal: 1, horizontal: 1,
}; };
let inner = inner.inner(&margin); let inner = inner.inner(&margin);
block.render(preview_area, surface); block.render(preview_area, cx.surface);
if let Some((path, range)) = self.current_file(cx.editor) { if let Some((path, range)) = self.current_file(cx.editor) {
let preview = self.get_preview(&path, cx.editor); let preview = self.get_preview(&path, cx.editor);
@ -215,7 +212,8 @@ impl<T: 'static> Component for FilePicker<T> {
let alt_text = preview.placeholder(); let alt_text = preview.placeholder();
let x = inner.x + inner.width.saturating_sub(alt_text.len() as u16) / 2; let x = inner.x + inner.width.saturating_sub(alt_text.len() as u16) / 2;
let y = inner.y + inner.height / 2; let y = inner.y + inner.height / 2;
surface.set_stringn(x, y, alt_text, inner.width as usize, text); cx.surface
.set_stringn(x, y, alt_text, inner.width as usize, text);
return; return;
} }
}; };
@ -237,7 +235,7 @@ impl<T: 'static> Component for FilePicker<T> {
doc, doc,
offset, offset,
inner, inner,
surface, cx.surface,
&cx.editor.theme, &cx.editor.theme,
highlights, highlights,
&cx.editor.config().whitespace, &cx.editor.config().whitespace,
@ -246,7 +244,7 @@ impl<T: 'static> Component for FilePicker<T> {
// highlight the line // highlight the line
if let Some((start, end)) = range { if let Some((start, end)) = range {
let offset = start.saturating_sub(first_line) as u16; let offset = start.saturating_sub(first_line) as u16;
surface.set_style( cx.surface.set_style(
Rect::new( Rect::new(
inner.x, inner.x,
inner.y + offset, inner.y + offset,
@ -552,7 +550,7 @@ impl<T: 'static> Component for Picker<T> {
EventResult::Consumed(None) EventResult::Consumed(None)
} }
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
let text_style = cx.editor.theme.get("ui.text"); let text_style = cx.editor.theme.get("ui.text");
let selected = cx.editor.theme.get("ui.text.focus"); let selected = cx.editor.theme.get("ui.text.focus");
let highlighted = cx.editor.theme.get("special").add_modifier(Modifier::BOLD); let highlighted = cx.editor.theme.get("special").add_modifier(Modifier::BOLD);
@ -560,7 +558,7 @@ impl<T: 'static> Component for Picker<T> {
// -- Render the frame: // -- Render the frame:
// clear area // clear area
let background = cx.editor.theme.get("ui.background"); let background = cx.editor.theme.get("ui.background");
surface.clear_with(area, background); cx.surface.clear_with(area, background);
// don't like this but the lifetime sucks // don't like this but the lifetime sucks
let block = Block::default().borders(Borders::ALL); let block = Block::default().borders(Borders::ALL);
@ -568,14 +566,14 @@ impl<T: 'static> Component for Picker<T> {
// calculate the inner area inside the box // calculate the inner area inside the box
let inner = block.inner(area); let inner = block.inner(area);
block.render(area, surface); block.render(area, cx.surface);
// -- Render the input bar: // -- Render the input bar:
let area = inner.clip_left(1).with_height(1); let area = inner.clip_left(1).with_height(1);
let count = format!("{}/{}", self.matches.len(), self.options.len()); let count = format!("{}/{}", self.matches.len(), self.options.len());
surface.set_stringn( cx.surface.set_stringn(
(area.x + area.width).saturating_sub(count.len() as u16 + 1), (area.x + area.width).saturating_sub(count.len() as u16 + 1),
area.y, area.y,
&count, &count,
@ -583,13 +581,13 @@ impl<T: 'static> Component for Picker<T> {
text_style, text_style,
); );
self.prompt.render(area, surface, cx); self.prompt.render(area, cx);
// -- Separator // -- Separator
let sep_style = Style::default().fg(Color::Rgb(90, 89, 119)); let sep_style = Style::default().fg(Color::Rgb(90, 89, 119));
let borders = BorderType::line_symbols(BorderType::Plain); let borders = BorderType::line_symbols(BorderType::Plain);
for x in inner.left()..inner.right() { for x in inner.left()..inner.right() {
if let Some(cell) = surface.get_mut(x, inner.y + 1) { if let Some(cell) = cx.surface.get_mut(x, inner.y + 1) {
cell.set_symbol(borders.horizontal).set_style(sep_style); cell.set_symbol(borders.horizontal).set_style(sep_style);
} }
} }
@ -610,7 +608,8 @@ impl<T: 'static> Component for Picker<T> {
for (i, (_index, option)) in files.take(rows as usize).enumerate() { for (i, (_index, option)) in files.take(rows as usize).enumerate() {
let is_active = i == (self.cursor - offset); let is_active = i == (self.cursor - offset);
if is_active { if is_active {
surface.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected); cx.surface
.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected);
} }
let formatted = (self.format_fn)(option); let formatted = (self.format_fn)(option);
@ -620,7 +619,7 @@ impl<T: 'static> Component for Picker<T> {
.fuzzy_indices(&formatted, self.prompt.line()) .fuzzy_indices(&formatted, self.prompt.line())
.unwrap_or_default(); .unwrap_or_default();
surface.set_string_truncated( cx.surface.set_string_truncated(
inner.x, inner.x,
inner.y + i as u16, inner.y + i as u16,
&formatted, &formatted,

@ -3,7 +3,6 @@ use crate::{
ctrl, key, ctrl, key,
}; };
use crossterm::event::Event; use crossterm::event::Event;
use tui::buffer::Buffer as Surface;
use helix_core::Position; use helix_core::Position;
use helix_view::{ use helix_view::{
@ -179,7 +178,7 @@ impl<T: Component> Component for Popup<T> {
Some(self.size) Some(self.size)
} }
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, viewport: Rect, cx: &mut RenderContext<'_>) {
// trigger required_size so we recalculate if the child changed // trigger required_size so we recalculate if the child changed
self.required_size((viewport.width, viewport.height)); self.required_size((viewport.width, viewport.height));
@ -192,10 +191,10 @@ impl<T: Component> Component for Popup<T> {
// clear area // clear area
let background = cx.editor.theme.get("ui.popup"); let background = cx.editor.theme.get("ui.popup");
surface.clear_with(area, background); cx.surface.clear_with(area, background);
let inner = area.inner(&self.margin); let inner = area.inner(&self.margin);
self.contents.render(inner, surface, cx); self.contents.render(inner, cx);
} }
fn id(&self) -> Option<&'static str> { fn id(&self) -> Option<&'static str> {

@ -4,7 +4,6 @@ use crossterm::event::Event;
use helix_view::input::KeyEvent; use helix_view::input::KeyEvent;
use helix_view::keyboard::KeyCode; use helix_view::keyboard::KeyCode;
use std::{borrow::Cow, ops::RangeFrom}; use std::{borrow::Cow, ops::RangeFrom};
use tui::buffer::Buffer as Surface;
use tui::widgets::{Block, Borders, Widget}; use tui::widgets::{Block, Borders, Widget};
use helix_core::{ use helix_core::{
@ -327,7 +326,7 @@ impl Prompt {
const BASE_WIDTH: u16 = 30; const BASE_WIDTH: u16 = 30;
impl Prompt { impl Prompt {
pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { pub fn render_prompt(&self, area: Rect, cx: &mut RenderContext<'_>) {
let theme = &cx.editor.theme; let theme = &cx.editor.theme;
let prompt_color = theme.get("ui.text"); let prompt_color = theme.get("ui.text");
let completion_color = theme.get("ui.statusline"); let completion_color = theme.get("ui.statusline");
@ -367,7 +366,7 @@ impl Prompt {
.map(|selection| selection / items * items) .map(|selection| selection / items * items)
.unwrap_or_default(); .unwrap_or_default();
surface.clear_with(area, background); cx.surface.clear_with(area, background);
let mut row = 0; let mut row = 0;
let mut col = 0; let mut col = 0;
@ -380,7 +379,7 @@ impl Prompt {
} else { } else {
completion_color completion_color
}; };
surface.set_stringn( cx.surface.set_stringn(
area.x + col * (1 + col_width), area.x + col * (1 + col_width),
area.y + row, area.y + row,
&completion, &completion,
@ -413,7 +412,7 @@ impl Prompt {
)); ));
let background = theme.get("ui.help"); let background = theme.get("ui.help");
surface.clear_with(area, background); cx.surface.clear_with(area, background);
let block = Block::default() let block = Block::default()
// .title(self.title.as_str()) // .title(self.title.as_str())
@ -425,14 +424,15 @@ impl Prompt {
horizontal: 1, horizontal: 1,
}); });
block.render(area, surface); block.render(area, cx.surface);
text.render(inner, surface, cx); text.render(inner, cx);
} }
let line = area.height - 1; let line = area.height - 1;
// render buffer text // render buffer text
surface.set_string(area.x, area.y + line, &self.prompt, prompt_color); cx.surface
surface.set_string( .set_string(area.x, area.y + line, &self.prompt, prompt_color);
cx.surface.set_string(
area.x + self.prompt.len() as u16, area.x + self.prompt.len() as u16,
area.y + line, area.y + line,
&self.line, &self.line,
@ -547,8 +547,8 @@ impl Component for Prompt {
EventResult::Consumed(None) EventResult::Consumed(None)
} }
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
self.render_prompt(area, surface, cx) self.render_prompt(area, cx)
} }
fn cursor(&self, area: Rect, _editor: &Editor) -> (Option<Position>, CursorKind) { fn cursor(&self, area: Rect, _editor: &Editor) -> (Option<Position>, CursorKind) {

@ -1,5 +1,4 @@
use crate::compositor::{Component, RenderContext}; use crate::compositor::{Component, RenderContext};
use tui::buffer::Buffer as Surface;
use helix_view::graphics::Rect; use helix_view::graphics::Rect;
@ -30,13 +29,13 @@ impl From<tui::text::Text<'static>> for Text {
} }
impl Component for Text { impl Component for Text {
fn render(&mut self, area: Rect, surface: &mut Surface, _cx: &mut RenderContext<'_>) { fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
use tui::widgets::{Paragraph, Widget, Wrap}; use tui::widgets::{Paragraph, Widget, Wrap};
let par = Paragraph::new(self.contents.clone()).wrap(Wrap { trim: false }); let par = Paragraph::new(self.contents.clone()).wrap(Wrap { trim: false });
// .scroll(x, y) offsets // .scroll(x, y) offsets
par.render(area, surface); par.render(area, cx.surface);
} }
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {

Loading…
Cancel
Save