Skip to content

Commit

Permalink
feat: control gaps now shrink when not enough space
Browse files Browse the repository at this point in the history
closes #740
  • Loading branch information
tomasklaen committed Nov 1, 2023
1 parent 16f61eb commit b8280b0
Showing 1 changed file with 28 additions and 17 deletions.
45 changes: 28 additions & 17 deletions src/uosc/elements/Controls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ local Button = require('elements/Button')
local CycleButton = require('elements/CycleButton')
local Speed = require('elements/Speed')

-- `scale` - `options.controls_size` scale factor.
-- `ratio` - Width/height ratio of a static or dynamic element.
-- `ratio_min` Min ratio for 'dynamic' sized element.
---@alias ControlItem {element?: Element; kind: string; sizing: 'space' | 'static' | 'dynamic'; scale: number; ratio?: number; ratio_min?: number; hide: boolean; dispositions?: table<string, boolean>}
-- sizing:
-- static - shrink, have highest claim on available space, disappear when there's not enough of it
-- dynamic - shrink to make room for static elements until they reach their ratio_min, then disappear
-- gap - shrink if there's no space left
-- space - expands to fill available space, shrinks as needed
-- scale - `options.controls_size` scale factor.
-- ratio - Width/height ratio of a static or dynamic element.
-- ratio_min Min ratio for 'dynamic' sized element.
---@alias ControlItem {element?: Element; kind: string; sizing: 'space' | 'static' | 'dynamic' | 'gap'; scale: number; ratio?: number; ratio_min?: number; hide: boolean; dispositions?: table<string, boolean>}

---@class Controls : Element
local Controls = class(Element)
Expand Down Expand Up @@ -109,7 +114,7 @@ function Controls:init_options()
if kind == 'space' then
control.sizing = 'space'
elseif kind == 'gap' then
table_assign(control, {sizing = 'dynamic', scale = 1, ratio = params[1] or 0.3, ratio_min = 0})
table_assign(control, {sizing = 'gap', scale = 1, ratio = params[1] or 0.3, ratio_min = 0})
elseif kind == 'command' then
if #params ~= 2 then
mp.error(string.format(
Expand Down Expand Up @@ -264,22 +269,24 @@ function Controls:update_dimensions()
self.ax, self.ay = window_border + margin, self.by - size

-- Controls
local available_width = self.bx - self.ax
local statics_width = (#self.layout - 1) * spacing
local available_width, statics_width = self.bx - self.ax, 0
local min_content_width = statics_width
local max_dynamics_width, dynamic_units, spaces = 0, 0, 0
local max_dynamics_width, dynamic_units, spaces, gaps = 0, 0, 0, 0

-- Calculate statics_width, min_content_width, and count spaces
-- Calculate statics_width, min_content_width, and count spaces & gaps
for c, control in ipairs(self.layout) do
if control.sizing == 'space' then
spaces = spaces + 1
elseif control.sizing == 'gap' then
gaps = gaps + control.scale * control.ratio
elseif control.sizing == 'static' then
local width = size * control.scale * control.ratio
local width = size * control.scale * control.ratio + (c ~= #self.layout and spacing or 0)
statics_width = statics_width + width
min_content_width = min_content_width + width
elseif control.sizing == 'dynamic' then
min_content_width = min_content_width + size * control.scale * control.ratio_min
max_dynamics_width = max_dynamics_width + size * control.scale * control.ratio
local spacing = (c ~= #self.layout and spacing or 0)
min_content_width = min_content_width + size * control.scale * control.ratio_min + spacing
max_dynamics_width = max_dynamics_width + size * control.scale * control.ratio + spacing
dynamic_units = dynamic_units + control.scale * control.ratio
end
end
Expand All @@ -291,7 +298,7 @@ function Controls:update_dimensions()
i = i + (a * (a % 2 == 0 and 1 or -1))
local control = self.layout[i]

if control.kind ~= 'gap' and control.kind ~= 'space' then
if control.sizing ~= 'gap' and control.sizing ~= 'space' then
control.hide = true
if control.element then control.element.enabled = false end
if control.sizing == 'static' then
Expand All @@ -300,7 +307,7 @@ function Controls:update_dimensions()
statics_width = statics_width - width - spacing
elseif control.sizing == 'dynamic' then
min_content_width = min_content_width - size * control.scale * control.ratio_min - spacing
max_dynamics_width = max_dynamics_width - size * control.scale * control.ratio
max_dynamics_width = max_dynamics_width - size * control.scale * control.ratio - spacing
dynamic_units = dynamic_units - control.scale * control.ratio
end

Expand All @@ -312,15 +319,19 @@ function Controls:update_dimensions()
-- Lay out the elements
local current_x = self.ax
local width_for_dynamics = available_width - statics_width
local space_width = (width_for_dynamics - max_dynamics_width) / spaces
local empty_space_width = width_for_dynamics - max_dynamics_width
local width_for_gaps = math.min(empty_space_width, size * gaps)
local individual_space_width = spaces > 0 and ((empty_space_width - width_for_gaps) / spaces) or 0

for c, control in ipairs(self.layout) do
if not control.hide then
local sizing, element, scale, ratio = control.sizing, control.element, control.scale, control.ratio
local width, height = 0, 0

if sizing == 'space' then
if space_width > 0 then width = space_width end
if individual_space_width > 0 then width = individual_space_width end
elseif sizing == 'gap' then
if width_for_gaps > 0 then width = width_for_gaps * (ratio / gaps) end
elseif sizing == 'static' then
height = size * scale
width = height * ratio
Expand All @@ -332,7 +343,7 @@ function Controls:update_dimensions()

local bx = current_x + width
if element then element:set_coordinates(round(current_x), round(self.by - height), bx, self.by) end
current_x = bx + spacing
current_x = element and bx + spacing or bx
end
end

Expand Down

0 comments on commit b8280b0

Please # to comment.