[RTL UI] update low-level widgets to handle mirroring

These updated low-level widgets will handle 90%
of the needed UI mirroring.
reviewable/pr5680/r1
poire-z 4 years ago
parent d6d49a64a7
commit 36ce82d8c2

@ -18,6 +18,7 @@ Example:
--]]
local BD = require("ui/bidi")
local Blitbuffer = require("ffi/blitbuffer")
local Geom = require("ui/geometry")
local Size = require("ui/size")
@ -38,6 +39,8 @@ local FrameContainer = WidgetContainer:new{
width = nil,
height = nil,
invert = false,
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
}
function FrameContainer:getSize()
@ -46,6 +49,9 @@ function FrameContainer:getSize()
self._padding_right = self.padding_right or self.padding
self._padding_bottom = self.padding_bottom or self.padding
self._padding_left = self.padding_left or self.padding
if self._mirroredUI and self.allow_mirroring then
self._padding_left, self._padding_right = self._padding_right, self._padding_left
end
return Geom:new{
w = content_size.w + ( self.margin + self.bordersize ) * 2 + self._padding_left + self._padding_right,
h = content_size.h + ( self.margin + self.bordersize ) * 2 + self._padding_top + self._padding_bottom
@ -62,6 +68,11 @@ function FrameContainer:paintTo(bb, x, y)
local container_width = self.width or my_size.w
local container_height = self.height or my_size.h
local shift_x = 0
if self._mirroredUI and self.allow_mirroring then
shift_x = container_width - my_size.w
end
--- @todo get rid of margin here? 13.03 2013 (houqp)
if self.background then
bb:paintRoundedRect(x, y,
@ -83,7 +94,7 @@ function FrameContainer:paintTo(bb, x, y)
end
if self[1] then
self[1]:paintTo(bb,
x + self.margin + self.bordersize + self._padding_left,
x + self.margin + self.bordersize + self._padding_left + shift_x,
y + self.margin + self.bordersize + self._padding_top)
end
if self.invert then

@ -2,9 +2,13 @@
LeftContainer aligns its content (1 widget) at the left of its own dimensions
--]]
local BD = require("ui/bidi")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local LeftContainer = WidgetContainer:new()
local LeftContainer = WidgetContainer:new{
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
}
function LeftContainer:paintTo(bb, x, y)
local contentSize = self[1]:getSize()
@ -13,6 +17,9 @@ function LeftContainer:paintTo(bb, x, y)
-- throw error? paint to scrap buffer and blit partially?
-- for now, we ignore this
-- end
if self._mirroredUI and self.allow_mirroring then
x = x + (self.dimen.w - contentSize.w) -- as in RightContainer
end
self[1]:paintTo(bb, x , y + math.floor((self.dimen.h - contentSize.h)/2))
end

@ -2,9 +2,13 @@
RightContainer aligns its content (1 widget) at the right of its own dimensions
--]]
local BD = require("ui/bidi")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local RightContainer = WidgetContainer:new()
local RightContainer = WidgetContainer:new{
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
}
function RightContainer:paintTo(bb, x, y)
local contentSize = self[1]:getSize()
@ -13,8 +17,12 @@ function RightContainer:paintTo(bb, x, y)
-- throw error? paint to scrap buffer and blit partially?
-- for now, we ignore this
-- end
if not self._mirroredUI or not self.allow_mirroring then
x = x + (self.dimen.w - contentSize.w)
-- else: keep x, as in LeftContainer
end
self[1]:paintTo(bb,
x + (self.dimen.w - contentSize.w),
x,
y + math.floor((self.dimen.h - contentSize.h)/2))
end

@ -2,10 +2,14 @@
A layout widget that puts objects besides each other.
--]]
local BD = require("ui/bidi")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local util = require("util")
local HorizontalGroup = WidgetContainer:new{
align = "center",
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
_size = nil,
}
@ -13,6 +17,9 @@ function HorizontalGroup:getSize()
if not self._size then
self._size = { w = 0, h = 0 }
self._offsets = { }
if self._mirroredUI and self.allow_mirroring then
util.arrayReverse(self)
end
for i, widget in ipairs(self) do
local w_size = widget:getSize()
self._offsets[i] = {
@ -24,6 +31,9 @@ function HorizontalGroup:getSize()
self._size.h = w_size.h
end
end
if self._mirroredUI and self.allow_mirroring then
util.arrayReverse(self)
end
end
return self._size
end
@ -31,6 +41,9 @@ end
function HorizontalGroup:paintTo(bb, x, y)
local size = self:getSize()
if self._mirroredUI and self.allow_mirroring then
util.arrayReverse(self)
end
for i, widget in ipairs(self) do
if self.align == "center" then
widget:paintTo(bb,
@ -45,6 +58,9 @@ function HorizontalGroup:paintTo(bb, x, y)
self.align)
end
end
if self._mirroredUI and self.allow_mirroring then
util.arrayReverse(self)
end
end
function HorizontalGroup:clear()

@ -2,9 +2,20 @@
A layout widget that puts objects above each other.
--]]
local BD = require("ui/bidi")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local OverlapGroup = WidgetContainer:new{
-- Note: we default to allow_mirroring = true.
-- When using LeftContainer, RightContainer or HorizontalGroup
-- in an OverlapGroup, mostly when they take the whole width,
-- either OverlapGroup, or all the others, need to have
-- allow_mirroring=false (otherwise, some upper mirroring would
-- cancel a lower one...).
-- It's usually safer to set it to false on the OverlapGroup,
-- but some thinking is needed when many of them are nested.
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
_size = nil,
}
@ -45,10 +56,19 @@ function OverlapGroup:paintTo(bb, x, y)
local size = self:getSize()
for i, wget in ipairs(self) do
local overlap_align = wget.overlap_align
if self._mirroredUI and self.allow_mirroring then
if overlap_align == "right" then
overlap_align = "left"
elseif overlap_align ~= "center" then
overlap_align = "right"
end
-- see if something to do with wget.overlap_offset
end
local wget_size = wget:getSize()
if wget.overlap_align == "right" then
if overlap_align == "right" then
wget:paintTo(bb, x+size.w-wget_size.w, y)
elseif wget.overlap_align == "center" then
elseif overlap_align == "center" then
wget:paintTo(bb, x+math.floor((size.w-wget_size.w)/2), y)
elseif wget.overlap_offset then
wget:paintTo(bb, x+wget.overlap_offset[1], y+wget.overlap_offset[2])

