Allow custom title and ui config in custom layout.

Adds the following layouts:

- Static
- Dynamic

Deprecates `CustomContent` (but won't be removed to maintain compatibility).

Closes: https://github.com/sayanarijit/xplr/issues/563
pull/589/head
Arijit Basu 1 year ago
parent 6595e2ee93
commit 82a822be45

@ -20,6 +20,10 @@ A border can be one of the following:
- Double
- Thick
### Border Style
The [style][1] of the borders.
## Example
```lua
@ -28,3 +32,5 @@ xplr.config.general.panel_ui.default.border_type = "Thick"
xplr.config.general.panel_ui.default.border_style.fg = "Black"
xplr.config.general.panel_ui.default.border_style.bg = "Gray"
```
[1]: style.md#style

@ -32,56 +32,61 @@ A layout can be one of the following:
- [Selection][11]
- [HelpMenu][12]
- [SortAndFilter][13]
- [CustomContent][25]
- [Static][25]
- [Dynamic][26]
- [Horizontal][14]
- [Vertical][16]
- CustomContent (deprecated, use `Static` or `Dynamic`)
### Nothing
This layout contains a blank panel.
Example: "Nothing"
Type: "Nothing"
### Table
This layout contains the table displaying the files and directories in the
current directory.
This layout contains the table displaying the files and directories in the current
directory.
### InputAndLogs
This layout contains the panel displaying the input prompt and logs.
Example: "InputAndLogs"
Type: "InputAndLogs"
### Selection
This layout contains the panel displaying the selected paths.
Example: "Selection"
Type: "Selection"
### HelpMenu
This layout contains the panel displaying the help menu for the current mode in
real-time.
Example: "HelpMenu"
Type: "HelpMenu"
### SortAndFilter
This layout contains the panel displaying the pipeline of sorters and filters
applied of the list of paths being displayed.
This layout contains the panel displaying the pipeline of sorters and filters applied of
the list of paths being displayed.
Example: "SortAndFilter"
Type: "SortAndFilter"
### Custom Content
### Static
Custom content is a special layout to render something custom.
It contains the following information:
This is a custom layout to render static content.
Type: { Static = [Custom Panel][27] }
### Dynamic
- [title][33]
- [body][34]
This is a custom layout to render dynamic content using a function defined in
[xplr.fn][28] that returns [Custom Panel][27].
Example: { CustomContent = { title = [title][33], body = [body][34] }
Type: { Dynamic = [Content Renderer][35] }
### Horizontal
@ -92,7 +97,7 @@ It contains the following information:
- [config][15]
- [splits][17]
Example: { Horizontal = { config = [config][15], splits = [splits][17] }
Type: { Horizontal = { config = [config][15], splits = [splits][17] }
### Vertical
@ -103,7 +108,7 @@ It contains the following information:
- [config][15]
- [splits][17]
Example: { Vertical = { config = [config][15], splits = [splits][17] }
Type: { Vertical = { config = [config][15], splits = [splits][17] }
## Layout Config
@ -166,187 +171,153 @@ Type: list of [Layout][3]
The list of child layouts to fit into the parent layout.
## title
Type: nullable string
The title of the panel.
## body
## Custom Panel
Type: [Content Body][26]
Custom panel can be one of the following:
The body of the panel.
- [Paragraph][29]
- [List][30]
- [Table][31]
## Content Body
Content body can be one of the following:
- [StaticParagraph][27]
- [DynamicParagraph][28]
- [StaticList][29]
- [DynamicList][30]
- [StaticTable][31]
- [DynamicTable][32]
## Static Paragraph
### Paragraph
A paragraph to render. It contains the following fields:
- **render** (string): The string to render.
- **ui** (nullable [Panel UI Config][32]): Optional UI config for the panel.
- **body** (string): The string to render.
#### Example: Render a custom static paragraph
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = {
StaticParagraph = { render = "custom body" },
Static = {
Paragraph = {
ui = { title = { format = " custom title " } },
body = "custom body",
},
},
}
```
## Dynamic Paragraph
A [Lua function][35] to render a custom paragraph.
It contains the following fields:
- **render** (string): The [lua function][35] that returns the paragraph to
render.
#### Example: Render a custom dynamic paragraph
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = { DynamicParagraph = { render = "custom.render_layout" } },
},
}
xplr.config.layouts.builtin.default = { Dynamic = "custom.render_layout" }
xplr.fn.custom.render_layout = function(ctx)
return ctx.app.pwd
return {
Paragraph = {
ui = { title = { format = ctx.app.pwd } },
body = xplr.util.to_yaml(ctx.app.focused_node),
},
}
end
```
## Static List
### List
A list to render. It contains the following fields:
- **render** (list of string): The list to render.
- **ui** (nullable [Panel UI Config][32]): Optional UI config for the panel.
- **body** (list of string): The list of strings to display.
#### Example: Render a custom static list
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = {
StaticList = { render = { "1", "2", "3" } },
Static = {
List = {
ui = { title = { format = " custom title " } },
body = { "1", "2", "3" },
},
},
}
```
## Dynamic List
A [Lua function][35] to render a custom list.
It contains the following fields:
- **render** (string): The [lua function][35] that returns the list to render.
#### Example: Render a custom dynamic list
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = { DynamicList = { render = "custom.render_layout" } },
},
}
xplr.config.layouts.builtin.default = { Dynamic = "custom.render_layout" }
xplr.fn.custom.render_layout = function(ctx)
return {
ctx.app.pwd,
ctx.app.version,
tostring(ctx.app.pid),
List = {
ui = { title = { format = ctx.app.pwd } },
body = {
(ctx.app.focused_node or {}).relative_path or "",
ctx.app.version,
tostring(ctx.app.pid),
},
},
}
end
```
## Static Table
## Table
A table to render. It contains the following fields:
A custom table to render. It contains the following fields:
- **ui** (nullable [Panel UI Config][32]): Optional UI config for the panel.
- **widths** (list of [Constraint][22]): Width of the columns.
- **col_spacing** (nullable int): Spacing between columns. Defaults to 1.
- **render** (list of list of string): The rows and columns to render.
- **body** (list of list of string): The rows and columns to render.
#### Example: Render a custom static table
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = {
StaticTable = {
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
col_spacing = 1,
render = {
{ "a", "b" },
{ "c", "d" },
},
Static = {
Table = {
ui = { title = { format = " custom title " } },
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
body = {
{ "a", "b" },
{ "c", "d" },
},
},
},
}
```
## Dynamic Table
A [Lua function][35] to render a custom table.
It contains the following fields:
- **widths** (list of [Constraint][22]): Width of the columns.
- **col_spacing** (nullable int): Spacing between columns. Defaults to 1.
- **render** (string): The [lua function][35] that returns the table to render.
#### Example: Render a custom dynamic table
```lua
xplr.config.layouts.builtin.default = {
CustomContent = {
title = "custom title",
body = {
DynamicTable = {
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
col_spacing = 1,
render = "custom.render_layout",
},
},
},
}
xplr.config.layouts.builtin.default = {Dynamic = "custom.render_layout" }
xplr.fn.custom.render_layout = function(ctx)
return {
{ "", "" },
{ "Layout height", tostring(ctx.layout_size.height) },
{ "Layout width", tostring(ctx.layout_size.width) },
{ "", "" },
{ "Screen height", tostring(ctx.screen_size.height) },
{ "Screen width", tostring(ctx.screen_size.width) },
Table = {
ui = { title = { format = ctx.app.pwd } },
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
body = {
{ "", "" },
{ "Layout height", tostring(ctx.layout_size.height) },
{ "Layout width", tostring(ctx.layout_size.width) },
{ "", "" },
{ "Screen height", tostring(ctx.screen_size.height) },
{ "Screen width", tostring(ctx.screen_size.width) },
},
},
}
end
```
## Panel UI Config
It contains the following optional fields:
- **title** ({ format = "string", style = [Style][33] }): the title of the panel.
- **style** ([Style][33]): The style of the panel body.
- **borders** (nullable list of [Border][34]): The shape of the borders.
- **border_type** ([Border Type][54]): The type of the borders.
- **border_style** ([Style][33]): The style of the borders.
## Content Renderer
It is a Lua function that receives [a special argument][36] as input and
@ -421,16 +392,16 @@ Hence, only the following fields are avilable.
[22]: #constraint
[23]: https://s6.gifyu.com/images/layout.png
[24]: https://gifyu.com/image/1X38
[25]: #custom-content
[26]: #content-body
[27]: #static-paragraph
[28]: #dynamic-paragraph
[29]: #static-list
[30]: #dynamic-list
[31]: #static-table
[32]: #dynamic-table
[33]: #title
[34]: #body
[25]: #static
[26]: #dynamic
[27]: #custom-panel
[28]: configuration.md#function
[29]: #paragraph
[30]: #list
[31]: #table
[32]: #panel-ui-config
[33]: style.md#style
[34]: borders.md#border
[35]: #content-renderer
[36]: #content-renderer-argument
[37]: #size
@ -450,3 +421,4 @@ Hence, only the following fields are avilable.
[51]: layouts.md
[52]: lua-function-calls.md#vroot
[53]: lua-function-calls.md#initial_pwd
[54]: borders.md#border-type

@ -0,0 +1,23 @@
xplr.config.layouts.builtin.default = {
Dynamic = "custom.render_layout",
}
xplr.fn.custom.render_layout = function(ctx)
return {
Table = {
ui = { title = { format = ctx.app.pwd } },
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
body = {
{ "", "" },
{ "Layout height", tostring(ctx.layout_size.height) },
{ "Layout width", tostring(ctx.layout_size.width) },
{ "", "" },
{ "Screen height", tostring(ctx.screen_size.height) },
{ "Screen width", tostring(ctx.screen_size.width) },
},
},
}
end

@ -0,0 +1,224 @@
// Things of the past, mostly bad decisions, which cannot erased, stays in this
// haunted module.
use crate::app;
use crate::lua;
use crate::ui::block;
use crate::ui::string_to_text;
use crate::ui::Constraint;
use crate::ui::ContentRendererArg;
use mlua::Lua;
use serde::{Deserialize, Serialize};
use tui::backend::Backend;
use tui::layout::Constraint as TuiConstraint;
use tui::layout::Rect as TuiRect;
use tui::widgets::Cell;
use tui::widgets::List;
use tui::widgets::ListItem;
use tui::widgets::Paragraph;
use tui::widgets::Row;
use tui::widgets::Table;
use tui::Frame;
/// A cursed enum from crate::ui.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub enum ContentBody {
/// A paragraph to render
StaticParagraph { render: String },
/// A Lua function that returns a paragraph to render
DynamicParagraph { render: String },
/// List to render
StaticList { render: Vec<String> },
/// A Lua function that returns lines to render
DynamicList { render: String },
/// A table to render
StaticTable {
widths: Vec<Constraint>,
col_spacing: Option<u16>,
render: Vec<Vec<String>>,
},
/// A Lua function that returns a table to render
DynamicTable {
widths: Vec<Constraint>,
col_spacing: Option<u16>,
render: String,
},
}
/// A cursed struct from crate::ui.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct CustomContent {
pub title: Option<String>,
pub body: ContentBody,
}
/// A cursed function from crate::ui.
pub fn draw_custom_content<B: Backend>(
f: &mut Frame<B>,
screen_size: TuiRect,
layout_size: TuiRect,
app: &app::App,
content: CustomContent,
lua: &Lua,
) {
let config = app.config.general.panel_ui.default.clone();
let title = content.title;
let body = content.body;
match body {
ContentBody::StaticParagraph { render } => {
let render = string_to_text(render);
let content = Paragraph::new(render).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::DynamicParagraph { render } => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let render = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg).unwrap_or_else(|e| format!("{e:?}"))
})
.unwrap_or_else(|e| e.to_string());
let render = string_to_text(render);
let content = Paragraph::new(render).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::StaticList { render } => {
let items = render
.into_iter()
.map(string_to_text)
.map(ListItem::new)
.collect::<Vec<ListItem>>();
let content = List::new(items).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::DynamicList { render } => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let items = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![format!("{e:?}")])
})
.unwrap_or_else(|e| vec![e.to_string()])
.into_iter()
.map(string_to_text)
.map(ListItem::new)
.collect::<Vec<ListItem>>();
let content = List::new(items).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::StaticTable {
widths,
col_spacing,
render,
} => {
let rows = render
.into_iter()
.map(|cols| {
Row::new(
cols.into_iter()
.map(string_to_text)
.map(Cell::from)
.collect::<Vec<Cell>>(),
)
})
.collect::<Vec<Row>>();
let widths = widths
.into_iter()
.map(|w| w.to_tui(screen_size, layout_size))
.collect::<Vec<TuiConstraint>>();
let content = Table::new(rows)
.widths(&widths)
.column_spacing(col_spacing.unwrap_or(1))
.block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::DynamicTable {
widths,
col_spacing,
render,
} => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let rows = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![vec![format!("{e:?}")]])
})
.unwrap_or_else(|e| vec![vec![e.to_string()]])
.into_iter()
.map(|cols| {
Row::new(
cols.into_iter()
.map(string_to_text)
.map(Cell::from)
.collect::<Vec<Cell>>(),
)
})
.collect::<Vec<Row>>();
let widths = widths
.into_iter()
.map(|w| w.to_tui(screen_size, layout_size))
.collect::<Vec<TuiConstraint>>();
let mut content = Table::new(rows).widths(&widths).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
if let Some(col_spacing) = col_spacing {
content = content.column_spacing(col_spacing);
};
f.render_widget(content, layout_size);
}
}
}

@ -4,6 +4,7 @@
pub mod app;
pub mod cli;
pub mod compat;
pub mod config;
pub mod directory_buffer;
pub mod event_reader;

@ -1,5 +1,6 @@
use crate::app::{HelpMenuLine, NodeFilterApplicable, NodeSorterApplicable};
use crate::app::{Node, ResolvedNode};
use crate::compat::{draw_custom_content, CustomContent};
use crate::config::PanelUiConfig;
use crate::lua;
use crate::permissions::Permissions;
@ -38,7 +39,7 @@ fn read_only_indicator(app: &app::App) -> &str {
}
}
fn string_to_text<'a>(string: String) -> Text<'a> {
pub fn string_to_text<'a>(string: String) -> Text<'a> {
if *NO_COLOR {
Text::raw(string)
} else {
@ -77,31 +78,23 @@ impl LayoutOptions {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub enum ContentBody {
/// A paragraph to render
StaticParagraph { render: String },
/// A Lua function that returns a paragraph to render
DynamicParagraph { render: String },
/// List to render
StaticList { render: Vec<String> },
/// A Lua function that returns lines to render
DynamicList { render: String },
/// A table to render
StaticTable {
widths: Vec<Constraint>,
col_spacing: Option<u16>,
render: Vec<Vec<String>>,
pub enum CustomPanel {
Paragraph {
#[serde(default)]
ui: PanelUiConfig,
body: String,
},
/// A Lua function that returns a table to render
DynamicTable {
List {
#[serde(default)]
ui: PanelUiConfig,
body: Vec<String>,
},
Table {
#[serde(default)]
ui: PanelUiConfig,
widths: Vec<Constraint>,
col_spacing: Option<u16>,
render: String,
body: Vec<Vec<String>>,
},
}
@ -114,10 +107,8 @@ pub enum Layout {
Selection,
HelpMenu,
SortAndFilter,
CustomContent {
title: Option<String>,
body: ContentBody,
},
Static(CustomPanel),
Dynamic(String),
Horizontal {
config: LayoutOptions,
splits: Vec<Layout>,
@ -126,6 +117,9 @@ pub enum Layout {
config: LayoutOptions,
splits: Vec<Layout>,
},
/// For compatibility only. A better choice is Static or Dymanic layout.
CustomContent(CustomContent),
}
impl Default for Layout {
@ -640,7 +634,7 @@ impl NodeUiMetadata {
}
}
fn block<'a>(config: PanelUiConfig, default_title: String) -> Block<'a> {
pub fn block<'a>(config: PanelUiConfig, default_title: String) -> Block<'a> {
Block::default()
.borders(TuiBorders::from_bits_truncate(
config
@ -770,7 +764,7 @@ fn draw_table<B: Backend>(
.filter_map(|c| {
c.format.as_ref().map(|f| {
let out = lua::call(lua, f, v.clone())
.unwrap_or_else(|e| e.to_string());
.unwrap_or_else(|e| format!("{e:?}"));
string_to_text(out)
})
})
@ -876,8 +870,8 @@ fn draw_selection<B: Backend>(
.as_ref()
.map(|f| {
lua::serialize::<Node>(lua, n)
.map(|n| lua::call(lua, f, n).unwrap_or_else(|e| e.to_string()))
.unwrap_or_else(|e| e.to_string())
.and_then(|n| lua::call(lua, f, n))
.unwrap_or_else(|e| format!("{e:?}"))
})
.unwrap_or_else(|| n.absolute_path.clone());
string_to_text(out)
@ -1211,94 +1205,68 @@ pub fn draw_nothing<B: Backend>(
f.render_widget(nothing, layout_size);
}
pub fn draw_custom_content<B: Backend>(
pub fn draw_dynamic<B: Backend>(
f: &mut Frame<B>,
screen_size: TuiRect,
layout_size: TuiRect,
app: &app::App,
title: Option<String>,
body: ContentBody,
func: &str,
lua: &Lua,
) {
let config = app.config.general.panel_ui.default.clone();
match body {
ContentBody::StaticParagraph { render } => {
let render = string_to_text(render);
let content = Paragraph::new(render).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::DynamicParagraph { render } => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let render = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg).unwrap_or_else(|e| format!("{e:?}"))
})
.unwrap_or_else(|e| e.to_string());
let render = string_to_text(render);
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let content = Paragraph::new(render).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
let panel: CustomPanel = lua::serialize(lua, &ctx)
.and_then(|arg| lua::call(lua, func, arg))
.unwrap_or_else(|e| CustomPanel::Paragraph {
ui: app.config.general.panel_ui.default.clone(),
body: format!("{e:?}"),
});
ContentBody::StaticList { render } => {
let items = render
.into_iter()
.map(string_to_text)
.map(ListItem::new)
.collect::<Vec<ListItem>>();
draw_static(f, screen_size, layout_size, app, panel, lua);
}
let content = List::new(items).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
pub fn draw_static<B: Backend>(
f: &mut Frame<B>,
screen_size: TuiRect,
layout_size: TuiRect,
app: &app::App,
panel: CustomPanel,
_lua: &Lua,
) {
let defaultui = app.config.general.panel_ui.default.clone();
match panel {
CustomPanel::Paragraph { ui, body } => {
let config = defaultui.extend(&ui);
let body = string_to_text(body);
let content = Paragraph::new(body).block(block(config, "".into()));
f.render_widget(content, layout_size);
}
ContentBody::DynamicList { render } => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
CustomPanel::List { ui, body } => {
let config = defaultui.extend(&ui);
let items = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![format!("{e:?}")])
})
.unwrap_or_else(|e| vec![e.to_string()])
let items = body
.into_iter()
.map(string_to_text)
.map(ListItem::new)
.collect::<Vec<ListItem>>();
let content = List::new(items).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
let content = List::new(items).block(block(config, "".into()));
f.render_widget(content, layout_size);
}
ContentBody::StaticTable {
CustomPanel::Table {
ui,
widths,
col_spacing,
render,
body,
} => {
let rows = render
let config = defaultui.extend(&ui);
let rows = body
.into_iter()
.map(|cols| {
Row::new(
@ -1318,55 +1286,7 @@ pub fn draw_custom_content<B: Backend>(
let content = Table::new(rows)
.widths(&widths)
.column_spacing(col_spacing.unwrap_or(1))
.block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
f.render_widget(content, layout_size);
}
ContentBody::DynamicTable {
widths,
col_spacing,
render,
} => {
let ctx = ContentRendererArg {
app: app.to_lua_ctx_light(),
layout_size: layout_size.into(),
screen_size: screen_size.into(),
};
let rows = lua::serialize(lua, &ctx)
.map(|arg| {
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![vec![format!("{e:?}")]])
})
.unwrap_or_else(|e| vec![vec![e.to_string()]])
.into_iter()
.map(|cols| {
Row::new(
cols.into_iter()
.map(string_to_text)
.map(Cell::from)
.collect::<Vec<Cell>>(),
)
})
.collect::<Vec<Row>>();
let widths = widths
.into_iter()
.map(|w| w.to_tui(screen_size, layout_size))
.collect::<Vec<TuiConstraint>>();
let mut content = Table::new(rows).widths(&widths).block(block(
config,
title.map(|t| format!(" {t} ")).unwrap_or_default(),
));
if let Some(col_spacing) = col_spacing {
content = content.column_spacing(col_spacing);
};
.block(block(config, "".into()));
f.render_widget(content, layout_size);
}
@ -1394,9 +1314,9 @@ impl From<TuiRect> for Rect {
#[derive(Debug, Clone, Serialize)]
pub struct ContentRendererArg {
app: app::LuaContextLight,
screen_size: Rect,
layout_size: Rect,
pub app: app::LuaContextLight,
pub screen_size: Rect,
pub layout_size: Rect,
}
pub fn draw_layout<B: Backend>(
@ -1422,8 +1342,14 @@ pub fn draw_layout<B: Backend>(
draw_logs(f, screen_size, layout_size, app, lua);
};
}
Layout::CustomContent { title, body } => {
draw_custom_content(f, screen_size, layout_size, app, title, body, lua)
Layout::Static(panel) => {
draw_static(f, screen_size, layout_size, app, panel, lua)
}
Layout::Dynamic(ref func) => {
draw_dynamic(f, screen_size, layout_size, app, func, lua)
}
Layout::CustomContent(content) => {
draw_custom_content(f, screen_size, layout_size, app, content, lua)
}
Layout::Horizontal { config, splits } => {
let chunks = TuiLayout::default()

Loading…
Cancel
Save