diff --git a/src/musicplayer/ui/layout.gleam b/src/musicplayer/ui/layout.gleam index 0b83862..c7b9993 100644 --- a/src/musicplayer/ui/layout.gleam +++ b/src/musicplayer/ui/layout.gleam @@ -18,8 +18,13 @@ pub type Section { PlaybackTime } +pub type Dimension { + Percent(width: Int, height: Int) + Flex +} + pub type Style { - Style(width_percent: Int, height_percent: Int) + Style(dimensions: Dimension) } /// A Nodes width and height is in percentage (of the available width/height of its parent Node) @@ -28,6 +33,7 @@ pub type Node { Cell(content: String, style: Style) } +/// The root node must use `Root` section pub type Layout { Layout(width: Int, height: Int, nodes: dict.Dict(Section, Node)) } @@ -39,7 +45,7 @@ pub fn new() -> Layout { Root, Row( content: "Music Player", - style: Style(width_percent: 100, height_percent: 100), + style: Style(dimensions: Percent(width: 100, height: 100)), children: [Header, Search, PlaybackTime], ), ), @@ -47,7 +53,7 @@ pub fn new() -> Layout { Header, Row( content: "Foo (1) | Bar (2) | Baz (3)", - style: Style(width_percent: 100, height_percent: 33), + style: Style(dimensions: Percent(width: 100, height: 33)), children: [], ), ), @@ -55,7 +61,7 @@ pub fn new() -> Layout { Search, Row( content: "", - style: Style(width_percent: 100, height_percent: 33), + style: Style(dimensions: Percent(width: 100, height: 33)), children: [], ), ), @@ -63,7 +69,7 @@ pub fn new() -> Layout { PlaybackTime, Row( content: "00:00", - style: Style(width_percent: 100, height_percent: 33), + style: Style(dimensions: Percent(width: 100, height: 33)), children: [], ), ), @@ -95,6 +101,7 @@ pub fn update_dimensions(layout: Layout, width: Int, height: Int) -> Layout { pub fn render(layout: Layout) -> Nil { internal.clear_screen() + [layout.width, layout.height] |> list.map(int.to_string) |> string.join(" ") @@ -157,15 +164,22 @@ pub fn render_generic( Ok(node) -> { let margin = 2.0 - let width = - container_width *. { int.to_float(node.style.width_percent) /. 100.0 } - |> float.floor - |> float.truncate + let #(width, height) = case node.style.dimensions { + Flex -> todo + Percent(width:, height:) -> { + let width = + container_width *. { int.to_float(width) /. 100.0 } + |> float.floor + |> float.truncate - let height = - container_height *. { int.to_float(node.style.height_percent) /. 100.0 } - |> float.floor - |> float.truncate + let height = + container_height *. { int.to_float(height) /. 100.0 } + |> float.floor + |> float.truncate + + #(width, height) + } + } let #(cx, cy) = case node { Row(..) -> #(container_tl_x, container_tl_y + { index * height }) @@ -185,25 +199,30 @@ pub fn render_generic( |> list.fold(parent, fn(acc_into, ic) { let #(i, child) = ic - let cw = - container_width - *. { int.to_float(node.style.width_percent) /. 100.0 } - -. margin - |> float.floor + let #(width, height) = case node.style.dimensions { + Flex -> todo + Percent(width:, height:) -> { + let width = + container_width *. { int.to_float(width) /. 100.0 } -. margin + |> float.floor - let ch = - container_height - *. { int.to_float(node.style.height_percent) /. 100.0 } - -. margin - |> float.floor + let height = + container_height + *. { int.to_float(height) /. 100.0 } + -. margin + |> float.floor + + #(width, height) + } + } let child_origin_x = container_tl_x + 1 let child_origin_y = container_tl_y + 1 render_generic( layout, - cw, - ch, + width, + height, child_origin_x, child_origin_y, i, diff --git a/src/musicplayer/ui/layout_examples/layout_examples.gleam b/src/musicplayer/ui/layout_examples/layout_examples.gleam index 6c93217..d231a79 100644 --- a/src/musicplayer/ui/layout_examples/layout_examples.gleam +++ b/src/musicplayer/ui/layout_examples/layout_examples.gleam @@ -1,7 +1,7 @@ import gleam/dict import musicplayer/ui/internal -import musicplayer/ui/layout.{Layout, Section, Style} +import musicplayer/ui/layout.{Layout, Percent, Section, Style} import musicplayer/ui/layout_examples/wait_for_input.{wait_for_input} pub fn main() { @@ -21,10 +21,10 @@ fn two_rows_with_cells(width: Int, height: Int) -> layout.Layout { let nodes = dict.from_list([ #( - Section("Root"), + layout.Root, layout.Row( content: "container", - style: Style(width_percent: 100, height_percent: 100), + style: Style(dimensions: Percent(width: 100, height: 100)), children: [ Section("Row1"), Section("Row2"), @@ -35,7 +35,7 @@ fn two_rows_with_cells(width: Int, height: Int) -> layout.Layout { Section("Row1"), layout.Row( content: "row 1", - style: Style(width_percent: 100, height_percent: 50), + style: Style(dimensions: Percent(width: 100, height: 50)), children: [ Section("A"), Section("A"), @@ -46,21 +46,21 @@ fn two_rows_with_cells(width: Int, height: Int) -> layout.Layout { Section("A"), layout.Cell( content: "cell 1", - style: Style(width_percent: 50, height_percent: 100), + style: Style(dimensions: Percent(width: 50, height: 50)), ), ), #( Section("B"), layout.Cell( content: "cell 2", - style: Style(width_percent: 50, height_percent: 100), + style: Style(dimensions: Percent(width: 50, height: 50)), ), ), #( Section("Row2"), layout.Row( content: "row 2", - style: Style(width_percent: 100, height_percent: 50), + style: Style(dimensions: Percent(width: 50, height: 50)), children: [], ), ), diff --git a/test/musicplayer/ui/layout_test.gleam b/test/musicplayer/ui/layout_test.gleam index 433c751..15c8472 100644 --- a/test/musicplayer/ui/layout_test.gleam +++ b/test/musicplayer/ui/layout_test.gleam @@ -5,23 +5,23 @@ import gleeunit import gleeunit/should import musicplayer/ui/virtual_ansi -import musicplayer/ui/layout.{Layout, Section, Style} +import musicplayer/ui/layout.{Layout, Percent, Section, Style} pub fn main() -> Nil { gleeunit.main() } -pub fn foo_test() { +pub fn percent_layout_test() { let layout = Layout( width: 80, height: 20, nodes: dict.from_list([ #( - Section("Root"), + layout.Root, layout.Row( content: "container", - style: Style(width_percent: 100, height_percent: 100), + style: Style(dimensions: Percent(width: 100, height: 100)), children: [ Section("Row1"), Section("Row2"), @@ -32,7 +32,7 @@ pub fn foo_test() { Section("Row1"), layout.Row( content: "row 1", - style: Style(width_percent: 100, height_percent: 50), + style: Style(dimensions: Percent(width: 100, height: 50)), children: [ Section("A"), Section("B"), @@ -43,21 +43,21 @@ pub fn foo_test() { Section("A"), layout.Cell( content: "cell 1", - style: Style(width_percent: 50, height_percent: 100), + style: Style(dimensions: Percent(width: 50, height: 100)), ), ), #( Section("B"), layout.Cell( content: "cell 2", - style: Style(width_percent: 50, height_percent: 100), + style: Style(dimensions: Percent(width: 50, height: 100)), ), ), #( Section("Row2"), layout.Row( content: "row 1", - style: Style(width_percent: 100, height_percent: 50), + style: Style(dimensions: Percent(width: 100, height: 50)), children: [], ), ), @@ -88,8 +88,7 @@ container─────────────────────── └──────────────────────────────────────────────────────────────────────────────┘ " - let visual = - virtual_ansi.render(layout, Section("Root"), layout.width, layout.height) + let visual = virtual_ansi.render(layout) case visual == string.trim(expected) { True -> Nil False -> { diff --git a/test/musicplayer/ui/virtual_ansi.gleam b/test/musicplayer/ui/virtual_ansi.gleam index ad8c692..525ee2a 100644 --- a/test/musicplayer/ui/virtual_ansi.gleam +++ b/test/musicplayer/ui/virtual_ansi.gleam @@ -3,12 +3,12 @@ import gleam/int import gleam/list import gleam/string -import musicplayer/ui/layout.{type Layout, type Section, Renders} +import musicplayer/ui/layout.{type Layout, Renders} pub type Screen = dict.Dict(#(Int, Int), String) -pub fn render(layout: Layout, root: Section, width: Int, height: Int) -> String { +pub fn render(layout: Layout) -> String { let test_renders = Renders( box: fn(screen, x, y, w, h) { box(screen, x, y, w, h) }, @@ -18,12 +18,12 @@ pub fn render(layout: Layout, root: Section, width: Int, height: Int) -> String let screen = layout.render_generic( layout, - int.to_float(width), - int.to_float(height), + int.to_float(layout.width), + int.to_float(layout.height), 1, 1, 0, - root, + layout.Root, dict.new(), test_renders, )