defmodule FloUI.Modal.ScrollLayout do
@moduledoc """
## Usage in SnapFramework
Scrolling layout modal component. Great for displaying content within a modal that needs to scroll.
data is a tuple in the form of ` elixir {label, component, component_data, component_opts}`
style opts
`width: :integer`
`height: :integer`
`frame_width: :integer`
`frame_height: :integer`
`content_height: :integer`
`content_width: :integer`
`show_check: :boolean`
`show_close: :boolean`
``` elixir
<%= graph font_size: 20 %>
<%= component FloUI.Modal.ScrollLayout,
{"Label", FloUI.SelectionList, {@selection_list, @selected}, [id: :project_list]},
id: :scroll_layout,
width: 500,
height: 520,
frame_width: 480,
frame_height: 500,
content_width: 480,
content_height: @content_height,
show_check: true,
show_close: true
%>
```
"""
use Scenic.Component
alias Scenic.Graph
import Scenic.Primitives
alias FloUI.Theme
alias FloUI.Modal.Body
alias FloUI.Modal.Header
import FloUI.Scrollable.Components
@graph Graph.build(font_size: 16)
def validate(nil), do: :invalid_data
def validate(data), do: {:ok, data}
def init(scene, {title, cmp, data, cmp_opts}, opts) do
scene =
assign(scene,
graph: @graph,
title: title,
component: cmp,
component_data: data,
component_opts: cmp_opts,
width: opts[:width] || 500,
height: opts[:height] || 500,
frame_width: opts[:frame_width] || 480,
frame_height: opts[:frame_height] || 500,
content_width: opts[:content_width] || 500,
content_height: opts[:content_height] || 500,
show_check: opts[:show_check] || false,
show_close: opts[:show_close] || false
)
|> render_layout
{:ok, scene}
end
def handle_event({:click, :btn_check}, _from, scene) do
send_parent_event(scene, :modal_done)
{:noreply, scene}
end
def handle_event({:click, :btn_close}, _from, scene) do
send_parent_event(scene, :modal_close)
{:noreply, scene}
end
def handle_event(event, _, scene) do
{:cont, event, scene}
end
defp render_layout(%{
assigns: %{
graph: graph,
title: title,
component: cmp,
component_data: cmp_data,
component_opts: cmp_opts,
width: width,
height: height,
frame_width: frame_width,
frame_height: frame_height,
content_width: content_width,
content_height: content_height,
show_check: show_check,
show_close: show_close
}
} = scene) do
graph =
graph
|> Body.add_to_graph(nil, translate: {0, 50}, width: width, height: height)
|> scrollable(
%{
frame: {frame_width, frame_height},
content: %{x: 0, y: 10, width: content_width, height: content_height}
},
&cmp.add_to_graph(&1, cmp_data, cmp_opts),
id: :scroll_box,
translate: {0, 60},
vertical_scroll_bar: [
scroll_buttons: true,
scroll_bar_theme: Scenic.Primitive.Style.Theme.preset(:dark),
scroll_bar_thickness: 15
]
)
|> Header.add_to_graph(title, width: width, show_check: show_check, show_close: show_close)
assign(scene, graph: graph)
|> push_graph(graph)
end
end