@ -27,6 +27,7 @@ Example:
]]
local BD = require("ui/bidi")
local Blitbuffer = require("ffi/blitbuffer")
local Geom = require("ui/geometry")
local Widget = require("ui/widget/widget")
@ -46,6 +47,9 @@ local ProgressWidget = Widget:new{
ticks = nil,
tick_width = Screen:scaleBySize(3),
last = nil,
fill_from_right = false,
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
}
function ProgressWidget:getSize()
@ -69,17 +73,30 @@ function ProgressWidget:paintTo(bb, x, y)
self.bordersize, self.bordercolor, self.radius)
-- paint percentage infill
if self.percentage >= 0 and self.percentage <= 1 then
bb:paintRect(x+self.margin_h, math.ceil(y+self.margin_v+self.bordersize),
math.ceil((my_size.w-2*self.margin_h)*self.percentage),
my_size.h-2*(self.margin_v+self.bordersize), self.rectcolor)
if self.fill_from_right or (self._mirroredUI and not self.fill_from_right) then
bb:paintRect(x+self.margin_h + math.ceil((my_size.w-2*self.margin_h)*(1-self.percentage)),
math.ceil(y+self.margin_v+self.bordersize),
math.ceil((my_size.w-2*self.margin_h)*self.percentage),
my_size.h-2*(self.margin_v+self.bordersize),
self.rectcolor)
else
bb:paintRect(x+self.margin_h,
math.ceil(y+self.margin_v+self.bordersize),
math.ceil((my_size.w-2*self.margin_h)*self.percentage),
my_size.h-2*(self.margin_v+self.bordersize), self.rectcolor)
end
end
if self.ticks and self.last and self.last > 0 then
local bar_width = (my_size.w-2*self.margin_h)
local y_pos = y + self.margin_v + self.bordersize
local bar_height = my_size.h-2*(self.margin_v+self.bordersize)
for i=1, #self.ticks do
local tick_x = bar_width*(self.ticks[i]/self.last)
if self._mirroredUI then
tick_x = bar_width - tick_x
end
bb:paintRect(
x + bar_width*(self.ticks[i]/self.last) + self.margin_h,
x + self.margin_h + tick_x,
y_pos,
self.tick_width,
bar_height,
@ -92,6 +109,21 @@ function ProgressWidget:setPercentage(percentage)
self.percentage = percentage
end
function ProgressWidget:getPercentageFromPosition(pos)
if not pos or not pos.x then
return nil
end
local width = self.dimen.w - 2*self.margin_h
local x = pos.x - self.dimen.x - self.margin_h
if x < 0 or x > width then
return nil
end
if BD.mirroredUILayout() then
x = width - x
end
return x / width
end
function ProgressWidget:updateStyle(thick, height)
if thick then
if height then

@ -2,12 +2,15 @@
A layout widget that puts objects under each other.
--]]
local BD = require("ui/bidi")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local VerticalGroup = WidgetContainer:new{
align = "center",
allow_mirroring = true,
_mirroredUI = BD.mirroredUILayout(),
_size = nil,
_offsets = {}
_offsets = {},
}
function VerticalGroup:getSize()
@ -31,15 +34,23 @@ end
function VerticalGroup:paintTo(bb, x, y)
local size = self:getSize()
local align = self.align
if self._mirroredUI and self.allow_mirroring then
if align == "left" then
align = "right"
elseif align == "right" then
align = "left"
end
end
for i, widget in ipairs(self) do
if self.align == "center" then
if align == "center" then
widget:paintTo(bb,
x + math.floor((size.w - self._offsets[i].x) / 2),
y + self._offsets[i].y)
elseif self.align == "left" then
elseif align == "left" then
widget:paintTo(bb, x, y + self._offsets[i].y)
elseif self.align == "right" then
elseif align == "right" then
widget:paintTo(bb,
x + size.w - self._offsets[i].x,
y + self._offsets[i].y)

@ -280,6 +280,17 @@ function util.arrayAppend(t1, t2)
end
end
-- Reverse array elements in-place in table t
---- @param t Lua table
function util.arrayReverse(t)
local i, j = 1, #t
while i < j do
t[i], t[j] = t[j], t[i]
i = i + 1
j = j - 1
end
end
-- Merge t2 into t1, overwriting existing elements if they already exist
-- Probably not safe with nested tables (c.f., https://stackoverflow.com/q/1283388)
---- @param t1 Lua table

Loading…
Cancel
Save