diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 513b90fab..9e3c0e622 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Button = require("ui/widget/button") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") @@ -457,9 +458,10 @@ function FileManager:onShowPlusMenu() end function FileManager:onSwipeFM(ges) - if ges.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "west" then self.file_chooser:onNextPage() - elseif ges.direction == "east" then + elseif direction == "east" then self.file_chooser:onPrevPage() end return true diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 3d76d5195..8f362f2e5 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local CenterContainer = require("ui/widget/container/centercontainer") local CloudStorage = require("apps/cloudstorage/cloudstorage") local ConfirmBox = require("ui/widget/confirmbox") @@ -611,10 +612,10 @@ function FileManagerMenu:_getTabIndexFromLocation(ges) return last_tab_index -- if the start position is far right elseif ges.pos.x > 2 * Screen:getWidth() / 3 then - return #self.tab_item_table + return BD.mirroredUILayout() and 1 or #self.tab_item_table -- if the start position is far left elseif ges.pos.x < Screen:getWidth() / 3 then - return 1 + return BD.mirroredUILayout() and #self.tab_item_table or 1 -- if center return the last index else return last_tab_index diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index e9c4f6443..3039c038c 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local CenterContainer = require("ui/widget/container/centercontainer") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -231,7 +232,7 @@ function ReaderBookmark:onShowBookmark() w = Screen:getWidth(), h = Screen:getHeight(), }, - direction = "east" + direction = BD.flipDirectionIfMirroredUILayout("east") } } } diff --git a/frontend/apps/reader/modules/readerdogear.lua b/frontend/apps/reader/modules/readerdogear.lua index 51c562242..5d3898e6d 100644 --- a/frontend/apps/reader/modules/readerdogear.lua +++ b/frontend/apps/reader/modules/readerdogear.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Device = require("device") local Geom = require("ui/geometry") local ImageWidget = require("ui/widget/imagewidget") @@ -33,6 +34,7 @@ function ReaderDogear:setupDogear(new_dogear_size) dimen = Geom:new{w = Screen:getWidth(), h = self.dogear_size}, ImageWidget:new{ file = "resources/icons/dogear.png", + rotation_angle = BD.mirroredUILayout() and 90 or 0, width = self.dogear_size, height = self.dogear_size, } diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index f19b2ad03..8d40b8d7e 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local CenterContainer = require("ui/widget/container/centercontainer") @@ -21,6 +22,7 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer") local util = require("util") local T = require("ffi/util").template local _ = require("gettext") +local C_ = _.pgettext local Screen = Device.screen local MODE = { @@ -41,26 +43,45 @@ local symbol_prefix = { letters = { time = nil, pages_left = "=>", - battery = "B:", - percentage = "R:", - book_time_to_read = "TB:", - chapter_time_to_read = "TC:", - frontlight = "L:", - mem_usage = "M:", - wifi_status = "W:", + battery = C_("FooterLetterPrefix", "B:"), + percentage = C_("FooterLetterPrefix", "R:"), + book_time_to_read = C_("FooterLetterPrefix", "TB:"), + chapter_time_to_read = C_("FooterLetterPrefix", "TC:"), + frontlight = C_("FooterLetterPrefix", "L:"), + mem_usage = C_("FooterLetterPrefix", "M:"), + wifi_status = C_("FooterLetterPrefix", "W:"), }, icons = { time = "⌚", - pages_left = "⇒", + pages_left = BD.mirroredUILayout() and "⇐" or "⇒", battery = "", - percentage = "⤠", + percentage = BD.mirroredUILayout() and "⤟" or "⤠", book_time_to_read = "⏳", - chapter_time_to_read = "⤻", + chapter_time_to_read = BD.mirroredUILayout() and "⥖" or "⤻", frontlight = "☼", mem_usage = "", wifi_status = "", } } +if BD.mirroredUILayout() then + -- We need to RTL-wrap these letters and symbols for proper layout + for k, v in pairs(symbol_prefix.letters) do + local colon = v:find(":") + local wrapped + if colon then + local pre = v:sub(1, colon-1) + local post = v:sub(colon) + wrapped = BD.wrap(pre) .. BD.wrap(post) + else + wrapped = BD.wrap(v) + end + symbol_prefix.letters[k] = wrapped + end + for k, v in pairs(symbol_prefix.icons) do + symbol_prefix.icons[k] = BD.wrap(v) + end +end + local PROGRESS_BAR_STYLE_THICK_DEFAULT_HEIGHT = 7 local PROGRESS_BAR_STYLE_THIN_DEFAULT_HEIGHT = 3 @@ -115,9 +136,9 @@ local footerTextGeneratorMap = { prefix = "" end end - return prefix .. batt_lvl .. "%" + return BD.wrap(prefix) .. batt_lvl .. "%" else - return prefix .. " " .. (powerd:isCharging() and "+" or "") .. batt_lvl .. "%" + return BD.wrap(prefix) .. " " .. (powerd:isCharging() and "+" or "") .. batt_lvl .. "%" end end, time = function(footer) @@ -1230,10 +1251,13 @@ function ReaderFooter:genAllFooterText() elseif self.settings.items_separator == "bullet" then separator = " • " end + -- We need to BD.wrap() all items and separators, so we're + -- sure they are laid out in our order (reversed in RTL), + -- without ordering by the RTL Bidi algorithm. for _, gen in ipairs(self.footerTextGenerators) do - table.insert(info, gen(self)) + table.insert(info, BD.wrap(gen(self))) end - return table.concat(info, separator) + return table.concat(info, BD.wrap(separator)) end function ReaderFooter:setTocMarkers(reset) diff --git a/frontend/apps/reader/modules/readergesture.lua b/frontend/apps/reader/modules/readergesture.lua index 8fffabe7f..2cccf378d 100644 --- a/frontend/apps/reader/modules/readergesture.lua +++ b/frontend/apps/reader/modules/readergesture.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Device = require("device") @@ -225,6 +226,44 @@ function ReaderGesture:init() } local gm = G_reader_settings:readSetting(self.ges_mode) if gm == nil then G_reader_settings:saveSetting(self.ges_mode, {}) end + + -- Some of these defaults need to be reversed in RTL mirrored UI, + -- and as we set them in the saved gestures, we need to reset them + -- to the defaults in case of UI language's direction change. + local mirrored_if_rtl = { + tap_top_left_corner = "tap_top_right_corner", + tap_right_bottom_corner = "tap_left_bottom_corner", + } + local is_rtl = BD.mirroredUILayout() + if is_rtl then + for k, v in pairs(mirrored_if_rtl) do + self.default_gesture[k], self.default_gesture[v] = self.default_gesture[v], self.default_gesture[k] + end + end + -- We remember the last UI direction gestures were made on. If it changes, + -- reset the mirrored_if_rtl ones to the default for the new direction. + local ges_dir_setting = self.ges_mode.."ui_lang_direction_rtl" + local prev_lang_dir_rtl = G_reader_settings:isTrue(ges_dir_setting) + if (is_rtl and not prev_lang_dir_rtl) or (not is_rtl and prev_lang_dir_rtl) then + local reset = false + for k, v in pairs(mirrored_if_rtl) do + -- We only replace them if they are still the other direction's default. + -- If not, the user has changed them: let him deal with setting new ones if needed. + if gm[k] == self.default_gesture[v] then + gm[k] = self.default_gesture[k] + reset = true + end + if gm[v] == self.default_gesture[k] then + gm[v] = self.default_gesture[v] + reset = true + end + end + if reset then + logger.info("UI language direction changed: resetting some gestures to direction default") + end + G_reader_settings:flipNilOrFalse(ges_dir_setting) + end + self.ui.menu:registerToMainMenu(self) self:initGesture() end @@ -1577,8 +1616,12 @@ function ReaderGesture:onToggleReadingOrder() local document_module = self.ui.document.info.has_pages and self.ui.paging or self.ui.rolling document_module.inverse_reading_order = not document_module.inverse_reading_order document_module:setupTouchZones() + local is_rtl = BD.mirroredUILayout() + if document_module.inverse_reading_order then + is_rtl = not is_rtl + end UIManager:show(Notification:new{ - text = document_module.inverse_reading_order and _("RTL page turning.") or _("LTR page turning."), + text = is_rtl and _("RTL page turning.") or _("LTR page turning."), timeout = 2.5, }) return true diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 6538ca4ab..a12946a77 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local Device = require("device") local Event = require("ui/event") @@ -350,9 +351,19 @@ function ReaderHighlight:onShowHighlightDialog(page, index) } if not self.ui.document.info.has_pages then + local start_prev = "◁⇱" + local start_next = "⇱▷" + local end_prev = "◁⇲" + local end_next = "⇲▷" + if BD.mirroredUILayout() then + -- Sadly, there's only north west & south east arrow to corner, + -- north east and south west do not exist in Unicode. + start_prev, start_next = BD.ltr(start_next), BD.ltr(start_prev) + end_prev, end_next = BD.ltr(end_next), BD.ltr(end_prev) + end table.insert(buttons, { { - text = "◁⇱", + text = start_prev, callback = function() self:updateHighlight(page, index, 0, -1, false) end, @@ -362,7 +373,7 @@ function ReaderHighlight:onShowHighlightDialog(page, index) end }, { - text = "⇱▷", + text = start_next, callback = function() self:updateHighlight(page, index, 0, 1, false) end, @@ -372,7 +383,7 @@ function ReaderHighlight:onShowHighlightDialog(page, index) end }, { - text = "◁⇲", + text = end_prev, callback = function() self:updateHighlight(page, index, 1, -1, false) end, @@ -381,7 +392,7 @@ function ReaderHighlight:onShowHighlightDialog(page, index) end }, { - text = "⇲▷", + text = end_next, callback = function() self:updateHighlight(page, index, 1, 1, false) end, @@ -577,6 +588,14 @@ function ReaderHighlight:onHoldPan(_, ges) and self.holdpan_pos.x < 1/8*Screen:getWidth() local is_in_bottom_right_corner = self.holdpan_pos.y > 7/8*Screen:getHeight() and self.holdpan_pos.x > 7/8*Screen:getWidth() + if BD.mirroredUILayout() then + -- Note: this might not be really usable, as crengine native selection + -- is not adapted to RTL text + is_in_top_left_corner = self.holdpan_pos.y < 1/8*Screen:getHeight() + and self.holdpan_pos.x > 7/8*Screen:getWidth() + is_in_bottom_right_corner = self.holdpan_pos.y > 7/8*Screen:getHeight() + and self.holdpan_pos.x < 1/8*Screen:getWidth() + end if is_in_top_left_corner or is_in_bottom_right_corner then if self.was_in_some_corner then -- Do nothing, wait for the user to move his finger out of that corner diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 4d997ff27..27145c27d 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -2,6 +2,7 @@ ReaderLink is an abstraction for document-specific link interfaces. ]] +local BD = require("ui/bidi") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -689,7 +690,8 @@ function ReaderLink:onGoBackLink(show_notification_if_empty) end function ReaderLink:onSwipe(arg, ges) - if ges.direction == "east" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "east" then if isSwipeToGoBackEnabled() then if #self.location_stack > 0 then -- Remember if location stack is going to be empty, so we @@ -709,7 +711,7 @@ function ReaderLink:onSwipe(arg, ges) return true end end - elseif ges.direction == "west" then + elseif direction == "west" then local ret = false if isSwipeToFollowNearestLinkEnabled() then ret = self:onGoToPageLink(ges, isSwipeIgnoreExternalLinksEnabled(), isFootnoteLinkInPopupEnabled()) diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index fe304f921..697c37dac 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local CenterContainer = require("ui/widget/container/centercontainer") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -373,10 +374,10 @@ function ReaderMenu:_getTabIndexFromLocation(ges) return self.last_tab_index -- if the start position is far right elseif ges.pos.x > 2 * Screen:getWidth() / 3 then - return #self.tab_item_table + return BD.mirroredUILayout() and 1 or #self.tab_item_table -- if the start position is far left elseif ges.pos.x < Screen:getWidth() / 3 then - return 1 + return BD.mirroredUILayout() and #self.tab_item_table or 1 -- if center return the last index else return self.last_tab_index diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua index 5b03c9263..ebd6a012c 100644 --- a/frontend/apps/reader/modules/readerpaging.lua +++ b/frontend/apps/reader/modules/readerpaging.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Device = require("device") local Event = require("ui/event") local Geom = require("ui/geometry") @@ -111,7 +112,11 @@ function ReaderPaging:setupTapTouchZones() ratio_w = DTAP_ZONE_BACKWARD.w, ratio_h = DTAP_ZONE_BACKWARD.h, } + local do_mirror = BD.mirroredUILayout() if self.inverse_reading_order then + do_mirror = not do_mirror + end + if do_mirror then forward_zone.ratio_x = 1 - forward_zone.ratio_x - forward_zone.ratio_w backward_zone.ratio_x = 1 - backward_zone.ratio_x - backward_zone.ratio_w end @@ -373,39 +378,42 @@ function ReaderPaging:pageFlipping(flipping_page, flipping_ges) local steps = #self.flip_steps local stp_proportion = flipping_ges.distance / Screen:getWidth() local abs_proportion = flipping_ges.distance / Screen:getHeight() - if flipping_ges.direction == "east" then + local direction = BD.flipDirectionIfMirroredUILayout(flipping_ges.direction) + if direction == "east" then self:_gotoPage(flipping_page - self.flip_steps[math.ceil(steps*stp_proportion)]) - elseif flipping_ges.direction == "west" then + elseif direction == "west" then self:_gotoPage(flipping_page + self.flip_steps[math.ceil(steps*stp_proportion)]) - elseif flipping_ges.direction == "south" then + elseif direction == "south" then self:_gotoPage(flipping_page - math.floor(whole*abs_proportion)) - elseif flipping_ges.direction == "north" then + elseif direction == "north" then self:_gotoPage(flipping_page + math.floor(whole*abs_proportion)) end UIManager:setDirty(self.view.dialog, "partial") end function ReaderPaging:bookmarkFlipping(flipping_page, flipping_ges) - if flipping_ges.direction == "east" then + local direction = BD.flipDirectionIfMirroredUILayout(flipping_ges.direction) + if direction == "east" then self.ui:handleEvent(Event:new("GotoPreviousBookmark", flipping_page)) - elseif flipping_ges.direction == "west" then + elseif direction == "west" then self.ui:handleEvent(Event:new("GotoNextBookmark", flipping_page)) end UIManager:setDirty(self.view.dialog, "partial") end function ReaderPaging:onSwipe(_, ges) + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) if self.bookmark_flipping_mode then self:bookmarkFlipping(self.current_page, ges) elseif self.page_flipping_mode and self.original_page then self:_gotoPage(self.original_page) - elseif ges.direction == "west" then + elseif direction == "west" then if self.inverse_reading_order then self:onGotoViewRel(-1) else self:onGotoViewRel(1) end - elseif ges.direction == "east" then + elseif direction == "east" then if self.inverse_reading_order then self:onGotoViewRel(1) else diff --git a/frontend/apps/reader/modules/readerrolling.lua b/frontend/apps/reader/modules/readerrolling.lua index 66cb24c36..4ed154bf6 100644 --- a/frontend/apps/reader/modules/readerrolling.lua +++ b/frontend/apps/reader/modules/readerrolling.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -304,7 +305,11 @@ function ReaderRolling:setupTouchZones() ratio_w = DDOUBLE_TAP_ZONE_PREV_CHAPTER.w, ratio_h = DDOUBLE_TAP_ZONE_PREV_CHAPTER.h, } + local do_mirror = BD.mirroredUILayout() if self.inverse_reading_order then + do_mirror = not do_mirror + end + if do_mirror then forward_zone.ratio_x = 1 - forward_zone.ratio_x - forward_zone.ratio_w backward_zone.ratio_x = 1 - backward_zone.ratio_x - backward_zone.ratio_w @@ -464,13 +469,14 @@ function ReaderRolling:getLastPercent() end function ReaderRolling:onSwipe(_, ges) - if ges.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "west" then if self.inverse_reading_order then self:onGotoViewRel(-1) else self:onGotoViewRel(1) end - elseif ges.direction == "east" then + elseif direction == "east" then if self.inverse_reading_order then self:onGotoViewRel(1) else @@ -597,20 +603,36 @@ function ReaderRolling:onGotoXPointer(xp, marker_xp) -- Make it 4/5 of left margin wide (and bigger when huge margin) local marker_w = math.floor(math.max(doc_margins["left"] - Screen:scaleBySize(5), doc_margins["left"] * 4/5)) - if self.ui.document:getVisiblePageCount() > 1 and screen_x > Screen:getWidth() / 2 then - -- On right page in 2-pages mode - -- We could show the marker on the right of the page with: - -- screen_x = Screen:getWidth() - marker_w - -- But it's best to show it on the left of text, so in - -- the middle margin, so it still shows just left of a - -- footnote number. - -- This is a bit tricky with how the middle margin is sized - -- by crengine (see LVDocView::updateLayout() in lvdocview.cpp) - screen_x = Screen:getWidth() / 2 - local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage()+1) - marker_w = page2_x + marker_w - screen_x - else - screen_x = 0 + if self.ui.document:getVisiblePageCount() > 1 then -- 2-pages mode + if screen_x < Screen:getWidth() / 2 then -- On left page + if BD.mirroredUILayout() then + -- In the middle margin, on the right of text + -- Same trick as below, assuming page2_x is equal to page 1 right x + screen_x = Screen:getWidth() / 2 + local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage()+1) + marker_w = page2_x + marker_w - screen_x + screen_x = screen_x - marker_w + else + screen_x = 0 -- In left page left margin + end + else -- On right page + if BD.mirroredUILayout() then + screen_x = Screen:getWidth() - marker_w -- In right page right margin + else + -- In the middle margin, on the left of text + -- This is a bit tricky with how the middle margin is sized + -- by crengine (see LVDocView::updateLayout() in lvdocview.cpp) + screen_x = Screen:getWidth() / 2 + local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage()+1) + marker_w = page2_x + marker_w - screen_x + end + end + else -- 1-page mode + if BD.mirroredUILayout() then + screen_x = Screen:getWidth() - marker_w -- In right margin + else + screen_x = 0 -- In left margin + end end self.mark_func = function() diff --git a/frontend/apps/reader/modules/readersearch.lua b/frontend/apps/reader/modules/readersearch.lua index e2986121e..dcb640b2a 100644 --- a/frontend/apps/reader/modules/readersearch.lua +++ b/frontend/apps/reader/modules/readersearch.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") @@ -28,6 +29,11 @@ function ReaderSearch:addToMainMenu(menu_items) end function ReaderSearch:onShowFulltextSearchInput() + local backward_text = "◁" + local forward_text = "▷" + if BD.mirroredUILayout() then + backward_text, forward_text = forward_text, backward_text + end self:onInput{ title = _("Enter text to search for"), type = "text", @@ -40,14 +46,14 @@ function ReaderSearch:onShowFulltextSearchInput() end, }, { - text = "◁", + text = backward_text, callback = function() self:onShowSearchDialog(self.input_dialog:getInputText(), 1) self:closeInputDialog() end, }, { - text = "▷", + text = forward_text, is_enter_default = true, callback = function() self:onShowSearchDialog(self.input_dialog:getInputText(), 0) @@ -138,24 +144,33 @@ function ReaderSearch:onShowSearchDialog(text, direction) end end end + local from_start_text = "▕◁" + local backward_text = "◁" + local forward_text = "▷" + local from_end_text = "▷▏" + if BD.mirroredUILayout() then + backward_text, forward_text = forward_text, backward_text + -- Keep the LTR order of |< and >|: + from_start_text, from_end_text = BD.ltr(from_end_text), BD.ltr(from_start_text) + end self.search_dialog = ButtonDialog:new{ -- alpha = 0.7, buttons = { { { - text = "▕◁", + text = from_start_text, callback = do_search(self.searchFromStart, text), }, { - text = "◁", + text = backward_text, callback = do_search(self.searchNext, text, 1), }, { - text = "▷", + text = forward_text, callback = do_search(self.searchNext, text, 0), }, { - text = "▷▏", + text = from_end_text, callback = do_search(self.searchFromEnd, text), }, } diff --git a/frontend/apps/reader/modules/readertoc.lua b/frontend/apps/reader/modules/readertoc.lua index b2493beba..c324ab61e 100644 --- a/frontend/apps/reader/modules/readertoc.lua +++ b/frontend/apps/reader/modules/readertoc.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Button = require("ui/widget/button") local CenterContainer = require("ui/widget/container/centercontainer") local ConfirmBox = require("ui/widget/confirmbox") @@ -285,6 +286,7 @@ function ReaderToc:onShowToc() -- update collapsible state self.expand_button = Button:new{ icon = "resources/icons/appbar.control.expand.png", + icon_rotation_angle = BD.mirroredUILayout() and 180 or 0, width = Screen:scaleBySize(30), bordersize = 0, show_parent = self, @@ -338,7 +340,7 @@ function ReaderToc:onShowToc() w = Screen:getWidth(), h = Screen:getHeight(), }, - direction = "west" + direction = BD.flipDirectionIfMirroredUILayout("west") } } } @@ -352,7 +354,15 @@ function ReaderToc:onShowToc() function toc_menu:onMenuSelect(item, pos) -- if toc item has expand/collapse state and tap select on the left side -- the state switch action is triggered, otherwise goto the linked page - if item.state and pos and pos.x < 0.3 then + local do_toggle_state = false + if item.state and pos and pos.x then + if BD.mirroredUILayout() then + do_toggle_state = pos.x > 0.7 + else + do_toggle_state = pos.x < 0.3 + end + end + if do_toggle_state then item.state.callback() else toc_menu:close_callback() diff --git a/frontend/apps/reader/skimtowidget.lua b/frontend/apps/reader/skimtowidget.lua index 710dc7d43..07606d389 100644 --- a/frontend/apps/reader/skimtowidget.lua +++ b/frontend/apps/reader/skimtowidget.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Button = require("ui/widget/button") local CenterContainer = require("ui/widget/container/centercontainer") @@ -91,7 +92,7 @@ function SkimToWidget:init() text = dialog_title, face = self.title_face, bold = true, - width = self.screen_width * 0.95, + max_width = self.screen_width * 0.95, }, } @@ -198,8 +199,16 @@ function SkimToWidget:init() end, } + local chapter_next_text = "▷│" + local chapter_prev_text = "│◁" + local bookmark_next_text = "☆▷" + local bookmark_prev_text = "◁☆" + if BD.mirroredUILayout() then + chapter_next_text, chapter_prev_text = chapter_prev_text, chapter_next_text + bookmark_next_text, bookmark_prev_text = bookmark_prev_text, bookmark_next_text + end local button_chapter_next = Button:new{ - text = '▷│', + text = chapter_next_text, bordersize = self.button_bordersize, margin = self.button_margin, radius = 0, @@ -218,7 +227,7 @@ function SkimToWidget:init() } local button_chapter_prev = Button:new{ - text = "│◁", + text = chapter_prev_text, bordersize = self.button_bordersize, margin = self.button_margin, radius = 0, @@ -237,7 +246,7 @@ function SkimToWidget:init() } local button_bookmark_next = Button:new{ - text = "☆▷", + text = bookmark_next_text, bordersize = self.button_bordersize, margin = self.button_margin, radius = 0, @@ -265,7 +274,7 @@ function SkimToWidget:init() } local button_bookmark_prev = Button:new{ - text = "◁☆", + text = bookmark_prev_text, bordersize = self.button_bordersize, margin = self.button_margin, radius = 0, @@ -420,9 +429,10 @@ end function SkimToWidget:onTapProgress(arg, ges_ev) if ges_ev.pos:intersectWith(self.progress_bar.dimen) then - local width = self.progress_bar.dimen.w - local pos = ges_ev.pos.x - self.progress_bar.dimen.x - local perc = pos / width + local perc = self.progress_bar:getPercentageFromPosition(ges_ev.pos) + if not perc then + return true + end local page = Math.round(perc * self.page_count) self:addOriginToLocationStack() self.ui:handleEvent(Event:new("GotoPage", page )) diff --git a/frontend/ui/data/koptoptions.lua b/frontend/ui/data/koptoptions.lua index 4e00153eb..1e8d93fc4 100644 --- a/frontend/ui/data/koptoptions.lua +++ b/frontend/ui/data/koptoptions.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Device = require("device") local S = require("ui/data/strings") local optionsutil = require("ui/data/optionsutil") @@ -315,4 +316,16 @@ This can also be used to remove some gray background or to convert a grayscale o }, } +if BD.mirroredUILayout() then + -- The justification items {AUTO, LEFT, CENTER, RIGHT, JUSTIFY} will + -- be mirrored - but that's not enough: we need to swap LEFT and RIGHT, + -- so they appear in a more expected and balanced order to RTL users: + -- {JUSTIFY, LEFT, CENTER, RIGHT, AUTO} + local j = KoptOptions[3].options[6] + assert(j.name == "justification") + j.item_icons[2], j.item_icons[4] = j.item_icons[4], j.item_icons[2] + j.values[2], j.values[4] = j.values[4], j.values[2] + j.labels[2], j.labels[4] = j.labels[4], j.labels[2] +end + return KoptOptions diff --git a/frontend/ui/widget/button.lua b/frontend/ui/widget/button.lua index ac39d54d9..33d704353 100644 --- a/frontend/ui/widget/button.lua +++ b/frontend/ui/widget/button.lua @@ -33,6 +33,7 @@ local Button = InputContainer:new{ text = nil, -- mandatory text_func = nil, icon = nil, + icon_rotation_angle = 0, preselect = false, callback = nil, enabled = true, @@ -74,6 +75,7 @@ function Button:init() else self.label_widget = ImageWidget:new{ file = self.icon, + rotation_angle = self.icon_rotation_angle, dim = not self.enabled, scale_for_dpi = true, } diff --git a/frontend/ui/widget/checkmark.lua b/frontend/ui/widget/checkmark.lua index dd836e3c6..6e2c4f3a8 100644 --- a/frontend/ui/widget/checkmark.lua +++ b/frontend/ui/widget/checkmark.lua @@ -14,6 +14,7 @@ Example: ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Font = require("ui/font") local InputContainer = require("ui/widget/container/inputcontainer") @@ -27,30 +28,40 @@ local CheckMark = InputContainer:new{ face = Font:getFace("smallinfofont"), width = 0, height = 0, + _mirroredUI = BD.mirroredUILayout(), } function CheckMark:init() + -- Adjust these checkmarks if mirroring UI (para_direction_rtl should + -- follow BD.mirroredUILayout(), and not the set or reverted text + -- direction, for proper rendering on the right). + local para_direction_rtl = self._mirroredUI local checked_widget = TextWidget:new{ text = " ✓", -- preceded by thin space for better alignment face = self.face, + para_direction_rtl = para_direction_rtl, } local unchecked_widget = TextWidget:new{ text = "▢ ", face = self.face, + para_direction_rtl = para_direction_rtl, } local disabled_checked_widget = TextWidget:new{ text = " ✓", -- preceded by thin space for better alignment face = self.face, fgcolor = Blitbuffer.COLOR_DARK_GRAY, + para_direction_rtl = para_direction_rtl, } local disabled_unchecked_widget = TextWidget:new{ text = "▢ ", face = self.face, fgcolor = Blitbuffer.COLOR_DARK_GRAY, + para_direction_rtl = para_direction_rtl, } local empty_widget = TextWidget:new{ text = "", face = self.face, + para_direction_rtl = para_direction_rtl, } local widget if self.checkable then diff --git a/frontend/ui/widget/closebutton.lua b/frontend/ui/widget/closebutton.lua index 19b4c419e..49887432a 100644 --- a/frontend/ui/widget/closebutton.lua +++ b/frontend/ui/widget/closebutton.lua @@ -34,11 +34,11 @@ function CloseButton:init() face = Font:getFace("cfont", 30), } + -- The text box height is greater than its width, and we want this × to be + -- diagonally aligned with the top right corner (assuming padding_right=0, + -- or padding_right = padding_top so the diagonal aligment is preserved). local text_size = text_widget:getSize() - -- The text box height is greater than its width, and we want this × to - -- be diagonally aligned with our top right border local text_width_pad = (text_size.h - text_size.w) / 2 - -- We also add the provided padding_right self[1] = FrameContainer:new{ bordersize = 0, diff --git a/frontend/ui/widget/dictquicklookup.lua b/frontend/ui/widget/dictquicklookup.lua index 462c859f5..ecf5fcff4 100644 --- a/frontend/ui/widget/dictquicklookup.lua +++ b/frontend/ui/widget/dictquicklookup.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Button = require("ui/widget/button") local ButtonTable = require("ui/widget/buttontable") @@ -410,10 +411,15 @@ function DictQuickLookup:update() }, } else + local prev_dict_text = "◁◁" + local next_dict_text = "▷▷" + if BD.mirroredUILayout() then + prev_dict_text, next_dict_text = next_dict_text, prev_dict_text + end buttons = { { { - text = "◁◁", + text = prev_dict_text, enabled = self:isPrevDictAvaiable(), callback = function() self:changeToPrevDict() @@ -432,7 +438,7 @@ function DictQuickLookup:update() end, }, { - text = "▷▷", + text = next_dict_text, enabled = self:isNextDictAvaiable(), callback = function() self:changeToNextDict() @@ -462,7 +468,10 @@ function DictQuickLookup:update() { -- if more than one language, enable it and display "current lang > next lang" -- otherwise, just display current lang - text = self.is_wiki and ( #self.wiki_languages > 1 and self.wiki_languages[1].." > "..self.wiki_languages[2] or self.wiki_languages[1] ) or _("Follow Link"), + text = self.is_wiki + and ( #self.wiki_languages > 1 and BD.wrap(self.wiki_languages[1]).." > "..BD.wrap(self.wiki_languages[2]) + or self.wiki_languages[1] ) -- (this " > " will be auro-mirrored by bidi) + or _("Follow Link"), enabled = (self.is_wiki and #self.wiki_languages > 1) or self.selected_link ~= nil, callback = function() if self.is_wiki then @@ -738,7 +747,7 @@ function DictQuickLookup:onTapCloseDict(arg, ges_ev) -- processed for scrolling definition by ScrollTextWidget, which -- will pop it up for us here when it can't scroll anymore). -- This allow for continuous reading of results' definitions with tap. - if ges_ev.pos.x < Screen:getWidth()/2 then + if BD.flipIfMirroredUILayout(ges_ev.pos.x < Screen:getWidth()/2) then local prev_index = self.dict_index self:changeToPrevDict() if self.dict_index ~= prev_index then @@ -792,9 +801,10 @@ function DictQuickLookup:onSwipe(arg, ges) if ges.pos:intersectWith(self.definition_widget.dimen) then -- if we want changeDict to still work with swipe outside window : -- or not ges.pos:intersectWith(self.dict_frame.dimen) then - if ges.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "west" then self:changeToNextDict() - elseif ges.direction == "east" then + elseif direction == "east" then self:changeToPrevDict() else if self.refresh_callback then self.refresh_callback() end diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua index 59c6dc2ad..b3343ba9c 100644 --- a/frontend/ui/widget/filechooser.lua +++ b/frontend/ui/widget/filechooser.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Device = require("device") local DocSettings = require("docsettings") local DocumentRegistry = require("document/documentregistry") @@ -121,7 +122,7 @@ end function FileChooser:genItemTableFromPath(path) local dirs = {} local files = {} - local up_folder_arrow = "⬆ ../" + local up_folder_arrow = BD.mirroredUILayout() and BD.ltr("../ ⬆") or "⬆ ../" self.list(path, dirs, files) @@ -213,15 +214,18 @@ function FileChooser:genItemTableFromPath(path) local num_items = #sub_dirs + #dir_files local istr = ffiUtil.template(N_("1 item", "%1 items", num_items), num_items) local text + local bidi_wrap_func if dir.name == ".." then text = up_folder_arrow elseif dir.name == "." then -- possible with show_current_dir_for_hold text = _("Long-press to select current directory") else text = dir.name.."/" + bidi_wrap_func = BD.directory end table.insert(item_table, { text = text, + bidi_wrap_func = bidi_wrap_func, mandatory = istr, path = subdir_path, is_go_up = dir.name == ".." @@ -239,6 +243,7 @@ function FileChooser:genItemTableFromPath(path) local sstr = getFriendlySize(file_size) local file_item = { text = file.name, + bidi_wrap_func = BD.filename, mandatory = sstr, path = full_path } @@ -437,7 +442,7 @@ function FileChooser:showSetProviderButtons(file, filemanager_instance, reader_u if self.set_provider_dialog._check_file_button.checked then UIManager:show(ConfirmBox:new{ text = T(_("Always open '%2' with %1?"), - provider.provider_name, filename_pure), + provider.provider_name, BD.filename(filename_pure)), ok_text = _("Always"), ok_callback = function() DocumentRegistry:setProvider(file, provider, false) @@ -485,7 +490,7 @@ function FileChooser:showSetProviderButtons(file, filemanager_instance, reader_u end self.set_provider_dialog = OpenWithDialog:new{ - title = T(_("Open %1 with:"), filename_pure), + title = T(_("Open %1 with:"), BD.filename(filename_pure)), radio_buttons = radio_buttons, buttons = buttons, } diff --git a/frontend/ui/widget/footnotewidget.lua b/frontend/ui/widget/footnotewidget.lua index 00086d0b8..0c77972a4 100644 --- a/frontend/ui/widget/footnotewidget.lua +++ b/frontend/ui/widget/footnotewidget.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local CenterContainer = require("ui/widget/container/centercontainer") @@ -193,7 +194,11 @@ function FootnoteWidget:init() -- bullets in its own left margin. To get a chance to have them -- shown, we let MuPDF handle our left margin. local html_left_margin = self.doc_margins.left .. "px" - local css = T(PAGE_CSS, "0", "0", "0", html_left_margin, -- top right bottom left + local html_right_margin = "0" + if BD.mirroredUILayout() then + html_left_margin, html_right_margin = html_right_margin, html_left_margin + end + local css = T(PAGE_CSS, "0", html_right_margin, "0", html_left_margin, -- top right bottom left self.font_face, DEFAULT_CSS) if self.css then -- add any provided css css = css .. "\n" .. self.css @@ -327,14 +332,15 @@ function FootnoteWidget:onTapClose(arg, ges) end function FootnoteWidget:onSwipeFollow(arg, ges) - if ges.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "west" then if self.follow_callback then if self.close_callback then self.close_callback(self.height) end return self.follow_callback() end - elseif ges.direction == "south" or ges.direction == "east" then + elseif direction == "south" or direction == "east" then UIManager:close(self) -- We can close with swipe down. If footnote is scrollable, -- this event will be eaten by ScrollHtmlWidget, and it will @@ -345,7 +351,7 @@ function FootnoteWidget:onSwipeFollow(arg, ges) self.close_callback(self.height) end return true - elseif ges.direction == "north" then + elseif direction == "north" then -- no use for now do end -- luacheck: ignore 541 else -- diagonal swipe diff --git a/frontend/ui/widget/frontlightwidget.lua b/frontend/ui/widget/frontlightwidget.lua index 43cdb8c6f..3fe9864f7 100644 --- a/frontend/ui/widget/frontlightwidget.lua +++ b/frontend/ui/widget/frontlightwidget.lua @@ -651,9 +651,10 @@ function FrontLightWidget:onTapProgress(arg, ges_ev) -- Unschedule any pending updates. UIManager:unschedule(self.update) - local width = self.fl_group.dimen.w - local pos = ges_ev.pos.x - self.fl_group.dimen.x - local perc = pos / width + local perc = self.fl_group:getPercentageFromPosition(ges_ev.pos) + if not perc then + return true + end local num = Math.round(perc * self.fl_max) -- Always set the frontlight intensity. diff --git a/frontend/ui/widget/imageviewer.lua b/frontend/ui/widget/imageviewer.lua index 3eb24842c..c41ff7bf5 100644 --- a/frontend/ui/widget/imageviewer.lua +++ b/frontend/ui/widget/imageviewer.lua @@ -2,6 +2,7 @@ ImageViewer displays an image with some simple manipulation options. ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ButtonTable = require("ui/widget/buttontable") local CenterContainer = require("ui/widget/container/centercontainer") @@ -459,11 +460,19 @@ function ImageViewer:onTap(_, ges) end if self._images_list then -- If it's a list of image (e.g. animated gifs), tap left/right 1/3 of screen to navigate + local show_prev_image, show_next_image if ges.pos.x < Screen:getWidth()/3 then + show_prev_image = not BD.mirroredUILayout() + show_next_image = BD.mirroredUILayout() + elseif ges.pos.x > Screen:getWidth()*2/3 then + show_prev_image = BD.mirroredUILayout() + show_next_image = not BD.mirroredUILayout() + end + if show_prev_image then if self._images_list_cur > 1 then self:switchToImageNum(self._images_list_cur - 1) end - elseif ges.pos.x > Screen:getWidth()*2/3 then + elseif show_next_image then if self._images_list_cur < self._images_list_nb then self:switchToImageNum(self._images_list_cur + 1) end diff --git a/frontend/ui/widget/keyvaluepage.lua b/frontend/ui/widget/keyvaluepage.lua index 91337b6e6..f5f5489b6 100644 --- a/frontend/ui/widget/keyvaluepage.lua +++ b/frontend/ui/widget/keyvaluepage.lua @@ -19,6 +19,7 @@ Example: ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local Button = require("ui/widget/button") @@ -333,6 +334,7 @@ function KeyValuePage:init() end -- return button + --- @todo: alternative icon if BD.mirroredUILayout() self.page_return_arrow = Button:new{ icon = "resources/icons/appbar.arrow.left.up.png", callback = function() self:onReturn() end, @@ -340,26 +342,34 @@ function KeyValuePage:init() show_parent = self, } -- group for page info + local chevron_left = "resources/icons/appbar.chevron.left.png" + local chevron_right = "resources/icons/appbar.chevron.right.png" + local chevron_first = "resources/icons/appbar.chevron.first.png" + local chevron_last = "resources/icons/appbar.chevron.last.png" + if BD.mirroredUILayout() then + chevron_left, chevron_right = chevron_right, chevron_left + chevron_first, chevron_last = chevron_last, chevron_first + end self.page_info_left_chev = Button:new{ - icon = "resources/icons/appbar.chevron.left.png", + icon = chevron_left, callback = function() self:prevPage() end, bordersize = 0, show_parent = self, } self.page_info_right_chev = Button:new{ - icon = "resources/icons/appbar.chevron.right.png", + icon = chevron_right, callback = function() self:nextPage() end, bordersize = 0, show_parent = self, } self.page_info_first_chev = Button:new{ - icon = "resources/icons/appbar.chevron.first.png", + icon = chevron_first, callback = function() self:goToPage(1) end, bordersize = 0, show_parent = self, } self.page_info_last_chev = Button:new{ - icon = "resources/icons/appbar.chevron.last.png", + icon = chevron_last, callback = function() self:goToPage(self.pages) end, bordersize = 0, show_parent = self, @@ -446,6 +456,7 @@ function KeyValuePage:init() local content = OverlapGroup:new{ dimen = self.dimen:copy(), + allow_mirroring = false, VerticalGroup:new{ align = "left", self.title_bar, @@ -557,16 +568,17 @@ function KeyValuePage:onPrevPage() end function KeyValuePage:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:nextPage() return true - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:prevPage() return true - elseif ges_ev.direction == "south" then + elseif direction == "south" then -- Allow easier closing with swipe down self:onClose() - elseif ges_ev.direction == "north" then + elseif direction == "north" then -- no use for now do end -- luacheck: ignore 541 else -- diagonal swipe diff --git a/frontend/ui/widget/listview.lua b/frontend/ui/widget/listview.lua index a77b20846..6617ef191 100644 --- a/frontend/ui/widget/listview.lua +++ b/frontend/ui/widget/listview.lua @@ -36,6 +36,7 @@ Note that ListView is created mainly to be used as a building block for other widgets like @{ui.widget.networksetting|NetworkSetting}, so they can share the same pagination code. ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Device = require("device") local FrameContainer = require("ui/widget/container/framecontainer") @@ -113,10 +114,11 @@ function ListView:prevPage() end function ListView:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:nextPage() return true - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:prevPage() return true end diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua index 18655d89c..eeaced86e 100644 --- a/frontend/ui/widget/menu.lua +++ b/frontend/ui/widget/menu.lua @@ -2,6 +2,7 @@ Widget that displays a shortcut icon for menu item. --]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local Button = require("ui/widget/button") @@ -33,7 +34,6 @@ local util = require("ffi/util") local _ = require("gettext") local Input = Device.input local Screen = Device.screen -local getMenuText = require("util").getMenuText local ItemShortCutIcon = WidgetContainer:new{ dimen = Geom:new{ w = Screen:scaleBySize(22), h = Screen:scaleBySize(22) }, @@ -92,21 +92,30 @@ local MenuCloseButton = InputContainer:new{ } function MenuCloseButton:init() - self[1] = TextWidget:new{ + local text_widget = TextWidget:new{ text = "×", face = Font:getFace("cfont", 30), -- this font size align nicely with title } - - local text_size = self[1]:getSize() - -- The text box height is greater than its width, and we want this × to - -- be diagonally aligned with our top right border + -- The text box height is greater than its width, and we want this × to be + -- diagonally aligned with the top right corner (assuming padding_right=0, + -- or padding_right = padding_top so the diagonal aligment is preserved). + local text_size = text_widget:getSize() local text_width_pad = (text_size.h - text_size.w) / 2 - -- We also add the provided padding_right + + self[1] = FrameContainer:new{ + bordersize = 0, + padding = 0, + padding_top = self.padding_top, + padding_bottom = self.padding_bottom, + padding_left = self.padding_left, + padding_right = self.padding_right + text_width_pad, + text_widget, + } + self.dimen = Geom:new{ w = text_size.w + text_width_pad + self.padding_right, h = text_size.h, } - self.ges_events.Close = { GestureRange:new{ ges = "tap", @@ -401,6 +410,7 @@ function MenuItem:init() table.insert(hgroup, HorizontalSpan:new{ width = Size.span.horizontal_default }) end table.insert(hgroup, self._underline_container) + table.insert(hgroup, HorizontalSpan:new{ width = Size.padding.fullscreen }) self[1] = FrameContainer:new{ bordersize = 0, @@ -641,26 +651,34 @@ function Menu:init() -- group for items self.item_group = VerticalGroup:new{} -- group for page info + local chevron_left = "resources/icons/appbar.chevron.left.png" + local chevron_right = "resources/icons/appbar.chevron.right.png" + local chevron_first = "resources/icons/appbar.chevron.first.png" + local chevron_last = "resources/icons/appbar.chevron.last.png" + if BD.mirroredUILayout() then + chevron_left, chevron_right = chevron_right, chevron_left + chevron_first, chevron_last = chevron_last, chevron_first + end self.page_info_left_chev = Button:new{ - icon = "resources/icons/appbar.chevron.left.png", + icon = chevron_left, callback = function() self:onPrevPage() end, bordersize = 0, show_parent = self.show_parent, } self.page_info_right_chev = Button:new{ - icon = "resources/icons/appbar.chevron.right.png", + icon = chevron_right, callback = function() self:onNextPage() end, bordersize = 0, show_parent = self.show_parent, } self.page_info_first_chev = Button:new{ - icon = "resources/icons/appbar.chevron.first.png", + icon = chevron_first, callback = function() self:onFirstPage() end, bordersize = 0, show_parent = self.show_parent, } self.page_info_last_chev = Button:new{ - icon = "resources/icons/appbar.chevron.last.png", + icon = chevron_last, callback = function() self:onLastPage() end, bordersize = 0, show_parent = self.show_parent, @@ -807,6 +825,10 @@ function Menu:init() } end local content = OverlapGroup:new{ + -- This unique allow_mirroring=false looks like it's enough + -- to have this complex Menu, and all widgets based on it, + -- be mirrored correctly with RTL languages + allow_mirroring = false, dimen = self.dimen:copy(), self.content_group, page_return, @@ -979,7 +1001,7 @@ function Menu:updateItems(select_number) show_parent = self.show_parent, state = self.item_table[i].state, state_size = self.state_size or {}, - text = getMenuText(self.item_table[i]), + text = Menu.getMenuText(self.item_table[i]), mandatory = self.item_table[i].mandatory, bold = self.item_table.current == i or self.item_table[i].bold == true, dim = self.item_table[i].dim, @@ -1237,11 +1259,12 @@ function Menu:onTapCloseAllMenus(arg, ges_ev) end function Menu:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:onNextPage() - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:onPrevPage() - elseif ges_ev.direction == "south" then + elseif direction == "south" then if self.has_close_button and not self.no_title then -- If there is a close button displayed (so, this Menu can be -- closed), allow easier closing with swipe up/down @@ -1249,7 +1272,7 @@ function Menu:onSwipe(arg, ges_ev) end -- If there is no close button, it's a top level Menu and swipe -- up/down may hide/show top menu - elseif ges_ev.direction == "north" then + elseif direction == "north" then -- no use for now do end -- luacheck: ignore 541 else -- diagonal swipe @@ -1258,6 +1281,42 @@ function Menu:onSwipe(arg, ges_ev) end end +--- Adds > to touch menu items with a submenu +local arrow_left = "◂" -- U+25C2 BLACK LEFT-POINTING SMALL TRIANGLE +local arrow_right = "▸" -- U+25B8 BLACK RIGHT-POINTING SMALL TRIANGLE +local sub_item_format +-- Adjust arrow direction and position for menu with sub items +-- according to possible user choices +if BD.mirroredUILayout() then + if BD.rtlUIText() then -- normal case with RTL language + sub_item_format = "%s " .. BD.rtl(arrow_left) + else -- user reverted text direction, so LTR + sub_item_format = BD.ltr(arrow_left) .. " %s" + end +else + if BD.rtlUIText() then -- user reverted text direction, so RTL + sub_item_format = BD.rtl(arrow_right) .. " %s" + else -- normal case with LTR language + sub_item_format = "%s " .. BD.ltr(arrow_right) + end +end + +function Menu.getMenuText(item) + local text + if item.text_func then + text = item.text_func() + else + text = item.text + end + if item.bidi_wrap_func then + text = item.bidi_wrap_func(text) + end + if item.sub_item_table ~= nil or item.sub_item_table_func then + text = string.format(sub_item_format, text) + end + return text +end + function Menu.itemTableFromTouchMenu(t) local item_t = {} for k,v in pairs(t) do diff --git a/frontend/ui/widget/scrollhtmlwidget.lua b/frontend/ui/widget/scrollhtmlwidget.lua index 9588de534..1cd2869f6 100644 --- a/frontend/ui/widget/scrollhtmlwidget.lua +++ b/frontend/ui/widget/scrollhtmlwidget.lua @@ -2,6 +2,7 @@ HTML widget with vertical scroll bar. --]] +local BD = require("ui/bidi") local Device = require("device") local HtmlBoxWidget = require("ui/widget/htmlboxwidget") local Geom = require("ui/geometry") @@ -143,7 +144,7 @@ function ScrollHtmlWidget:onScrollText(arg, ges) end function ScrollHtmlWidget:onTapScrollText(arg, ges) - if ges.pos.x < Screen:getWidth()/2 then + if BD.flipIfMirroredUILayout(ges.pos.x < Screen:getWidth()/2) then if self.htmlbox_widget.page_number > 1 then self:scrollText(-1) return true diff --git a/frontend/ui/widget/scrolltextwidget.lua b/frontend/ui/widget/scrolltextwidget.lua index 1be9f1f90..2f49089ea 100644 --- a/frontend/ui/widget/scrolltextwidget.lua +++ b/frontend/ui/widget/scrolltextwidget.lua @@ -2,6 +2,7 @@ Text widget with vertical scroll bar. --]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Device = require("device") local Geom = require("ui/geometry") @@ -161,6 +162,9 @@ function ScrollTextWidget:moveCursorToCharPos(charpos) end function ScrollTextWidget:moveCursorToXY(x, y, no_overflow) + if BD.mirroredUILayout() then -- the scroll bar is on the left + x = x - self.scroll_bar_width - self.text_scroll_span + end self.text_widget:moveCursorToXY(x, y, no_overflow) self:updateScrollBar() end @@ -238,7 +242,7 @@ function ScrollTextWidget:onTapScrollText(arg, ges) return false end -- same tests as done in TextBoxWidget:scrollUp/Down - if ges.pos.x < Screen:getWidth()/2 then + if BD.flipIfMirroredUILayout(ges.pos.x < Screen:getWidth()/2) then if self.text_widget.virtual_line_num > 1 then self:scrollText(-1) return true diff --git a/frontend/ui/widget/sortwidget.lua b/frontend/ui/widget/sortwidget.lua index bf4e7315f..015aafd81 100644 --- a/frontend/ui/widget/sortwidget.lua +++ b/frontend/ui/widget/sortwidget.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local Button = require("ui/widget/button") @@ -452,14 +453,15 @@ function SortWidget:onPrevPage() end function SortWidget:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:onNextPage() - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:onPrevPage() - elseif ges_ev.direction == "south" then + elseif direction == "south" then -- Allow easier closing with swipe down self:onClose() - elseif ges_ev.direction == "north" then + elseif direction == "north" then -- no use for now do end -- luacheck: ignore 541 else -- diagonal swipe diff --git a/frontend/ui/widget/textviewer.lua b/frontend/ui/widget/textviewer.lua index 43039046e..0e6febb9d 100644 --- a/frontend/ui/widget/textviewer.lua +++ b/frontend/ui/widget/textviewer.lua @@ -8,6 +8,7 @@ Displays some text in a scrollable view. } UIManager:show(textviewer) ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ButtonTable = require("ui/widget/buttontable") local CenterContainer = require("ui/widget/container/centercontainer") @@ -256,10 +257,11 @@ end function TextViewer:onSwipe(arg, ges) if ges.pos:intersectWith(self.textw.dimen) then - if ges.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges.direction) + if direction == "west" then self.scroll_text_w:scrollText(1) return true - elseif ges.direction == "east" then + elseif direction == "east" then self.scroll_text_w:scrollText(-1) return true else diff --git a/frontend/ui/widget/toggleswitch.lua b/frontend/ui/widget/toggleswitch.lua index bbdedeefe..f5fb85340 100644 --- a/frontend/ui/widget/toggleswitch.lua +++ b/frontend/ui/widget/toggleswitch.lua @@ -5,6 +5,7 @@ Displays a button that toggles between states. Used in bottom configuration pane local ToggleSwitch = require("ui/widget/toggleswitch") ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local CenterContainer = require("ui/widget/container/centercontainer") local Device = require("device") @@ -173,6 +174,9 @@ end function ToggleSwitch:calculatePosition(gev) local x = (gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos + if BD.mirroredUILayout() then + x = self.n_pos - x + end local y = (gev.pos.y - self.dimen.y) / self.dimen.h * self.row_count return math.max(1, math.ceil(x)) + math.min(self.row_count-1, math.floor(y)) * self.n_pos end diff --git a/frontend/ui/widget/touchmenu.lua b/frontend/ui/widget/touchmenu.lua index cc0a23bdf..929fc4388 100644 --- a/frontend/ui/widget/touchmenu.lua +++ b/frontend/ui/widget/touchmenu.lua @@ -1,6 +1,7 @@ --[[-- TouchMenu widget for hierarchical menus. ]] +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Button = require("ui/widget/button") local CenterContainer = require("ui/widget/container/centercontainer") @@ -26,9 +27,9 @@ local UIManager = require("ui/uimanager") local UnderlineContainer = require("ui/widget/container/underlinecontainer") local VerticalGroup = require("ui/widget/verticalgroup") local VerticalSpan = require("ui/widget/verticalspan") -local util = require("ffi/util") +local getMenuText = require("ui/widget/menu").getMenuText local _ = require("gettext") -local getMenuText = require("util").getMenuText +local T = require("ffi/util").template local Input = Device.input local Screen = Device.screen @@ -247,6 +248,11 @@ function TouchMenuBar:init() -- we have to use local variable here for closure callback local _start_seg = end_seg + icon_sep_width local _end_seg = _start_seg + self.icon_widgets[k]:getSize().w + end_seg = _end_seg -- for next loop _start_seg + + if BD.mirroredUILayout() then + _start_seg, _end_seg = self.width - _end_seg, self.width - _start_seg + end if k == 1 then self.bar_sep = LineWidget:new{ @@ -294,9 +300,15 @@ function TouchMenuBar:init() -- if the active icon is the last icon then the empty bar segment has -- to move over to the right by the width of a separator and the stretch width if last_icon then + local _start_last_seg = icon_sep_width + stretch_width + _start_seg + local _end_last_seg = icon_sep_width + stretch_width + _end_seg + if BD.mirroredUILayout() then + _start_last_seg = _start_seg - icon_sep_width - stretch_width + _end_last_seg = _end_seg - icon_sep_width - stretch_width + end self.bar_sep.empty_segments = { { - s = icon_sep_width + stretch_width + _start_seg, e = icon_sep_width + stretch_width + _end_seg + s = _start_last_seg, e = _end_last_seg } } sep.style = "solid" @@ -327,8 +339,6 @@ function TouchMenuBar:init() table.insert(self.icon_seps, icon_sep_duplicate) table.insert(self.bar_icon_group, icon_sep_duplicate) end - - end_seg = _end_seg end self[1] = FrameContainer:new{ @@ -429,14 +439,19 @@ function TouchMenu:init() align = "center", } -- group for page info + local chevron_left = "resources/icons/appbar.chevron.left.png" + local chevron_right = "resources/icons/appbar.chevron.right.png" + if BD.mirroredUILayout() then + chevron_left, chevron_right = chevron_right, chevron_left + end self.page_info_left_chev = Button:new{ - icon = "resources/icons/appbar.chevron.left.png", + icon = chevron_left, callback = function() self:onPrevPage() end, bordersize = 0, show_parent = self.show_parent, } self.page_info_right_chev = Button:new{ - icon = "resources/icons/appbar.chevron.right.png", + icon = chevron_right, callback = function() self:onNextPage() end, bordersize = 0, show_parent = self.show_parent, @@ -592,7 +607,7 @@ function TouchMenu:updateItems() table.insert(self.item_group, self.footer) if self.page_num > 1 then -- @translators %1 is the current page. %2 is the total number of pages. In some languages a good translation might need to reverse this order, for instance: "Total %2, page %1". - self.page_info_text:setText(util.template(_("Page %1 of %2"), self.page, self.page_num)) + self.page_info_text:setText(T(_("Page %1 of %2"), self.page, self.page_num)) else self.page_info_text:setText("") end @@ -609,35 +624,35 @@ function TouchMenu:updateItems() end local powerd = Device:getPowerDevice() local batt_lvl = powerd:getCapacity() - time_info_txt = time_info_txt .. " ⌁" + local batt_symbol if powerd:isCharging() then - time_info_txt = time_info_txt .. "" + batt_symbol = "" else if batt_lvl >= 100 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 90 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 80 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 70 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 60 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 50 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 40 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 30 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 20 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" elseif batt_lvl >= 10 then - time_info_txt = time_info_txt .. "" + batt_symbol = "" else - time_info_txt = time_info_txt .. "" + batt_symbol = "" end end - time_info_txt = time_info_txt .. batt_lvl .. "%" + time_info_txt = BD.wrap(time_info_txt) .. " " .. BD.wrap("⌁") .. BD.wrap(batt_symbol) .. BD.wrap(batt_lvl .. "%") self.time_info:setText(time_info_txt) -- recalculate dimen based on new layout @@ -721,11 +736,12 @@ function TouchMenu:onPrevPage() end function TouchMenu:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:onNextPage() - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:onPrevPage() - elseif ges_ev.direction == "north" then + elseif direction == "north" then self:closeMenu() end end diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 50a7d8e54..0188f0d20 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -163,6 +163,7 @@ function VirtualKey:init() background = Blitbuffer.COLOR_WHITE, radius = 0, padding = 0, + allow_mirroring = false, CenterContainer:new{ dimen = Geom:new{ w = self.width - 2*self.bordersize, @@ -465,11 +466,11 @@ function VirtualKeyPopup:init() } local v_key_padding = VerticalSpan:new{width = parent_key.keyboard.key_padding} - local vertical_group = VerticalGroup:new{} - local horizontal_group_extra = HorizontalGroup:new{} - local horizontal_group_top = HorizontalGroup:new{} - local horizontal_group_middle = HorizontalGroup:new{} - local horizontal_group_bottom = HorizontalGroup:new{} + local vertical_group = VerticalGroup:new{ allow_mirroring = false } + local horizontal_group_extra = HorizontalGroup:new{ allow_mirroring = false } + local horizontal_group_top = HorizontalGroup:new{ allow_mirroring = false } + local horizontal_group_middle = HorizontalGroup:new{ allow_mirroring = false } + local horizontal_group_bottom = HorizontalGroup:new{ allow_mirroring = false } local function horizontalRow(chars, group) local layout_horizontal = {} @@ -565,6 +566,7 @@ function VirtualKeyPopup:init() background = Blitbuffer.COLOR_WHITE, radius = 0, padding = parent_key.keyboard.padding, + allow_mirroring = false, CenterContainer:new{ dimen = Geom:new{ w = parent_key.width*num_columns + 2*Size.border.default + (num_columns)*parent_key.keyboard.key_padding, @@ -778,9 +780,9 @@ function VirtualKeyboard:addKeys() local base_key_height = math.floor((self.height - (#self.KEYS + 1)*self.key_padding - 2*self.padding)/#self.KEYS) local h_key_padding = HorizontalSpan:new{width = self.key_padding} local v_key_padding = VerticalSpan:new{width = self.key_padding} - local vertical_group = VerticalGroup:new{} + local vertical_group = VerticalGroup:new{ allow_mirroring = false } for i = 1, #self.KEYS do - local horizontal_group = HorizontalGroup:new{} + local horizontal_group = HorizontalGroup:new{ allow_mirroring = false } local layout_horizontal = {} for j = 1, #self.KEYS[i] do local key @@ -828,6 +830,7 @@ function VirtualKeyboard:addKeys() background = Blitbuffer.COLOR_WHITE, radius = 0, padding = self.padding, + allow_mirroring = false, CenterContainer:new{ dimen = Geom:new{ w = self.width - 2*Size.border.default - 2*self.padding, diff --git a/frontend/util.lua b/frontend/util.lua index bf3113f93..17c874679 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -694,20 +694,6 @@ function util.getFormattedSize(size) return s end ---- Adds > to touch menu items with a submenu -function util.getMenuText(item) - local text - if item.text_func then - text = item.text_func() - else - text = item.text - end - if item.sub_item_table ~= nil or item.sub_item_table_func then - text = text .. " ▸" - end - return text -end - --[[-- Replaces invalid UTF-8 characters with a replacement string. diff --git a/plugins/coverbrowser.koplugin/listmenu.lua b/plugins/coverbrowser.koplugin/listmenu.lua index 39a496e0f..961ef00aa 100644 --- a/plugins/coverbrowser.koplugin/listmenu.lua +++ b/plugins/coverbrowser.koplugin/listmenu.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local CenterContainer = require("ui/widget/container/centercontainer") local Device = require("device") @@ -31,6 +32,7 @@ local _ = require("gettext") local N_ = _.ngettext local Screen = Device.screen local T = require("ffi/util").template +local getMenuText = require("ui/widget/menu").getMenuText local BookInfoManager = require("bookinfomanager") @@ -339,7 +341,7 @@ function ListMenuItem:update() local filename_without_suffix, filetype = util.splitFileNameSuffix(filename) local fileinfo_str = filetype if self.mandatory then - fileinfo_str = self.mandatory .. " " .. fileinfo_str + fileinfo_str = self.mandatory .. " " .. BD.wrap(fileinfo_str) end if bookinfo._no_provider then -- for unspported files: don't show extension on the right, @@ -452,7 +454,7 @@ function ListMenuItem:update() end corner_mark = ImageWidget:new{ file = "resources/icons/dogear.png", - rotation_angle = 270, + rotation_angle = BD.mirroredUILayout() and 180 or 270, width = corner_mark_size, height = corner_mark_size, } @@ -695,7 +697,12 @@ function ListMenuItem:paintTo(bb, x, y) if self.shortcut_icon then -- align it on bottom left corner of sub-widget local target = self[1][1][2] - local ix = 0 + local ix + if BD.mirroredUILayout() then + ix = target.dimen.w - self.shortcut_icon.dimen.w + else + ix = 0 + end local iy = target.dimen.h - self.shortcut_icon.dimen.h self.shortcut_icon:paintTo(bb, x+ix, y+iy) end @@ -703,7 +710,12 @@ function ListMenuItem:paintTo(bb, x, y) -- to which we paint over a dogear if needed if corner_mark and self.do_hint_opened and self.been_opened then -- align it on bottom right corner of widget - local ix = self.width - corner_mark:getSize().w + local ix + if BD.mirroredUILayout() then + ix = 0 + else + ix = self.width - corner_mark:getSize().w + end local iy = self.height - corner_mark:getSize().h corner_mark:paintTo(bb, x+ix, y+iy) end @@ -716,10 +728,22 @@ function ListMenuItem:paintTo(bb, x, y) if self.do_cover_image and target[1][1][1] then -- it has an image, align it on image's framecontainer's right border target = target[1][1] - bb:paintBorder(target.dimen.x + target.dimen.w - 1, target.dimen.y, d_w, d_h, 1) + local ix + if BD.mirroredUILayout() then + ix = target.dimen.x - d_w + 1 + else + ix = target.dimen.x + target.dimen.w - 1 + end + bb:paintBorder(ix, target.dimen.y, d_w, d_h, 1) else -- no image, align it to the left border - bb:paintBorder(x, y, d_w, d_h, 1) + local ix + if BD.mirroredUILayout() then + ix = target.dimen.x + target.dimen.w - d_w + else + ix = x + end + bb:paintBorder(ix, y, d_w, d_h, 1) end end end @@ -884,7 +908,7 @@ function ListMenu:_updateItemsBuildUI() height = self.item_height, width = self.item_width, entry = entry, - text = util.getMenuText(entry), + text = getMenuText(entry), show_parent = self.show_parent, mandatory = entry.mandatory, dimen = self.item_dimen:new(), diff --git a/plugins/coverbrowser.koplugin/mosaicmenu.lua b/plugins/coverbrowser.koplugin/mosaicmenu.lua index 9de307c24..701f407c0 100644 --- a/plugins/coverbrowser.koplugin/mosaicmenu.lua +++ b/plugins/coverbrowser.koplugin/mosaicmenu.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local CenterContainer = require("ui/widget/container/centercontainer") @@ -28,7 +29,7 @@ local util = require("util") local _ = require("gettext") local Screen = Device.screen local T = require("ffi/util").template -local getMenuText = require("util").getMenuText +local getMenuText = require("ui/widget/menu").getMenuText local BookInfoManager = require("bookinfomanager") @@ -195,7 +196,7 @@ function FakeCover:init() end if filename then filename_wg = TextBoxWidget:new{ - text = filename, + text = BD.filename(filename), face = Font:getFace("cfont", math.max(self.filename_font_max - sizedec, self.filename_font_min)), width = text_width, alignment = "center", @@ -607,7 +608,12 @@ function MosaicMenuItem:paintTo(bb, x, y) if self.shortcut_icon then -- align it on bottom left corner of widget local target = self - local ix = 0 + local ix + if BD.mirroredUILayout() then + ix = target.dimen.w - self.shortcut_icon.dimen.w + else + ix = 0 + end local iy = target.dimen.h - self.shortcut_icon.dimen.h self.shortcut_icon:paintTo(bb, x+ix, y+iy) end @@ -616,7 +622,12 @@ function MosaicMenuItem:paintTo(bb, x, y) if corner_mark and self.do_hint_opened and self.been_opened then -- align it on bottom right corner of sub-widget local target = self[1][1][1] - local ix = self.width - math.ceil((self.width - target.dimen.w)/2) - corner_mark:getSize().w + local ix + if BD.mirroredUILayout() then + ix = math.floor((self.width - target.dimen.w)/2) + else + ix = self.width - math.ceil((self.width - target.dimen.w)/2) - corner_mark:getSize().w + end local iy = self.height - math.ceil((self.height - target.dimen.h)/2) - corner_mark:getSize().h -- math.ceil() makes it looks better than math.floor() corner_mark:paintTo(bb, x+ix, y+iy) @@ -629,15 +640,27 @@ function MosaicMenuItem:paintTo(bb, x, y) local d_w = Screen:scaleBySize(3) local d_h = math.ceil(target.dimen.h / 8) -- Paint it directly relative to target.dimen.x/y which has been computed at this point - local ix = target.dimen.w - 1 - local iy = 0 - bb:paintBorder(target.dimen.x+ix, target.dimen.y+iy, d_w, d_h, 1) - local x_overflow = target.dimen.x+ix+d_w - x - self.dimen.w - if x_overflow > 0 then + local ix + if BD.mirroredUILayout() then + ix = - d_w + 1 -- Set alternate dimen to be marked as dirty to include this description in refresh - self.refresh_dimen = self[1].dimen:copy() - self.refresh_dimen.w = self.refresh_dimen.w + x_overflow + local x_overflow_left = x - target.dimen.x+ix -- positive if overflow + if x_overflow_left > 0 then + self.refresh_dimen = self[1].dimen:copy() + self.refresh_dimen.x = self.refresh_dimen.x - x_overflow_left + self.refresh_dimen.w = self.refresh_dimen.w + x_overflow_left + end + else + ix = target.dimen.w - 1 + -- Set alternate dimen to be marked as dirty to include this description in refresh + local x_overflow_right = target.dimen.x+ix+d_w - x - self.dimen.w + if x_overflow_right > 0 then + self.refresh_dimen = self[1].dimen:copy() + self.refresh_dimen.w = self.refresh_dimen.w + x_overflow_right + end end + local iy = 0 + bb:paintBorder(target.dimen.x+ix, target.dimen.y+iy, d_w, d_h, 1) end end @@ -732,7 +755,7 @@ function MosaicMenu:_recalculateDimen() end corner_mark = ImageWidget:new{ file = "resources/icons/dogear.png", - rotation_angle = 270, + rotation_angle = BD.mirroredUILayout() and 180 or 270, width = corner_mark_size, height = corner_mark_size, } diff --git a/plugins/goodreads.koplugin/doublekeyvaluepage.lua b/plugins/goodreads.koplugin/doublekeyvaluepage.lua index bebe29ec6..5d863d85e 100644 --- a/plugins/goodreads.koplugin/doublekeyvaluepage.lua +++ b/plugins/goodreads.koplugin/doublekeyvaluepage.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local BottomContainer = require("ui/widget/container/bottomcontainer") local Button = require("ui/widget/button") @@ -239,15 +240,20 @@ function DoubleKeyValuePage:init() text_font_bold = false, } -- group for page info + local chevron_left = "resources/icons/appbar.chevron.left.png" + local chevron_right = "resources/icons/appbar.chevron.right.png" + if BD.mirroredUILayout() then + chevron_left, chevron_right = chevron_right, chevron_left + end self.page_info_left_chev = Button:new{ - icon = "resources/icons/appbar.chevron.left.png", + icon = chevron_left, callback = function() self:prevPage() end, bordersize = 0, show_parent = self, } self.page_info_right_chev = Button:new{ - icon = "resources/icons/appbar.chevron.right.png", - callback = function() self:_nextPage() end, + icon = chevron_right, + callback = function() self:nextPage() end, bordersize = 0, show_parent = self, } @@ -413,16 +419,17 @@ function DoubleKeyValuePage:onPrevPage() end function DoubleKeyValuePage:onSwipe(arg, ges_ev) - if ges_ev.direction == "west" then + local direction = BD.flipDirectionIfMirroredUILayout(ges_ev.direction) + if direction == "west" then self:_nextPage() return true - elseif ges_ev.direction == "east" then + elseif direction == "east" then self:prevPage() return true - elseif ges_ev.direction == "south" then + elseif direction == "south" then -- Allow easier closing with swipe down self:onClose() - elseif ges_ev.direction == "north" then + elseif direction == "north" then -- no use for now do end -- luacheck: ignore 541 else -- diagonal swipe