Current section
Files
Jump to
Current section
Files
lib/layouts/components/button.ex
defmodule LayoutOMatic.Layouts.Components.Button do
# Buttons size based on :button_font_size with 20 being the default; width/height override
@default_font_size 20
@default_font :roboto
def translate(
%{
component: component,
starting_xy: starting_xy,
grid_xy: grid_xy,
max_xy: max_xy,
padding: padding
} = layout
) do
{_, text} = Map.get(component, :data)
# %{padding_top: padding_top, padding_bottom: padding_bottom, padding_right: padding_right, padding_left: padding_left} =
# case List.first(padding) do
# {padding: padding_values} ->
# end
%{height: requested_height, width: requested_width, button_font_size: font_size} =
case Map.get(component, :styles) do
map when map_size(map) == 3 ->
map
map when map_size(map) == 2 ->
Map.put(map, :button_font_size, @default_font_size)
end
{starting_x, starting_y} = starting_xy
{grid_x, grid_y} = grid_xy
metrics = get_font_metrics(text, font_size)
height = get_height(requested_height, metrics)
width = get_width(requested_width, metrics)
case starting_xy == grid_xy do
true ->
layout = Map.put(layout, :starting_xy, {starting_x + width, starting_y})
{:ok, {starting_x, starting_y}, layout}
false ->
# already in a new group, use starting_xy
case fits_in_x?(starting_x + width, max_xy) do
# fits in x
true ->
# fit in y?
case fits_in_y?(starting_y + height, max_xy) do
true ->
# fits
layout = Map.put(layout, :starting_xy, {starting_x + width, starting_y})
{:ok, {starting_x, starting_y}, layout}
# Does not fit
false ->
{:error, "Does not fit in grid"}
end
# doesnt fit in x
false ->
# fit in new y?
new_y = grid_y + height
case fits_in_y?(new_y, max_xy) do
# fits in new y, check x
true ->
new_layout =
layout
|> Map.put(:grid_xy, {grid_x, new_y})
|> Map.put(:starting_xy, {width, new_y})
{:ok, {grid_x, new_y}, new_layout}
false ->
{:error, "Does not fit in the grid"}
end
end
end
end
defp get_width(width, %{fm_width: fm_width, ascent: ascent}) do
case width do
nil -> fm_width + ascent + ascent
:auto -> fm_width + ascent + ascent
width when is_number(width) and width > 0 -> width
end
end
defp get_height(height, %{font_size: font_size, ascent: ascent}) do
case height do
nil -> font_size + ascent
:auto -> font_size + ascent
height when is_number(height) and height > 0 -> height
end
end
def get_font_metrics(text, font_size) do
font_size = font_size || @default_font_size
fm = Scenic.Cache.Static.FontMetrics.get!(@default_font)
ascent = FontMetrics.ascent(font_size, fm)
fm_width = FontMetrics.width(text, font_size, fm)
%{font_size: font_size, ascent: ascent, fm_width: fm_width}
end
def fits_in_x?(potential_x, {max_x, _}),
do: potential_x <= max_x
def fits_in_y?(potential_y, {_, max_y}),
do: potential_y <= max_y
end