diff --git a/frontend/ui/widget/container/framecontainer.lua b/frontend/ui/widget/container/framecontainer.lua index 5e5a2ce1f..cc5ecad1d 100644 --- a/frontend/ui/widget/container/framecontainer.lua +++ b/frontend/ui/widget/container/framecontainer.lua @@ -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 diff --git a/frontend/ui/widget/container/leftcontainer.lua b/frontend/ui/widget/container/leftcontainer.lua index d1f1837e4..635e2e517 100644 --- a/frontend/ui/widget/container/leftcontainer.lua +++ b/frontend/ui/widget/container/leftcontainer.lua @@ -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 diff --git a/frontend/ui/widget/container/rightcontainer.lua b/frontend/ui/widget/container/rightcontainer.lua index 605c0d9e3..f86dc221a 100644 --- a/frontend/ui/widget/container/rightcontainer.lua +++ b/frontend/ui/widget/container/rightcontainer.lua @@ -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 diff --git a/frontend/ui/widget/horizontalgroup.lua b/frontend/ui/widget/horizontalgroup.lua index 907428fb0..23931a4a2 100644 --- a/frontend/ui/widget/horizontalgroup.lua +++ b/frontend/ui/widget/horizontalgroup.lua @@ -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() diff --git a/frontend/ui/widget/overlapgroup.lua b/frontend/ui/widget/overlapgroup.lua index b5076693b..1865215cc 100644 --- a/frontend/ui/widget/overlapgroup.lua +++ b/frontend/ui/widget/overlapgroup.lua @@ -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]) diff --git a/frontend/ui/widget/progresswidget.lua b/frontend/ui/widget/progresswidget.lua index 8d8aa007d..d747f92ff 100644 --- a/frontend/ui/widget/progresswidget.lua +++ b/frontend/ui/widget/progresswidget.lua @@ -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 diff --git a/frontend/ui/widget/verticalgroup.lua b/frontend/ui/widget/verticalgroup.lua index db0c5f1d4..d34419cc5 100644 --- a/frontend/ui/widget/verticalgroup.lua +++ b/frontend/ui/widget/verticalgroup.lua @@ -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) diff --git a/frontend/util.lua b/frontend/util.lua index 03529bdf1..bf3113f93 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -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