Plot layout Views on grid #10
@@ -33,13 +33,41 @@ pub type Node {
|
||||
Cell(content: String, style: Style)
|
||||
}
|
||||
|
||||
pub type ViewIdx =
|
||||
Int
|
||||
|
||||
pub type View =
|
||||
dict.Dict(Section, Node)
|
||||
|
||||
// Layout consists of a list Views, and only one View is rendered at a time
|
||||
pub type Layout {
|
||||
Layout(columns: Int, rows: Int, nodes: dict.Dict(Section, Node))
|
||||
Layout(
|
||||
columns: Int,
|
||||
rows: Int,
|
||||
current_view: ViewIdx,
|
||||
views: dict.Dict(ViewIdx, View),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(columns: Int, rows: Int, nodes: List(#(Section, Node))) -> Layout {
|
||||
pub fn new(
|
||||
columns: Int,
|
||||
rows: Int,
|
||||
views: List(List(#(Section, Node))),
|
||||
) -> Layout {
|
||||
let views =
|
||||
list.index_map(views, fn(view_nodes, i) { #(i, view_nodes) })
|
||||
|> list.fold(dict.new(), fn(view_acc, iv) {
|
||||
let #(i, view_nodes) = iv
|
||||
|
||||
dict.insert(view_acc, i, view_loop(i, view_nodes))
|
||||
})
|
||||
|
||||
Layout(columns:, rows:, current_view: 0, views:)
|
||||
}
|
||||
|
||||
fn view_loop(i: ViewIdx, view_nodes: List(#(Section, Node))) -> View {
|
||||
let children =
|
||||
nodes
|
||||
view_nodes
|
||||
|> list.flat_map(fn(node) {
|
||||
case pair.second(node) {
|
||||
Row(children: c, ..) -> c
|
||||
@@ -51,22 +79,19 @@ pub fn new(columns: Int, rows: Int, nodes: List(#(Section, Node))) -> Layout {
|
||||
// All sections that are not children of other nodes will be added as
|
||||
// children to the root
|
||||
let orphans =
|
||||
nodes
|
||||
view_nodes
|
||||
|> list.map(pair.first)
|
||||
|> list.filter(fn(node) { !set.contains(children, node) })
|
||||
|
||||
let nodes =
|
||||
dict.from_list(nodes)
|
||||
|> dict.insert(
|
||||
Section(root_section),
|
||||
Row(
|
||||
content: "",
|
||||
style: Style(dimensions: Percent(width: 100, height: 100)),
|
||||
children: orphans,
|
||||
),
|
||||
)
|
||||
|
||||
Layout(columns:, rows:, nodes:)
|
||||
dict.from_list(view_nodes)
|
||||
|> dict.insert(
|
||||
Section(string.append("view_", string.inspect(i))),
|
||||
Row(
|
||||
content: "",
|
||||
style: Style(dimensions: Percent(width: 100, height: 100)),
|
||||
children: orphans,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn update_section(
|
||||
@@ -74,16 +99,25 @@ pub fn update_section(
|
||||
section: Section,
|
||||
content: String,
|
||||
) -> Layout {
|
||||
case dict.get(layout.nodes, section) {
|
||||
case dict.get(layout.views, layout.current_view) {
|
||||
Error(_) -> layout
|
||||
Ok(node) -> {
|
||||
let updated = case node {
|
||||
Cell(..) -> Cell(..node, content: content)
|
||||
Row(..) -> Row(..node, content: content)
|
||||
}
|
||||
Ok(view) ->
|
||||
case dict.get(view, section) {
|
||||
Error(_) -> layout
|
||||
Ok(node) -> {
|
||||
let updated_node = case node {
|
||||
Cell(..) -> Cell(..node, content: content)
|
||||
Row(..) -> Row(..node, content: content)
|
||||
}
|
||||
|
||||
Layout(..layout, nodes: dict.insert(layout.nodes, section, updated))
|
||||
}
|
||||
let updated_view = dict.insert(view, section, updated_node)
|
||||
|
||||
Layout(
|
||||
..layout,
|
||||
views: dict.insert(layout.views, layout.current_view, updated_view),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,11 +141,21 @@ pub fn render(layout: Layout) -> Nil {
|
||||
position_index: 0,
|
||||
)
|
||||
|
||||
let buffer: Buffer = dict.new()
|
||||
case dict.get(layout.views, layout.current_view) {
|
||||
Error(_) -> Nil
|
||||
Ok(view) -> {
|
||||
let buffer: Buffer = dict.new()
|
||||
|
||||
render_loop(layout, context, Section(root_section), buffer)
|
||||
|> plot.flush_buffer(layout.columns, layout.rows)
|
||||
|> internal.update
|
||||
render_loop(
|
||||
view,
|
||||
context,
|
||||
Section(string.append("view_", string.inspect(layout.current_view))),
|
||||
buffer,
|
||||
)
|
||||
|> plot.flush_buffer(layout.columns, layout.rows)
|
||||
|> internal.update
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type RenderContext {
|
||||
@@ -125,12 +169,12 @@ pub type RenderContext {
|
||||
}
|
||||
|
||||
pub fn render_loop(
|
||||
layout: Layout,
|
||||
view: View,
|
||||
context: RenderContext,
|
||||
from: Section,
|
||||
buffer: Buffer,
|
||||
) -> Buffer {
|
||||
case dict.get(layout.nodes, from) {
|
||||
case dict.get(view, from) {
|
||||
Error(_) -> buffer
|
||||
Ok(node) -> {
|
||||
// Margin between container and the node being rendered
|
||||
@@ -193,7 +237,7 @@ pub fn render_loop(
|
||||
position_index: i,
|
||||
)
|
||||
|
||||
render_loop(layout, context, child, acc_buffer)
|
||||
render_loop(view, context, child, acc_buffer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,41 +16,43 @@ pub fn main() {
|
||||
/// First row has two cells
|
||||
/// Second row has no cells
|
||||
fn two_rows_with_cells(columns: Int, rows: Int) -> layout.Layout {
|
||||
let nodes = [
|
||||
#(
|
||||
Section("Row1"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [
|
||||
Section("A"),
|
||||
Section("B"),
|
||||
],
|
||||
let views = [
|
||||
[
|
||||
#(
|
||||
Section("Row1"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [
|
||||
Section("A"),
|
||||
Section("B"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("A"),
|
||||
layout.Cell(
|
||||
content: "cell 1",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
#(
|
||||
Section("A"),
|
||||
layout.Cell(
|
||||
content: "cell 1",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("B"),
|
||||
layout.Cell(
|
||||
content: "cell 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
#(
|
||||
Section("B"),
|
||||
layout.Cell(
|
||||
content: "cell 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("Row2"),
|
||||
layout.Row(
|
||||
content: "row 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
children: [],
|
||||
#(
|
||||
Section("Row2"),
|
||||
layout.Row(
|
||||
content: "row 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 50)),
|
||||
children: [],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
]
|
||||
|
||||
layout.new(columns, rows, nodes)
|
||||
layout.new(columns, rows, views)
|
||||
}
|
||||
|
||||
@@ -19,30 +19,41 @@ pub fn new() -> Result(Subject(Control), String) {
|
||||
|
||||
let layout =
|
||||
[
|
||||
#(
|
||||
layout.Header,
|
||||
layout.Row(
|
||||
content: "Foo (1) | Bar (2) | Baz (3)",
|
||||
style: layout.Style(dimensions: layout.Percent(width: 100, height: 33)),
|
||||
children: [],
|
||||
[
|
||||
#(
|
||||
layout.Header,
|
||||
layout.Row(
|
||||
content: "Foo (1) | Bar (2) | Baz (3)",
|
||||
style: layout.Style(dimensions: layout.Percent(
|
||||
width: 100,
|
||||
height: 33,
|
||||
)),
|
||||
children: [],
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
layout.Search,
|
||||
layout.Row(
|
||||
content: "",
|
||||
style: layout.Style(dimensions: layout.Percent(width: 100, height: 33)),
|
||||
children: [],
|
||||
#(
|
||||
layout.Search,
|
||||
layout.Row(
|
||||
content: "",
|
||||
style: layout.Style(dimensions: layout.Percent(
|
||||
width: 100,
|
||||
height: 33,
|
||||
)),
|
||||
children: [],
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
layout.PlaybackTime,
|
||||
layout.Row(
|
||||
content: "00:00",
|
||||
style: layout.Style(dimensions: layout.Percent(width: 100, height: 33)),
|
||||
children: [],
|
||||
#(
|
||||
layout.PlaybackTime,
|
||||
layout.Row(
|
||||
content: "00:00",
|
||||
style: layout.Style(dimensions: layout.Percent(
|
||||
width: 100,
|
||||
height: 33,
|
||||
)),
|
||||
children: [],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
]
|
||||
|> layout.new(0, 0, _)
|
||||
|
||||
|
||||
@@ -12,45 +12,47 @@ pub fn main() -> Nil {
|
||||
}
|
||||
|
||||
pub fn percent_layout_test() {
|
||||
let nodes = [
|
||||
#(
|
||||
Section("Row1"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [
|
||||
Section("A"),
|
||||
Section("B"),
|
||||
],
|
||||
let views = [
|
||||
[
|
||||
#(
|
||||
Section("Row1"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [
|
||||
Section("A"),
|
||||
Section("B"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("A"),
|
||||
layout.Cell(
|
||||
content: "cell 1",
|
||||
style: Style(dimensions: Percent(width: 50, height: 100)),
|
||||
#(
|
||||
Section("A"),
|
||||
layout.Cell(
|
||||
content: "cell 1",
|
||||
style: Style(dimensions: Percent(width: 50, height: 100)),
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("B"),
|
||||
layout.Cell(
|
||||
content: "cell 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 100)),
|
||||
#(
|
||||
Section("B"),
|
||||
layout.Cell(
|
||||
content: "cell 2",
|
||||
style: Style(dimensions: Percent(width: 50, height: 100)),
|
||||
),
|
||||
),
|
||||
),
|
||||
#(
|
||||
Section("Row2"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [],
|
||||
#(
|
||||
Section("Row2"),
|
||||
layout.Row(
|
||||
content: "row 1",
|
||||
style: Style(dimensions: Percent(width: 100, height: 50)),
|
||||
children: [],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
]
|
||||
|
||||
let columns = 80
|
||||
let rows = 20
|
||||
let layout = layout.new(columns, rows, nodes)
|
||||
let layout = layout.new(columns, rows, views)
|
||||
|
||||
let expected =
|
||||
"
|
||||
@@ -87,11 +89,13 @@ pub fn percent_layout_test() {
|
||||
position_index: 0,
|
||||
)
|
||||
|
||||
let assert Ok(view) = dict.get(layout.views, layout.current_view)
|
||||
|
||||
let flushed =
|
||||
layout.render_loop(
|
||||
layout,
|
||||
view,
|
||||
context,
|
||||
Section(layout.root_section),
|
||||
Section(string.append("view_", string.inspect(layout.current_view))),
|
||||
dict.new(),
|
||||
)
|
||||
|> plot.flush_buffer(layout.columns, layout.rows)
|
||||
|
||||
Reference in New Issue
Block a user