diff options
author | Logan Hunt <logan.hunt@usu.edu> | 2023-01-04 15:22:28 -0700 |
---|---|---|
committer | Logan Hunt <logan.hunt@usu.edu> | 2023-01-04 15:22:28 -0700 |
commit | 1536d0192f9bb0490d64d58b4da22d12076a25af (patch) | |
tree | 5cc09ab0fa621efeb8a36c317eb5e53103846f18 /lib/chessh | |
parent | 93ae544684b29db30c6c65a5ba5e7cb51972123c (diff) | |
download | chessh-1536d0192f9bb0490d64d58b4da22d12076a25af.tar.gz chessh-1536d0192f9bb0490d64d58b4da22d12076a25af.zip |
Move to a new state when menu option selected
Diffstat (limited to 'lib/chessh')
-rw-r--r-- | lib/chessh/ssh/client.ex | 9 | ||||
-rw-r--r-- | lib/chessh/ssh/screens/board.ex | 26 | ||||
-rw-r--r-- | lib/chessh/ssh/screens/menu.ex | 72 | ||||
-rw-r--r-- | lib/chessh/ssh/screens/screen.ex | 7 |
4 files changed, 82 insertions, 32 deletions
diff --git a/lib/chessh/ssh/client.ex b/lib/chessh/ssh/client.ex index dfa222c..8dde954 100644 --- a/lib/chessh/ssh/client.ex +++ b/lib/chessh/ssh/client.ex @@ -1,6 +1,6 @@ defmodule Chessh.SSH.Client do alias IO.ANSI - alias Chessh.SSH.Client.Menu + alias Chessh.SSH.Client.{Menu, Board} require Logger use GenServer @@ -98,6 +98,7 @@ defmodule Chessh.SSH.Client do "\e[B" -> :down "\e[D" -> :left "\e[C" -> :right + "\r" -> :return x -> x end end @@ -107,9 +108,9 @@ defmodule Chessh.SSH.Client do Enum.member?(@min_terminal_height..@max_terminal_height, height) end - defp render( - %State{width: width, height: height, state_stack: [{module, _screen_state}]} = state - ) do + def render( + %State{width: width, height: height, state_stack: [{module, _screen_state} | _]} = state + ) do if terminal_size_allowed(width, height) do [ @clear_codes ++ diff --git a/lib/chessh/ssh/screens/board.ex b/lib/chessh/ssh/screens/board.ex index 7b22052..c95049f 100644 --- a/lib/chessh/ssh/screens/board.ex +++ b/lib/chessh/ssh/screens/board.ex @@ -1,14 +1,30 @@ defmodule Chessh.SSH.Client.Board do + alias Chessh.SSH.Client + alias IO.ANSI + + require Logger + + defmodule State do + defstruct cursor_x: 0, + cursor_y: 0 + end + use Chessh.SSH.Client.Screen - alias Chessh.SSH.Client.State - def render(%State{} = _state) do - @ascii_chars["pieces"]["white"]["knight"] + def render(%Client.State{} = _state) do + knight = @ascii_chars["pieces"]["white"]["knight"] + + [ANSI.home()] ++ + Enum.map( + Enum.zip(0..(length(knight) - 1), knight), + fn {i, line} -> + [ANSI.cursor(i, 0), line] + end + ) end - def handle_input(action, state) do + def handle_input(action, %Client.State{} = state) do case action do - "q" -> state _ -> state end end diff --git a/lib/chessh/ssh/screens/menu.ex b/lib/chessh/ssh/screens/menu.ex index 22aba85..f89670f 100644 --- a/lib/chessh/ssh/screens/menu.ex +++ b/lib/chessh/ssh/screens/menu.ex @@ -7,13 +7,13 @@ defmodule Chessh.SSH.Client.Menu do defmodule State do defstruct y: 0, - x: 0 + x: 0, + selected: 0 end use Chessh.SSH.Client.Screen @logo " Simponic's - dP MP\"\"\"\"\"\"`MM MP\"\"\"\"\"\"`MM M\"\"MMMMM\"\"MM 88 M mmmmm..M M mmmmm..M M MMMMM MM .d8888b. 88d888b. .d8888b. M. `YM M. `YM M `M @@ -22,54 +22,80 @@ defmodule Chessh.SSH.Client.Menu do `88888P' dP dP `88888P' Mb. .dM Mb. .dM M MMMMM MM MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM" + @options [ + {"Option 1", {Chessh.SSH.Client.Board, %{}}}, + {"Option 2", {Chessh.SSH.Client.Board, %{}}}, + {"Option 3", {Chessh.SSH.Client.Board, %{}}} + ] + def render(%Client.State{ width: width, height: height, - state_stack: [{_this_module, %State{y: y, x: x}} | _tail] + state_stack: [{_this_module, %State{selected: selected, y: dy, x: dx}} | _tail] }) do + text = String.split(@logo, "\n") {logo_width, logo_height} = Utils.text_dim(@logo) - - split = String.split(@logo, "\n") + {y, x} = center_rect({logo_width, logo_height + length(text)}, {width, height}) Enum.flat_map( - Enum.zip(0..(length(split) - 1), split), + Enum.zip(0..(length(text) - 1), text), fn {i, line} -> [ - ANSI.cursor(div(height - logo_height, 2) + i + y, div(width - logo_width, 2) + x), - "#{line}\n" + ANSI.cursor(y + i + dy, x + dx), + line ] end - ) + ) ++ + Enum.flat_map( + Enum.zip(0..(length(@options) - 1), @options), + fn {i, {option, _}} -> + [ + ANSI.cursor(y + length(text) + i + dy, x + dx), + if(i == selected, do: ANSI.format([:light_cyan, "* #{option}"]), else: option) + ] + end + ) ++ [ANSI.home()] + end + + def wrap_around(index, delta, length) do + calc = index + delta + if(calc < 0, do: length, else: 0) + rem(calc, length) end def handle_input( data, - %Client.State{state_stack: [{this_module, %State{y: y, x: x} = screen_state} | tail]} = - state + %Client.State{ + state_stack: + [{this_module, %State{selected: selected} = screen_state} | tail] = state_stack + } = state ) do - case data do - :left -> + case(data) do + :up -> %Client.State{ state - | state_stack: [{this_module, %State{screen_state | x: x - 1}} | tail] + | state_stack: [ + {this_module, + %State{screen_state | selected: wrap_around(selected, -1, length(@options))}} + | tail + ] } - :right -> + :down -> %Client.State{ state - | state_stack: [{this_module, %State{screen_state | x: x + 1}} | tail] + | state_stack: [ + {this_module, + %State{screen_state | selected: wrap_around(selected, 1, length(@options))}} + | tail + ] } - :up -> - %Client.State{ - state - | state_stack: [{this_module, %State{screen_state | y: y - 1}} | tail] - } + :return -> + {_, new_state} = Enum.at(@options, selected) - :down -> %Client.State{ state - | state_stack: [{this_module, %State{screen_state | y: y + 1}} | tail] + | state_stack: [new_state] ++ state_stack } _ -> diff --git a/lib/chessh/ssh/screens/screen.ex b/lib/chessh/ssh/screens/screen.ex index be6e00e..3d9e9ec 100644 --- a/lib/chessh/ssh/screens/screen.ex +++ b/lib/chessh/ssh/screens/screen.ex @@ -10,6 +10,13 @@ defmodule Chessh.SSH.Client.Screen do @ascii_chars Application.compile_env!(:chessh, :ascii_chars_json_file) |> File.read!() |> Jason.decode!() + + def center_rect({rect_width, rect_height}, {parent_width, parent_height}) do + { + div(parent_height - rect_height, 2), + div(parent_width - rect_width, 2) + } + end end end end |