mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
Text editor: rotate (#12658)
This commit is contained in:
@@ -60,28 +60,21 @@ local function isFile(file)
|
||||
return lfs.attributes(file, "mode") == "file"
|
||||
end
|
||||
|
||||
function FileManager:onSetRotationMode(rotation)
|
||||
if rotation ~= nil and rotation ~= Screen:getRotationMode() then
|
||||
Screen:setRotationMode(rotation)
|
||||
if FileManager.instance then
|
||||
self:reinit(self.path, self.focused_file)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function FileManager:onPhysicalKeyboardConnected()
|
||||
-- So that the key navigation shortcuts apply right away.
|
||||
-- This will also naturally call registerKeyEvents
|
||||
self:reinit(self.path, self.focused_file)
|
||||
end
|
||||
FileManager.onPhysicalKeyboardDisconnected = FileManager.onPhysicalKeyboardConnected
|
||||
|
||||
function FileManager:setRotationMode()
|
||||
local locked = G_reader_settings:isTrue("lock_rotation")
|
||||
if not locked then
|
||||
local rotation_mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT
|
||||
self:onSetRotationMode(rotation_mode)
|
||||
local mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT
|
||||
self:onSetRotationMode(mode)
|
||||
end
|
||||
end
|
||||
|
||||
function FileManager:onSetRotationMode(mode)
|
||||
local old_mode = Screen:getRotationMode()
|
||||
if mode ~= nil and mode ~= old_mode then
|
||||
Screen:setRotationMode(mode)
|
||||
if FileManager.instance then
|
||||
self:rotate()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -728,6 +721,8 @@ function FileManager:tapPlus()
|
||||
end
|
||||
|
||||
function FileManager:reinit(path, focused_file)
|
||||
path = path or self.path
|
||||
focused_file = focused_file or self.focused_file
|
||||
UIManager:flushSettings()
|
||||
self.dimen = Screen:getSize()
|
||||
-- backup the root path and path items
|
||||
@@ -748,6 +743,13 @@ function FileManager:reinit(path, focused_file)
|
||||
-- self:onRefresh()
|
||||
end
|
||||
|
||||
FileManager.rotate = FileManager.reinit
|
||||
|
||||
-- So that the key navigation shortcuts apply right away.
|
||||
-- This will also naturally call registerKeyEvents
|
||||
FileManager.onPhysicalKeyboardConnected = FileManager.reinit
|
||||
FileManager.onPhysicalKeyboardDisconnected = FileManager.reinit
|
||||
|
||||
function FileManager:getCurrentDir()
|
||||
return FileManager.instance and FileManager.instance.file_chooser.path
|
||||
end
|
||||
|
||||
@@ -2454,11 +2454,11 @@ function ReaderFooter:onSwapPageTurnButtons()
|
||||
end
|
||||
ReaderFooter.onToggleReadingOrder = ReaderFooter.onSwapPageTurnButtons
|
||||
|
||||
function ReaderFooter:onSetRotationMode()
|
||||
function ReaderFooter:onSetDimensions()
|
||||
self:updateFooterContainer()
|
||||
self:resetLayout(true)
|
||||
end
|
||||
ReaderFooter.onScreenResize = ReaderFooter.onSetRotationMode
|
||||
ReaderFooter.onScreenResize = ReaderFooter.onSetDimensions
|
||||
|
||||
function ReaderFooter:onSetPageHorizMargins(h_margins)
|
||||
if self.settings.progress_margin then
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local Device = require("device")
|
||||
local Event = require("ui/event")
|
||||
local _ = require("gettext")
|
||||
|
||||
local ReaderRotation = InputContainer:extend{
|
||||
current_rotation = 0,
|
||||
}
|
||||
|
||||
function ReaderRotation:init()
|
||||
self:registerKeyEvents()
|
||||
-- NOP our own gesture handling
|
||||
self.ges_events = nil
|
||||
end
|
||||
|
||||
function ReaderRotation:onGesture() end
|
||||
|
||||
function ReaderRotation:registerKeyEvents()
|
||||
if Device:hasKeyboard() then
|
||||
self.key_events = {
|
||||
-- these will all generate the same event, just with different arguments
|
||||
RotateLeft = {
|
||||
{ "J" },
|
||||
event = "Rotate",
|
||||
args = -90
|
||||
},
|
||||
RotateRight = {
|
||||
{ "K" },
|
||||
event = "Rotate",
|
||||
args = 90
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
ReaderRotation.onPhysicalKeyboardConnected = ReaderRotation.registerKeyEvents
|
||||
|
||||
--- @todo Reset rotation on new document, maybe on new page?
|
||||
--- @fixme: More importantly, this breaks rendering, c.f., `Document:renderPage`
|
||||
-- A modern implementation of this feature is available in Dispatcher via the `IterateRotation` Event.
|
||||
function ReaderRotation:onRotate(rotate_by)
|
||||
self.current_rotation = (self.current_rotation + rotate_by) % 360
|
||||
self.ui:handleEvent(Event:new("RotationUpdate", self.current_rotation))
|
||||
return true
|
||||
end
|
||||
|
||||
return ReaderRotation
|
||||
@@ -836,13 +836,15 @@ function ReaderView:restoreViewContext(ctx)
|
||||
return false
|
||||
end
|
||||
|
||||
function ReaderView:onSetRotationMode(rotation)
|
||||
if rotation ~= nil then
|
||||
local old_rotation = Screen:getRotationMode()
|
||||
if rotation == old_rotation then
|
||||
return
|
||||
function ReaderView:onSetRotationMode(mode)
|
||||
local old_mode = Screen:getRotationMode()
|
||||
if mode ~= nil and mode ~= old_mode then
|
||||
Screen:setRotationMode(mode)
|
||||
self:rotate(mode, old_mode)
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderView:rotate(mode, old_mode)
|
||||
-- NOTE: We cannot rely on getScreenMode, as it actually checks the screen dimensions, instead of the rotation mode.
|
||||
-- (i.e., it returns how the screen *looks* like, not how it's oriented relative to its native layout).
|
||||
-- This would horribly break if you started in Portrait (both rotation and visually),
|
||||
@@ -850,26 +852,18 @@ function ReaderView:onSetRotationMode(rotation)
|
||||
-- If you then attempted to switch to a Landscape *rotation*, it would mistakenly think the layout hadn't changed!
|
||||
-- So, instead, as we're concerned with *rotation* layouts, just compare the two.
|
||||
-- We use LinuxFB-style constants, so, Portraits are even, Landscapes are odds, making this trivial.
|
||||
local matching_orientation = bit.band(rotation, 1) == bit.band(old_rotation, 1)
|
||||
|
||||
if rotation ~= old_rotation and matching_orientation then
|
||||
local matching_orientation = bit.band(mode, 1) == bit.band(old_mode, 1)
|
||||
if matching_orientation then
|
||||
-- No layout change, just rotate & repaint with a flash
|
||||
Screen:setRotationMode(rotation)
|
||||
UIManager:setDirty(self.dialog, "full")
|
||||
Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", rotation)))
|
||||
return
|
||||
end
|
||||
|
||||
Screen:setRotationMode(rotation)
|
||||
end
|
||||
|
||||
else
|
||||
UIManager:setDirty(nil, "full") -- SetDimensions will only request a partial, we want a flash
|
||||
local new_screen_size = Screen:getSize()
|
||||
self.ui:handleEvent(Event:new("SetDimensions", new_screen_size))
|
||||
self.ui:onScreenResize(new_screen_size)
|
||||
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
||||
Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", rotation)))
|
||||
return
|
||||
end
|
||||
Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", mode)))
|
||||
end
|
||||
|
||||
function ReaderView:onSetDimensions(dimensions)
|
||||
@@ -975,7 +969,7 @@ function ReaderView:onBBoxUpdate(bbox)
|
||||
self.use_bbox = bbox and true or false
|
||||
end
|
||||
|
||||
--- @note: From ReaderRotation, which is broken and disabled.
|
||||
--- @note: From ReaderRotation, which was broken, and has been removed in #12658
|
||||
function ReaderView:onRotationUpdate(rotation)
|
||||
self.state.rotation = rotation
|
||||
self:recalculate()
|
||||
|
||||
@@ -322,7 +322,7 @@ function ReaderZooming:onRestoreDimensions(dimensions)
|
||||
self:setZoom()
|
||||
end
|
||||
|
||||
--- @note: From ReaderRotation, which is broken and disabled.
|
||||
--- @note: From ReaderRotation, which was broken, and has been removed in #12658
|
||||
function ReaderZooming:onRotationUpdate(rotation)
|
||||
self.rotation = rotation
|
||||
self:setZoom()
|
||||
|
||||
@@ -43,7 +43,6 @@ local ReaderLink = require("apps/reader/modules/readerlink")
|
||||
local ReaderMenu = require("apps/reader/modules/readermenu")
|
||||
local ReaderPageMap = require("apps/reader/modules/readerpagemap")
|
||||
local ReaderPanning = require("apps/reader/modules/readerpanning")
|
||||
--local ReaderRotation = require("apps/reader/modules/readerrotation")
|
||||
local ReaderPaging = require("apps/reader/modules/readerpaging")
|
||||
local ReaderRolling = require("apps/reader/modules/readerrolling")
|
||||
local ReaderSearch = require("apps/reader/modules/readersearch")
|
||||
@@ -159,15 +158,6 @@ function ReaderUI:init()
|
||||
view = self.view,
|
||||
ui = self
|
||||
})
|
||||
-- (legacy, and defunct) rotation controller
|
||||
--- @fixme: Tripping this would break rendering, c.f., `Document:renderPage`
|
||||
--[[
|
||||
self:registerModule("rotation", ReaderRotation:new{
|
||||
dialog = self.dialog,
|
||||
view = self.view,
|
||||
ui = self
|
||||
})
|
||||
--]]
|
||||
-- Handmade/custom ToC and hidden flows
|
||||
self:registerModule("handmade", ReaderHandMade:new{
|
||||
dialog = self.dialog,
|
||||
|
||||
@@ -501,9 +501,9 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, hinting)
|
||||
-- Make the context match the rotation,
|
||||
-- by pointing at the rotated origin via coordinates offsets.
|
||||
-- NOTE: We rotate our *Screen* bb on rotation (SetRotationMode), not the document,
|
||||
-- so we hardly ever exercise this codepath...
|
||||
-- AFAICT, the only thing that will *ever* (attempt to) rotate the document is ReaderRotation's key bindings (RotationUpdate).
|
||||
--- @fixme: And whaddayano, it's broken ;). The aptly named key binds in question are J/K, I shit you not.
|
||||
-- so we hardly ever exercize this codepath...
|
||||
-- AFAICT, the only thing that *ever* (attempted to) rotate the document was ReaderRotation's key bindings (RotationUpdate).
|
||||
--- @note: It was broken as all hell (it had likely never worked outside of its original implementation in KPV), and has been removed in #12658
|
||||
if rotation == 90 then
|
||||
dc:setOffset(page_size.w, 0)
|
||||
elseif rotation == 180 then
|
||||
|
||||
@@ -237,6 +237,8 @@ function InputDialog:init()
|
||||
title_multilines = true,
|
||||
bottom_v_padding = self.bottom_v_padding,
|
||||
info_text = self.description,
|
||||
left_icon = self.title_bar_left_icon,
|
||||
left_icon_tap_callback = self.title_bar_left_icon_tap_callback,
|
||||
show_parent = self,
|
||||
}
|
||||
|
||||
@@ -475,6 +477,31 @@ function InputDialog:init()
|
||||
end
|
||||
end
|
||||
|
||||
function InputDialog:reinit()
|
||||
local visible = self:isKeyboardVisible()
|
||||
self.input = self:getInputText() -- re-init with up-to-date text
|
||||
self:onClose() -- will close keyboard and save view position
|
||||
self._input_widget:onCloseWidget() -- proper cleanup of InputText and its keyboard
|
||||
if self._added_widgets then
|
||||
-- prevent these externally added widgets from being freed as :init() will re-add them
|
||||
for i = 1, #self._added_widgets do
|
||||
table.remove(self.vgroup, #self.vgroup-2)
|
||||
end
|
||||
end
|
||||
self:free()
|
||||
-- Restore original text_height (or reset it if none to force recomputing it)
|
||||
self.text_height = self.orig_text_height or nil
|
||||
|
||||
-- Same deal as in toggleKeyboard...
|
||||
self.keyboard_visible = visible and true or false
|
||||
self:init()
|
||||
if self.keyboard_visible then
|
||||
self:onShowKeyboard()
|
||||
end
|
||||
-- Our position on screen has probably changed, so have the full screen refreshed
|
||||
UIManager:setDirty("all", "flashui")
|
||||
end
|
||||
|
||||
function InputDialog:addWidget(widget, re_init)
|
||||
table.insert(self.layout, #self.layout, {widget})
|
||||
if not re_init then -- backup widget for re-init
|
||||
@@ -677,30 +704,7 @@ function InputDialog:onKeyboardClosed()
|
||||
end
|
||||
end
|
||||
|
||||
function InputDialog:onKeyboardHeightChanged()
|
||||
local visible = self:isKeyboardVisible()
|
||||
self.input = self:getInputText() -- re-init with up-to-date text
|
||||
self:onClose() -- will close keyboard and save view position
|
||||
self._input_widget:onCloseWidget() -- proper cleanup of InputText and its keyboard
|
||||
if self._added_widgets then
|
||||
-- prevent these externally added widgets from being freed as :init() will re-add them
|
||||
for i = 1, #self._added_widgets do
|
||||
table.remove(self.vgroup, #self.vgroup-2)
|
||||
end
|
||||
end
|
||||
self:free()
|
||||
-- Restore original text_height (or reset it if none to force recomputing it)
|
||||
self.text_height = self.orig_text_height or nil
|
||||
|
||||
-- Same deal as in toggleKeyboard...
|
||||
self.keyboard_visible = visible
|
||||
self:init()
|
||||
if self.keyboard_visible then
|
||||
self:onShowKeyboard()
|
||||
end
|
||||
-- Our position on screen has probably changed, so have the full screen refreshed
|
||||
UIManager:setDirty("all", "flashui")
|
||||
end
|
||||
InputDialog.onKeyboardHeightChanged = InputDialog.reinit
|
||||
|
||||
function InputDialog:onCloseDialog()
|
||||
local close_button = self.button_table:getButtonById("close")
|
||||
@@ -724,6 +728,15 @@ function InputDialog:onClose()
|
||||
self:onCloseKeyboard()
|
||||
end
|
||||
|
||||
function InputDialog:onSetRotationMode(mode)
|
||||
if self.rotation_enabled and mode ~= nil then -- Text editor only
|
||||
self.rotation_mode_backup = self.rotation_mode_backup or Screen:getRotationMode() -- backup only initial mode
|
||||
Screen:setRotationMode(mode)
|
||||
self:reinit()
|
||||
return true -- we are the upper widget, stop event propagation
|
||||
end
|
||||
end
|
||||
|
||||
function InputDialog:refreshButtons()
|
||||
-- Using what ought to be enough:
|
||||
-- return "ui", self.button_table.dimen
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local BD = require("ui/bidi")
|
||||
local ButtonDialog = require("ui/widget/buttondialog")
|
||||
local ConfirmBox = require("ui/widget/confirmbox")
|
||||
local DataStorage = require("datastorage")
|
||||
local Dispatcher = require("dispatcher")
|
||||
@@ -438,7 +439,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file)
|
||||
-- No need to warn if readonly, the user will know it when we open
|
||||
-- without keyboard and the Save button says "Read only".
|
||||
local readonly = true
|
||||
local file = io.open(file_path, 'r+b')
|
||||
local file = io.open(file_path, "r+b")
|
||||
if file then
|
||||
file:close()
|
||||
readonly = false
|
||||
@@ -474,18 +475,6 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file)
|
||||
end
|
||||
end
|
||||
|
||||
function TextEditor:readFileContent(file_path)
|
||||
local file = io.open(file_path, "rb")
|
||||
if not file then
|
||||
-- We checked file existence before, so assume it's
|
||||
-- because it's a new file
|
||||
return ""
|
||||
end
|
||||
local file_content = file:read("*all")
|
||||
file:close()
|
||||
return file_content
|
||||
end
|
||||
|
||||
function TextEditor:saveFileContent(file_path, content)
|
||||
local ok, err = util.writeToFile(content, file_path)
|
||||
if ok then
|
||||
@@ -514,7 +503,6 @@ function TextEditor:editFile(file_path, readonly)
|
||||
local directory, filename = util.splitFilePathName(file_path) -- luacheck: no unused
|
||||
local filename_without_suffix, filetype = util.splitFileNameSuffix(filename) -- luacheck: no unused
|
||||
local is_lua = filetype:lower() == "lua"
|
||||
local input
|
||||
local para_direction_rtl = nil -- use UI language direction
|
||||
if self.force_ltr_para_direction then
|
||||
para_direction_rtl = false -- force LTR
|
||||
@@ -524,7 +512,7 @@ function TextEditor:editFile(file_path, readonly)
|
||||
table.insert(buttons_first_row, {
|
||||
text = _("Lua check"),
|
||||
callback = function()
|
||||
local parse_error = util.checkLuaSyntax(input:getInputText())
|
||||
local parse_error = util.checkLuaSyntax(self.input:getInputText())
|
||||
if parse_error then
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("Lua syntax check failed:\n\n%1"), parse_error)
|
||||
@@ -542,16 +530,16 @@ function TextEditor:editFile(file_path, readonly)
|
||||
text = _("QR"),
|
||||
callback = function()
|
||||
UIManager:show(QRMessage:new{
|
||||
text = input:getInputText(),
|
||||
text = self.input:getInputText(),
|
||||
height = Screen:getHeight(),
|
||||
width = Screen:getWidth()
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
input = InputDialog:new{
|
||||
self.input = InputDialog:new{
|
||||
title = filename,
|
||||
input = self:readFileContent(file_path),
|
||||
input = util.readFromFile(file_path, "rb"),
|
||||
input_face = Font:getFace(self.font_face, self.font_size),
|
||||
para_direction_rtl = para_direction_rtl,
|
||||
auto_para_direction = self.auto_para_direction,
|
||||
@@ -561,6 +549,9 @@ function TextEditor:editFile(file_path, readonly)
|
||||
cursor_at_end = false,
|
||||
readonly = readonly,
|
||||
add_nav_bar = true,
|
||||
title_bar_left_icon = "appbar.menu",
|
||||
title_bar_left_icon_tap_callback = function() self:showMenu() end,
|
||||
rotation_enabled = true,
|
||||
keyboard_visible = self.show_keyboard_on_start, -- InputDialog will enforce false if readonly
|
||||
scroll_by_pan = true,
|
||||
buttons = {buttons_first_row},
|
||||
@@ -580,10 +571,13 @@ function TextEditor:editFile(file_path, readonly)
|
||||
end,
|
||||
-- File restoring callback
|
||||
reset_callback = function(content) -- Will add a Reset button
|
||||
return self:readFileContent(file_path), _("Text reset to last saved content")
|
||||
return util.readFromFile(file_path, "rb") or "", _("Text reset to last saved content")
|
||||
end,
|
||||
-- Close callback
|
||||
close_callback = function()
|
||||
if self.input.rotation_mode_backup and self.input.rotation_mode_backup ~= Screen:getRotationMode() then
|
||||
Screen:setRotationMode(self.input.rotation_mode_backup)
|
||||
end
|
||||
self:execWhenDoneFunc()
|
||||
end,
|
||||
-- File saving callback
|
||||
@@ -656,9 +650,9 @@ Do you want to keep this file as empty, or do you prefer to delete it?
|
||||
end,
|
||||
|
||||
}
|
||||
UIManager:show(input)
|
||||
UIManager:show(self.input)
|
||||
if self.show_keyboard_on_start and not readonly then
|
||||
input:onShowKeyboard()
|
||||
self.input:onShowKeyboard()
|
||||
end
|
||||
-- Note about readonly:
|
||||
-- We might have liked to still show keyboard even if readonly, just
|
||||
@@ -688,4 +682,32 @@ function TextEditor:quickEditFile(file_path, done_callback, possible_new_file)
|
||||
self:checkEditFile(file_path, possible_new_file or false)
|
||||
end
|
||||
|
||||
-- TitleBar left button tap
|
||||
function TextEditor:showMenu()
|
||||
local dialog
|
||||
local buttons = {}
|
||||
local optionsutil = require("ui/data/optionsutil")
|
||||
for i, mode in ipairs(optionsutil.rotation_modes) do
|
||||
buttons[i] = {{
|
||||
text = optionsutil.rotation_labels[i],
|
||||
enabled_func = function()
|
||||
return optionsutil.rotation_modes[i] ~= Screen:getRotationMode()
|
||||
end,
|
||||
callback = function()
|
||||
UIManager:close(dialog)
|
||||
self.input:onSetRotationMode(optionsutil.rotation_modes[i])
|
||||
end,
|
||||
}}
|
||||
end
|
||||
dialog = ButtonDialog:new{
|
||||
shrink_unneeded_width = true,
|
||||
buttons = buttons,
|
||||
anchor = function()
|
||||
return self.input.title_bar.left_button.image.dimen
|
||||
end,
|
||||
modal = true,
|
||||
}
|
||||
UIManager:show(dialog)
|
||||
end
|
||||
|
||||
return TextEditor
|
||||
|
||||
Reference in New Issue
Block a user