mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
cleanup: expand tab to 4 spaces
This commit is contained in:
34
defaults.lua
34
defaults.lua
@@ -69,26 +69,26 @@ DTAP_ZONE_BOOKMARK = {x = 7/8, y = 0, w = 1/8, h = 1/8}
|
|||||||
DTAP_ZONE_FLIPPING = {x = 0, y = 0, w = 1/8, h = 1/8}
|
DTAP_ZONE_FLIPPING = {x = 0, y = 0, w = 1/8, h = 1/8}
|
||||||
|
|
||||||
-- koptreader config defaults
|
-- koptreader config defaults
|
||||||
DKOPTREADER_CONFIG_FONT_SIZE = 1.0 -- range from 0.1 to 3.0
|
DKOPTREADER_CONFIG_FONT_SIZE = 1.0 -- range from 0.1 to 3.0
|
||||||
DKOPTREADER_CONFIG_TEXT_WRAP = 0 -- 1 = on, 0 = off
|
DKOPTREADER_CONFIG_TEXT_WRAP = 0 -- 1 = on, 0 = off
|
||||||
DKOPTREADER_CONFIG_TRIM_PAGE = 1 -- 1 = auto, 0 = manual
|
DKOPTREADER_CONFIG_TRIM_PAGE = 1 -- 1 = auto, 0 = manual
|
||||||
DKOPTREADER_CONFIG_DETECT_INDENT = 1 -- 1 = enable, 0 = disable
|
DKOPTREADER_CONFIG_DETECT_INDENT = 1 -- 1 = enable, 0 = disable
|
||||||
DKOPTREADER_CONFIG_DEFECT_SIZE = 1.0 -- range from 0.0 to 3.0
|
DKOPTREADER_CONFIG_DEFECT_SIZE = 1.0 -- range from 0.0 to 3.0
|
||||||
DKOPTREADER_CONFIG_PAGE_MARGIN = 0.10 -- range from 0.0 to 1.0
|
DKOPTREADER_CONFIG_PAGE_MARGIN = 0.10 -- range from 0.0 to 1.0
|
||||||
DKOPTREADER_CONFIG_LINE_SPACING = 1.2 -- range from 0.5 to 2.0
|
DKOPTREADER_CONFIG_LINE_SPACING = 1.2 -- range from 0.5 to 2.0
|
||||||
DKOPTREADER_CONFIG_RENDER_QUALITY = 1.0 -- range from 0.5 to 2.0
|
DKOPTREADER_CONFIG_RENDER_QUALITY = 1.0 -- range from 0.5 to 2.0
|
||||||
DKOPTREADER_CONFIG_AUTO_STRAIGHTEN = 0 -- range from 0 to 10
|
DKOPTREADER_CONFIG_AUTO_STRAIGHTEN = 0 -- range from 0 to 10
|
||||||
DKOPTREADER_CONFIG_JUSTIFICATION = 3 -- -1 = auto, 0 = left, 1 = center, 2 = right, 3 = full
|
DKOPTREADER_CONFIG_JUSTIFICATION = 3 -- -1 = auto, 0 = left, 1 = center, 2 = right, 3 = full
|
||||||
DKOPTREADER_CONFIG_MAX_COLUMNS = 2 -- range from 1 to 4
|
DKOPTREADER_CONFIG_MAX_COLUMNS = 2 -- range from 1 to 4
|
||||||
DKOPTREADER_CONFIG_CONTRAST = 1.0 -- range from 0.2 to 2.0
|
DKOPTREADER_CONFIG_CONTRAST = 1.0 -- range from 0.2 to 2.0
|
||||||
|
|
||||||
-- word spacing for reflow
|
-- word spacing for reflow
|
||||||
DKOPTREADER_CONFIG_WORD_SAPCINGS = {0.05, -1, 0.375} -- range from 0.05 to 0.5
|
DKOPTREADER_CONFIG_WORD_SAPCINGS = {0.05, -1, 0.375} -- range from 0.05 to 0.5
|
||||||
DKOPTREADER_CONFIG_DEFAULT_WORD_SAPCING = -1 -- range from 0.05 to 0.5
|
DKOPTREADER_CONFIG_DEFAULT_WORD_SAPCING = -1 -- range from 0.05 to 0.5
|
||||||
-- document languages for OCR
|
-- document languages for OCR
|
||||||
DKOPTREADER_CONFIG_DOC_LANGS_TEXT = {"English", "Chinese"}
|
DKOPTREADER_CONFIG_DOC_LANGS_TEXT = {"English", "Chinese"}
|
||||||
DKOPTREADER_CONFIG_DOC_LANGS_CODE = {"eng", "chi_sim"} -- language code, make sure you have corresponding training data
|
DKOPTREADER_CONFIG_DOC_LANGS_CODE = {"eng", "chi_sim"} -- language code, make sure you have corresponding training data
|
||||||
DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE = "eng" -- that have filenames starting with the language codes
|
DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE = "eng" -- that have filenames starting with the language codes
|
||||||
|
|
||||||
-- crereader font sizes
|
-- crereader font sizes
|
||||||
-- feel free to add more entries in this list
|
-- feel free to add more entries in this list
|
||||||
@@ -170,5 +170,5 @@ DDICT_FONT_SIZE = 20
|
|||||||
--DPICVIEWER_PAGE_MODE_ENABLE = false
|
--DPICVIEWER_PAGE_MODE_ENABLE = false
|
||||||
|
|
||||||
|
|
||||||
--DKOPTREADER_CONFIG_MULTI_THREADS = 1 -- 1 = on, 0 = off
|
--DKOPTREADER_CONFIG_MULTI_THREADS = 1 -- 1 = on, 0 = off
|
||||||
--DKOPTREADER_CONFIG_SCREEN_ROTATION = 0 -- 0, 90, 180, 270 degrees
|
--DKOPTREADER_CONFIG_SCREEN_ROTATION = 0 -- 0, 90, 180, 270 degrees
|
||||||
|
|||||||
@@ -17,175 +17,175 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local FileManager = InputContainer:extend{
|
local FileManager = InputContainer:extend{
|
||||||
title = _("FileManager"),
|
title = _("FileManager"),
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
height = Screen:getHeight(),
|
height = Screen:getHeight(),
|
||||||
root_path = lfs.currentdir(),
|
root_path = lfs.currentdir(),
|
||||||
-- our own size
|
-- our own size
|
||||||
dimen = Geom:new{ w = 400, h = 600 },
|
dimen = Geom:new{ w = 400, h = 600 },
|
||||||
onExit = function() end,
|
onExit = function() end,
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileManager:init()
|
function FileManager:init()
|
||||||
local exclude_dirs = {"%.sdr$"}
|
local exclude_dirs = {"%.sdr$"}
|
||||||
|
|
||||||
self.show_parent = self.show_parent or self
|
self.show_parent = self.show_parent or self
|
||||||
|
|
||||||
self.banner = VerticalGroup:new{
|
self.banner = VerticalGroup:new{
|
||||||
TextWidget:new{
|
TextWidget:new{
|
||||||
face = Font:getFace("tfont", 24),
|
face = Font:getFace("tfont", 24),
|
||||||
text = self.title,
|
text = self.title,
|
||||||
},
|
},
|
||||||
VerticalSpan:new{ width = Screen:scaleByDPI(10) }
|
VerticalSpan:new{ width = Screen:scaleByDPI(10) }
|
||||||
}
|
}
|
||||||
|
|
||||||
local g_show_hidden = G_reader_settings:readSetting("show_hidden")
|
local g_show_hidden = G_reader_settings:readSetting("show_hidden")
|
||||||
local show_hidden = g_show_hidden == nil and DSHOWHIDDENFILES or g_show_hidden
|
local show_hidden = g_show_hidden == nil and DSHOWHIDDENFILES or g_show_hidden
|
||||||
local file_chooser = FileChooser:new{
|
local file_chooser = FileChooser:new{
|
||||||
-- remeber to adjust the height when new item is added to the group
|
-- remeber to adjust the height when new item is added to the group
|
||||||
path = self.root_path,
|
path = self.root_path,
|
||||||
show_parent = self.show_parent,
|
show_parent = self.show_parent,
|
||||||
show_hidden = show_hidden,
|
show_hidden = show_hidden,
|
||||||
height = Screen:getHeight() - self.banner:getSize().h,
|
height = Screen:getHeight() - self.banner:getSize().h,
|
||||||
is_popout = false,
|
is_popout = false,
|
||||||
is_borderless = true,
|
is_borderless = true,
|
||||||
has_close_button = true,
|
has_close_button = true,
|
||||||
dir_filter = function(dirname)
|
dir_filter = function(dirname)
|
||||||
for _, pattern in ipairs(exclude_dirs) do
|
for _, pattern in ipairs(exclude_dirs) do
|
||||||
if dirname:match(pattern) then return end
|
if dirname:match(pattern) then return end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
file_filter = function(filename)
|
file_filter = function(filename)
|
||||||
if DocumentRegistry:getProvider(filename) then
|
if DocumentRegistry:getProvider(filename) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
self.file_chooser = file_chooser
|
self.file_chooser = file_chooser
|
||||||
|
|
||||||
function file_chooser:onFileSelect(file)
|
function file_chooser:onFileSelect(file)
|
||||||
showReaderUI(file)
|
showReaderUI(file)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local copyFile = function(file) self:copyFile(file) end
|
local copyFile = function(file) self:copyFile(file) end
|
||||||
local pasteHere = function(file) self:pasteHere(file) end
|
local pasteHere = function(file) self:pasteHere(file) end
|
||||||
local cutFile = function(file) self:cutFile(file) end
|
local cutFile = function(file) self:cutFile(file) end
|
||||||
local deleteFile = function(file) self:deleteFile(file) end
|
local deleteFile = function(file) self:deleteFile(file) end
|
||||||
local fileManager = self
|
local fileManager = self
|
||||||
|
|
||||||
function file_chooser:onFileHold(file)
|
function file_chooser:onFileHold(file)
|
||||||
--DEBUG("hold file", file)
|
--DEBUG("hold file", file)
|
||||||
self.file_dialog = ButtonDialog:new{
|
self.file_dialog = ButtonDialog:new{
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Copy"),
|
text = _("Copy"),
|
||||||
callback = function()
|
callback = function()
|
||||||
copyFile(file)
|
copyFile(file)
|
||||||
UIManager:close(self.file_dialog)
|
UIManager:close(self.file_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Paste"),
|
text = _("Paste"),
|
||||||
enabled = fileManager.clipboard and true or false,
|
enabled = fileManager.clipboard and true or false,
|
||||||
callback = function()
|
callback = function()
|
||||||
pasteHere(file)
|
pasteHere(file)
|
||||||
self:refreshPath()
|
self:refreshPath()
|
||||||
UIManager:close(self.file_dialog)
|
UIManager:close(self.file_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Cut"),
|
text = _("Cut"),
|
||||||
callback = function()
|
callback = function()
|
||||||
cutFile(file)
|
cutFile(file)
|
||||||
UIManager:close(self.file_dialog)
|
UIManager:close(self.file_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Delete"),
|
text = _("Delete"),
|
||||||
callback = function()
|
callback = function()
|
||||||
local path = util.realpath(file)
|
local path = util.realpath(file)
|
||||||
deleteFile(file)
|
deleteFile(file)
|
||||||
self:refreshPath()
|
self:refreshPath()
|
||||||
UIManager:close(self.file_dialog)
|
UIManager:close(self.file_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
UIManager:show(self.file_dialog)
|
UIManager:show(self.file_dialog)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
self.layout = VerticalGroup:new{
|
self.layout = VerticalGroup:new{
|
||||||
self.banner,
|
self.banner,
|
||||||
file_chooser,
|
file_chooser,
|
||||||
}
|
}
|
||||||
|
|
||||||
local fm_ui = FrameContainer:new{
|
local fm_ui = FrameContainer:new{
|
||||||
padding = 0,
|
padding = 0,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
background = 0,
|
background = 0,
|
||||||
self.layout,
|
self.layout,
|
||||||
}
|
}
|
||||||
|
|
||||||
self[1] = fm_ui
|
self[1] = fm_ui
|
||||||
|
|
||||||
self.menu = FileManagerMenu:new{
|
self.menu = FileManagerMenu:new{
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
table.insert(self, self.menu)
|
table.insert(self, self.menu)
|
||||||
table.insert(self, FileManagerHistory:new{
|
table.insert(self, FileManagerHistory:new{
|
||||||
ui = self,
|
ui = self,
|
||||||
menu = self.menu
|
menu = self.menu
|
||||||
})
|
})
|
||||||
|
|
||||||
self:handleEvent(Event:new("SetDimensions", self.dimen))
|
self:handleEvent(Event:new("SetDimensions", self.dimen))
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:toggleHiddenFiles()
|
function FileManager:toggleHiddenFiles()
|
||||||
self.file_chooser:toggleHiddenFiles()
|
self.file_chooser:toggleHiddenFiles()
|
||||||
G_reader_settings:saveSetting("show_hidden", self.file_chooser.show_hidden)
|
G_reader_settings:saveSetting("show_hidden", self.file_chooser.show_hidden)
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:onClose()
|
function FileManager:onClose()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
if self.onExit then
|
if self.onExit then
|
||||||
self:onExit()
|
self:onExit()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:copyFile(file)
|
function FileManager:copyFile(file)
|
||||||
self.cutfile = false
|
self.cutfile = false
|
||||||
self.clipboard = file
|
self.clipboard = file
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:cutFile(file)
|
function FileManager:cutFile(file)
|
||||||
self.cutfile = true
|
self.cutfile = true
|
||||||
self.clipboard = file
|
self.clipboard = file
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:pasteHere(file)
|
function FileManager:pasteHere(file)
|
||||||
if self.clipboard then
|
if self.clipboard then
|
||||||
file = util.realpath(file)
|
file = util.realpath(file)
|
||||||
local orig = util.realpath(self.clipboard)
|
local orig = util.realpath(self.clipboard)
|
||||||
local dest = lfs.attributes(file, "mode") == "directory" and
|
local dest = lfs.attributes(file, "mode") == "directory" and
|
||||||
file or file:match("(.*/)")
|
file or file:match("(.*/)")
|
||||||
if self.cutfile then
|
if self.cutfile then
|
||||||
util.execute("/bin/mv", orig, dest)
|
util.execute("/bin/mv", orig, dest)
|
||||||
else
|
else
|
||||||
util.execute("/bin/cp", "-r", orig, dest)
|
util.execute("/bin/cp", "-r", orig, dest)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManager:deleteFile(file)
|
function FileManager:deleteFile(file)
|
||||||
util.execute("/bin/rm", "-r", util.realpath(file))
|
util.execute("/bin/rm", "-r", util.realpath(file))
|
||||||
end
|
end
|
||||||
|
|
||||||
return FileManager
|
return FileManager
|
||||||
|
|||||||
@@ -11,103 +11,103 @@ local _ = require("gettext")
|
|||||||
local history_dir = "./history/"
|
local history_dir = "./history/"
|
||||||
|
|
||||||
local FileManagerHistory = InputContainer:extend{
|
local FileManagerHistory = InputContainer:extend{
|
||||||
hist_menu_title = _("History"),
|
hist_menu_title = _("History"),
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileManagerHistory:init()
|
function FileManagerHistory:init()
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerHistory:onSetDimensions(dimen)
|
function FileManagerHistory:onSetDimensions(dimen)
|
||||||
self.dimen = dimen
|
self.dimen = dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerHistory:onMenuHold(item)
|
function FileManagerHistory:onMenuHold(item)
|
||||||
self.histfile_dialog = ButtonDialog:new{
|
self.histfile_dialog = ButtonDialog:new{
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Delete"),
|
text = _("Delete"),
|
||||||
callback = function()
|
callback = function()
|
||||||
os.remove(history_dir..item.histfile)
|
os.remove(history_dir..item.histfile)
|
||||||
self._manager:updateItemTable()
|
self._manager:updateItemTable()
|
||||||
UIManager:close(self.histfile_dialog)
|
UIManager:close(self.histfile_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
UIManager:show(self.histfile_dialog)
|
UIManager:show(self.histfile_dialog)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerHistory:onShowHist()
|
function FileManagerHistory:onShowHist()
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.hist_menu = Menu:new{
|
self.hist_menu = Menu:new{
|
||||||
ui = self.ui,
|
ui = self.ui,
|
||||||
width = Screen:getWidth()-50,
|
width = Screen:getWidth()-50,
|
||||||
height = Screen:getHeight()-50,
|
height = Screen:getHeight()-50,
|
||||||
show_parent = menu_container,
|
show_parent = menu_container,
|
||||||
onMenuHold = self.onMenuHold,
|
onMenuHold = self.onMenuHold,
|
||||||
_manager = self,
|
_manager = self,
|
||||||
}
|
}
|
||||||
self:updateItemTable()
|
self:updateItemTable()
|
||||||
|
|
||||||
table.insert(menu_container, self.hist_menu)
|
table.insert(menu_container, self.hist_menu)
|
||||||
|
|
||||||
self.hist_menu.close_callback = function()
|
self.hist_menu.close_callback = function()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerHistory:addToMainMenu(tab_item_table)
|
function FileManagerHistory:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.main, {
|
table.insert(tab_item_table.main, {
|
||||||
text = self.hist_menu_title,
|
text = self.hist_menu_title,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:onShowHist()
|
self:onShowHist()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerHistory:updateItemTable()
|
function FileManagerHistory:updateItemTable()
|
||||||
function readHistDir(re)
|
function readHistDir(re)
|
||||||
local sorted_files = {}
|
local sorted_files = {}
|
||||||
for f in lfs.dir(history_dir) do
|
for f in lfs.dir(history_dir) do
|
||||||
local path = history_dir..f
|
local path = history_dir..f
|
||||||
if lfs.attributes(path, "mode") == "file" then
|
if lfs.attributes(path, "mode") == "file" then
|
||||||
table.insert(sorted_files, {file = f, date = lfs.attributes(path, "modification")})
|
table.insert(sorted_files, {file = f, date = lfs.attributes(path, "modification")})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(sorted_files, function(v1,v2) return v1.date > v2.date end)
|
table.sort(sorted_files, function(v1,v2) return v1.date > v2.date end)
|
||||||
for _, v in pairs(sorted_files) do
|
for _, v in pairs(sorted_files) do
|
||||||
table.insert(re, {
|
table.insert(re, {
|
||||||
dir = DocSettings:getPathFromHistory(v.file),
|
dir = DocSettings:getPathFromHistory(v.file),
|
||||||
name = DocSettings:getNameFromHistory(v.file),
|
name = DocSettings:getNameFromHistory(v.file),
|
||||||
histfile = v.file,
|
histfile = v.file,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.hist = {}
|
self.hist = {}
|
||||||
local last_files = {}
|
local last_files = {}
|
||||||
readHistDir(last_files)
|
readHistDir(last_files)
|
||||||
for _,v in pairs(last_files) do
|
for _,v in pairs(last_files) do
|
||||||
table.insert(self.hist, {
|
table.insert(self.hist, {
|
||||||
text = v.name,
|
text = v.name,
|
||||||
histfile = v.histfile,
|
histfile = v.histfile,
|
||||||
callback = function()
|
callback = function()
|
||||||
showReaderUI(v.dir .. "/" .. v.name)
|
showReaderUI(v.dir .. "/" .. v.name)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
self.hist_menu:swithItemTable(self.hist_menu_title, self.hist)
|
self.hist_menu:swithItemTable(self.hist_menu_title, self.hist)
|
||||||
end
|
end
|
||||||
|
|
||||||
return FileManagerHistory
|
return FileManagerHistory
|
||||||
|
|||||||
@@ -12,143 +12,143 @@ local Language = require("ui/language")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local FileManagerMenu = InputContainer:extend{
|
local FileManagerMenu = InputContainer:extend{
|
||||||
tab_item_table = nil,
|
tab_item_table = nil,
|
||||||
registered_widgets = {},
|
registered_widgets = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileManagerMenu:init()
|
function FileManagerMenu:init()
|
||||||
self.tab_item_table = {
|
self.tab_item_table = {
|
||||||
main = {
|
main = {
|
||||||
icon = "resources/icons/appbar.pokeball.png",
|
icon = "resources/icons/appbar.pokeball.png",
|
||||||
},
|
},
|
||||||
home = {
|
home = {
|
||||||
icon = "resources/icons/appbar.home.png",
|
icon = "resources/icons/appbar.home.png",
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:close(self.menu_container)
|
UIManager:close(self.menu_container)
|
||||||
self.ui:onClose()
|
self.ui:onClose()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
self.registered_widgets = {}
|
self.registered_widgets = {}
|
||||||
|
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowMenu = { { "Menu" }, doc = _("show menu") },
|
ShowMenu = { { "Menu" }, doc = _("show menu") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:initGesListener()
|
function FileManagerMenu:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapShowMenu = {
|
TapShowMenu = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
w = Screen:getWidth()*3/4,
|
w = Screen:getWidth()*3/4,
|
||||||
h = Screen:getHeight()/4,
|
h = Screen:getHeight()/4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:setUpdateItemTable()
|
function FileManagerMenu:setUpdateItemTable()
|
||||||
for _, widget in pairs(self.registered_widgets) do
|
for _, widget in pairs(self.registered_widgets) do
|
||||||
widget:addToMainMenu(self.tab_item_table)
|
widget:addToMainMenu(self.tab_item_table)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.tab_item_table.main, {
|
table.insert(self.tab_item_table.main, {
|
||||||
text = _("Toggle hidden files"),
|
text = _("Toggle hidden files"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self.ui:toggleHiddenFiles()
|
self.ui:toggleHiddenFiles()
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
if Device:hasFrontlight() then
|
if Device:hasFrontlight() then
|
||||||
ReaderFrontLight:addToMainMenu(self.tab_item_table)
|
ReaderFrontLight:addToMainMenu(self.tab_item_table)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.tab_item_table.main, {
|
table.insert(self.tab_item_table.main, {
|
||||||
text = _("Help"),
|
text = _("Help"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Please report bugs to https://github.com/koreader/ koreader/issues, Click at the bottom of the page for more options"),
|
text = _("Please report bugs to https://github.com/koreader/ koreader/issues, Click at the bottom of the page for more options"),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
table.insert(self.tab_item_table.main, {
|
table.insert(self.tab_item_table.main, {
|
||||||
text = _("Version"),
|
text = _("Version"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = io.open("git-rev", "r"):read(),
|
text = io.open("git-rev", "r"):read(),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
table.insert(self.tab_item_table.main, Language:getLangMenuTable())
|
table.insert(self.tab_item_table.main, Language:getLangMenuTable())
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:onShowMenu()
|
function FileManagerMenu:onShowMenu()
|
||||||
if #self.tab_item_table.main == 0 then
|
if #self.tab_item_table.main == 0 then
|
||||||
self:setUpdateItemTable()
|
self:setUpdateItemTable()
|
||||||
end
|
end
|
||||||
|
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
ignore = "height",
|
ignore = "height",
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
|
|
||||||
local main_menu = nil
|
local main_menu = nil
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
main_menu = TouchMenu:new{
|
main_menu = TouchMenu:new{
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
tab_item_table = {
|
tab_item_table = {
|
||||||
self.tab_item_table.main,
|
self.tab_item_table.main,
|
||||||
self.tab_item_table.home,
|
self.tab_item_table.home,
|
||||||
},
|
},
|
||||||
show_parent = menu_container,
|
show_parent = menu_container,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
main_menu = Menu:new{
|
main_menu = Menu:new{
|
||||||
title = _("File manager menu"),
|
title = _("File manager menu"),
|
||||||
item_table = {},
|
item_table = {},
|
||||||
width = Screen:getWidth() - 100,
|
width = Screen:getWidth() - 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _,item_table in pairs(self.tab_item_table) do
|
for _,item_table in pairs(self.tab_item_table) do
|
||||||
for k,v in ipairs(item_table) do
|
for k,v in ipairs(item_table) do
|
||||||
table.insert(main_menu.item_table, v)
|
table.insert(main_menu.item_table, v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main_menu.close_callback = function ()
|
main_menu.close_callback = function ()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
menu_container[1] = main_menu
|
menu_container[1] = main_menu
|
||||||
-- maintain a reference to menu_container
|
-- maintain a reference to menu_container
|
||||||
self.menu_container = menu_container
|
self.menu_container = menu_container
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:onTapShowMenu()
|
function FileManagerMenu:onTapShowMenu()
|
||||||
self:onShowMenu()
|
self:onShowMenu()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:onSetDimensions(dimen)
|
function FileManagerMenu:onSetDimensions(dimen)
|
||||||
-- update listening according to new screen dimen
|
-- update listening according to new screen dimen
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileManagerMenu:registerToMainMenu(widget)
|
function FileManagerMenu:registerToMainMenu(widget)
|
||||||
table.insert(self.registered_widgets, widget)
|
table.insert(self.registered_widgets, widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
return FileManagerMenu
|
return FileManagerMenu
|
||||||
|
|||||||
@@ -2,98 +2,98 @@
|
|||||||
A global LRU cache
|
A global LRU cache
|
||||||
]]--
|
]]--
|
||||||
local function calcFreeMem()
|
local function calcFreeMem()
|
||||||
local meminfo = io.open("/proc/meminfo", "r")
|
local meminfo = io.open("/proc/meminfo", "r")
|
||||||
local freemem = 0
|
local freemem = 0
|
||||||
if meminfo then
|
if meminfo then
|
||||||
for line in meminfo:lines() do
|
for line in meminfo:lines() do
|
||||||
local free, buffer, cached, n
|
local free, buffer, cached, n
|
||||||
free, n = line:gsub("^MemFree:%s-(%d+) kB", "%1")
|
free, n = line:gsub("^MemFree:%s-(%d+) kB", "%1")
|
||||||
if n ~= 0 then freemem = freemem + tonumber(free)*1024 end
|
if n ~= 0 then freemem = freemem + tonumber(free)*1024 end
|
||||||
buffer, n = line:gsub("^Buffers:%s-(%d+) kB", "%1")
|
buffer, n = line:gsub("^Buffers:%s-(%d+) kB", "%1")
|
||||||
if n ~= 0 then freemem = freemem + tonumber(buffer)*1024 end
|
if n ~= 0 then freemem = freemem + tonumber(buffer)*1024 end
|
||||||
cached, n = line:gsub("^Cached:%s-(%d+) kB", "%1")
|
cached, n = line:gsub("^Cached:%s-(%d+) kB", "%1")
|
||||||
if n ~= 0 then freemem = freemem + tonumber(cached)*1024 end
|
if n ~= 0 then freemem = freemem + tonumber(cached)*1024 end
|
||||||
end
|
end
|
||||||
meminfo:close()
|
meminfo:close()
|
||||||
end
|
end
|
||||||
return freemem
|
return freemem
|
||||||
end
|
end
|
||||||
|
|
||||||
local function calcCacheMemSize()
|
local function calcCacheMemSize()
|
||||||
local min = DGLOBAL_CACHE_SIZE_MINIMUM
|
local min = DGLOBAL_CACHE_SIZE_MINIMUM
|
||||||
local max = DGLOBAL_CACHE_SIZE_MAXIMUM
|
local max = DGLOBAL_CACHE_SIZE_MAXIMUM
|
||||||
local calc = calcFreeMem()*(DGLOBAL_CACHE_FREE_PROPORTION or 0)
|
local calc = calcFreeMem()*(DGLOBAL_CACHE_FREE_PROPORTION or 0)
|
||||||
return math.min(max, math.max(min, calc))
|
return math.min(max, math.max(min, calc))
|
||||||
end
|
end
|
||||||
|
|
||||||
local Cache = {
|
local Cache = {
|
||||||
-- cache configuration:
|
-- cache configuration:
|
||||||
max_memsize = calcCacheMemSize(),
|
max_memsize = calcCacheMemSize(),
|
||||||
-- cache state:
|
-- cache state:
|
||||||
current_memsize = 0,
|
current_memsize = 0,
|
||||||
-- associative cache
|
-- associative cache
|
||||||
cache = {},
|
cache = {},
|
||||||
-- this will hold the LRU order of the cache
|
-- this will hold the LRU order of the cache
|
||||||
cache_order = {}
|
cache_order = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Cache:new(o)
|
function Cache:new(o)
|
||||||
o = o or {}
|
o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cache:insert(key, object)
|
function Cache:insert(key, object)
|
||||||
-- guarantee that we have enough memory in cache
|
-- guarantee that we have enough memory in cache
|
||||||
if(object.size > self.max_memsize) then
|
if(object.size > self.max_memsize) then
|
||||||
-- we're not allowed to claim this much at all
|
-- we're not allowed to claim this much at all
|
||||||
error("too much memory claimed")
|
error("too much memory claimed")
|
||||||
end
|
end
|
||||||
-- delete objects that least recently used
|
-- delete objects that least recently used
|
||||||
-- (they are at the end of the cache_order array)
|
-- (they are at the end of the cache_order array)
|
||||||
while self.current_memsize + object.size > self.max_memsize do
|
while self.current_memsize + object.size > self.max_memsize do
|
||||||
local removed_key = table.remove(self.cache_order)
|
local removed_key = table.remove(self.cache_order)
|
||||||
self.current_memsize = self.current_memsize - self.cache[removed_key].size
|
self.current_memsize = self.current_memsize - self.cache[removed_key].size
|
||||||
self.cache[removed_key]:onFree()
|
self.cache[removed_key]:onFree()
|
||||||
self.cache[removed_key] = nil
|
self.cache[removed_key] = nil
|
||||||
end
|
end
|
||||||
-- insert new object in front of the LRU order
|
-- insert new object in front of the LRU order
|
||||||
table.insert(self.cache_order, 1, key)
|
table.insert(self.cache_order, 1, key)
|
||||||
self.cache[key] = object
|
self.cache[key] = object
|
||||||
self.current_memsize = self.current_memsize + object.size
|
self.current_memsize = self.current_memsize + object.size
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cache:check(key)
|
function Cache:check(key)
|
||||||
if self.cache[key] then
|
if self.cache[key] then
|
||||||
if self.cache_order[1] ~= key then
|
if self.cache_order[1] ~= key then
|
||||||
-- put key in front of the LRU list
|
-- put key in front of the LRU list
|
||||||
for k, v in ipairs(self.cache_order) do
|
for k, v in ipairs(self.cache_order) do
|
||||||
if v == key then
|
if v == key then
|
||||||
table.remove(self.cache_order, k)
|
table.remove(self.cache_order, k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(self.cache_order, 1, key)
|
table.insert(self.cache_order, 1, key)
|
||||||
end
|
end
|
||||||
return self.cache[key]
|
return self.cache[key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cache:willAccept(size)
|
function Cache:willAccept(size)
|
||||||
-- we only allow single objects to fill 75% of the cache
|
-- we only allow single objects to fill 75% of the cache
|
||||||
if size*4 < self.max_memsize*3 then
|
if size*4 < self.max_memsize*3 then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- blank the cache
|
-- blank the cache
|
||||||
function Cache:clear()
|
function Cache:clear()
|
||||||
for k, _ in pairs(self.cache) do
|
for k, _ in pairs(self.cache) do
|
||||||
self.cache[k]:onFree()
|
self.cache[k]:onFree()
|
||||||
end
|
end
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
self.cache_order = {}
|
self.cache_order = {}
|
||||||
self.current_memsize = 0
|
self.current_memsize = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
return Cache
|
return Cache
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ Inheritable abstraction for cache items
|
|||||||
--]]
|
--]]
|
||||||
|
|
||||||
local CacheItem = {
|
local CacheItem = {
|
||||||
size = 64, -- some reasonable default for simple Lua values / small tables
|
size = 64, -- some reasonable default for simple Lua values / small tables
|
||||||
}
|
}
|
||||||
|
|
||||||
function CacheItem:new(o)
|
function CacheItem:new(o)
|
||||||
o = o or {}
|
o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function CacheItem:onFree()
|
function CacheItem:onFree()
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
local DocSettings = require("docsettings") -- for dump method
|
local DocSettings = require("docsettings") -- for dump method
|
||||||
|
|
||||||
local Dbg = {
|
local Dbg = {
|
||||||
is_on = false,
|
is_on = false,
|
||||||
ev_log = nil,
|
ev_log = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
local Dbg_mt = {}
|
local Dbg_mt = {}
|
||||||
|
|
||||||
local function LvDEBUG(lv, ...)
|
local function LvDEBUG(lv, ...)
|
||||||
local line = ""
|
local line = ""
|
||||||
for i,v in ipairs({...}) do
|
for i,v in ipairs({...}) do
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
line = line .. " " .. DocSettings:dump(v, lv)
|
line = line .. " " .. DocSettings:dump(v, lv)
|
||||||
else
|
else
|
||||||
line = line .. " " .. tostring(v)
|
line = line .. " " .. tostring(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print("#"..line)
|
print("#"..line)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dbg_mt.__call(dbg, ...)
|
function Dbg_mt.__call(dbg, ...)
|
||||||
if dbg.is_on then LvDEBUG(math.huge, ...) end
|
if dbg.is_on then LvDEBUG(math.huge, ...) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dbg:turnOn()
|
function Dbg:turnOn()
|
||||||
self.is_on = true
|
self.is_on = true
|
||||||
|
|
||||||
-- create or clear ev log file
|
-- create or clear ev log file
|
||||||
os.execute("echo > ev.log")
|
os.execute("echo > ev.log")
|
||||||
self.ev_log = io.open("ev.log", "w")
|
self.ev_log = io.open("ev.log", "w")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dbg:logEv(ev)
|
function Dbg:logEv(ev)
|
||||||
local log = ev.type.."|"..ev.code.."|"
|
local log = ev.type.."|"..ev.code.."|"
|
||||||
..ev.value.."|"..ev.time.sec.."|"..ev.time.usec.."\n"
|
..ev.value.."|"..ev.time.sec.."|"..ev.time.usec.."\n"
|
||||||
self.ev_log:write(log)
|
self.ev_log:write(log)
|
||||||
self.ev_log:flush()
|
self.ev_log:flush()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dbg:traceback()
|
function Dbg:traceback()
|
||||||
LvDEBUG(math.huge, debug.traceback())
|
LvDEBUG(math.huge, debug.traceback())
|
||||||
end
|
end
|
||||||
|
|
||||||
setmetatable(Dbg, Dbg_mt)
|
setmetatable(Dbg, Dbg_mt)
|
||||||
|
|||||||
@@ -2,133 +2,133 @@ local DocSettings = {}
|
|||||||
-- lfs
|
-- lfs
|
||||||
|
|
||||||
function DocSettings:getHistoryPath(fullpath)
|
function DocSettings:getHistoryPath(fullpath)
|
||||||
local i = #fullpath - 1
|
local i = #fullpath - 1
|
||||||
-- search for last slash
|
-- search for last slash
|
||||||
while i > 0 do
|
while i > 0 do
|
||||||
if fullpath:sub(i,i) == "/" then
|
if fullpath:sub(i,i) == "/" then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
i = i - 1
|
i = i - 1
|
||||||
end
|
end
|
||||||
-- construct path to configuration file in history dir
|
-- construct path to configuration file in history dir
|
||||||
local filename = fullpath:sub(i+1, -1)
|
local filename = fullpath:sub(i+1, -1)
|
||||||
local basename = fullpath:sub(1, i)
|
local basename = fullpath:sub(1, i)
|
||||||
return "./history/["..basename:gsub("/","#").."] "..filename..".lua"
|
return "./history/["..basename:gsub("/","#").."] "..filename..".lua"
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:getPathFromHistory(hist_name)
|
function DocSettings:getPathFromHistory(hist_name)
|
||||||
-- 1. select everything included in brackets
|
-- 1. select everything included in brackets
|
||||||
local s = string.match(hist_name,"%b[]")
|
local s = string.match(hist_name,"%b[]")
|
||||||
-- 2. crop the bracket-sign from both sides
|
-- 2. crop the bracket-sign from both sides
|
||||||
-- 3. and finally replace decorative signs '#' to dir-char '/'
|
-- 3. and finally replace decorative signs '#' to dir-char '/'
|
||||||
return string.gsub(string.sub(s,2,-3),"#","/")
|
return string.gsub(string.sub(s,2,-3),"#","/")
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:getNameFromHistory(hist_name)
|
function DocSettings:getNameFromHistory(hist_name)
|
||||||
-- at first, search for path length
|
-- at first, search for path length
|
||||||
local s = string.len(string.match(hist_name,"%b[]"))
|
local s = string.len(string.match(hist_name,"%b[]"))
|
||||||
-- and return the rest of string without 4 last characters (".lua")
|
-- and return the rest of string without 4 last characters (".lua")
|
||||||
return string.sub(hist_name, s+2, -5)
|
return string.sub(hist_name, s+2, -5)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:open(docfile)
|
function DocSettings:open(docfile)
|
||||||
local conf_path = nil
|
local conf_path = nil
|
||||||
if docfile == ".reader" then
|
if docfile == ".reader" then
|
||||||
-- we handle reader setting as special case
|
-- we handle reader setting as special case
|
||||||
conf_path = "settings.reader.lua"
|
conf_path = "settings.reader.lua"
|
||||||
else
|
else
|
||||||
if lfs.attributes("./history","mode") ~= "directory" then
|
if lfs.attributes("./history","mode") ~= "directory" then
|
||||||
lfs.mkdir("history")
|
lfs.mkdir("history")
|
||||||
end
|
end
|
||||||
conf_path = self:getHistoryPath(docfile)
|
conf_path = self:getHistoryPath(docfile)
|
||||||
end
|
end
|
||||||
-- construct settings obj
|
-- construct settings obj
|
||||||
local new = { file = conf_path, data = {} }
|
local new = { file = conf_path, data = {} }
|
||||||
local ok, stored = pcall(dofile, new.file)
|
local ok, stored = pcall(dofile, new.file)
|
||||||
if not ok then
|
if not ok then
|
||||||
-- try legacy conf path, for backward compatibility. this also
|
-- try legacy conf path, for backward compatibility. this also
|
||||||
-- takes care of reader legacy setting
|
-- takes care of reader legacy setting
|
||||||
ok, stored = pcall(dofile, docfile..".kpdfview.lua")
|
ok, stored = pcall(dofile, docfile..".kpdfview.lua")
|
||||||
end
|
end
|
||||||
if ok then
|
if ok then
|
||||||
new.data = stored
|
new.data = stored
|
||||||
end
|
end
|
||||||
return setmetatable(new, { __index = DocSettings})
|
return setmetatable(new, { __index = DocSettings})
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:readSetting(key)
|
function DocSettings:readSetting(key)
|
||||||
return self.data[key]
|
return self.data[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:saveSetting(key, value)
|
function DocSettings:saveSetting(key, value)
|
||||||
self.data[key] = value
|
self.data[key] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:delSetting(key)
|
function DocSettings:delSetting(key)
|
||||||
self.data[key] = nil
|
self.data[key] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:dump(data, max_lv)
|
function DocSettings:dump(data, max_lv)
|
||||||
local out = {}
|
local out = {}
|
||||||
self:_serialize(data, out, 0, max_lv)
|
self:_serialize(data, out, 0, max_lv)
|
||||||
return table.concat(out)
|
return table.concat(out)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- simple serialization function, won't do uservalues, functions, loops
|
-- simple serialization function, won't do uservalues, functions, loops
|
||||||
function DocSettings:_serialize(what, outt, indent, max_lv)
|
function DocSettings:_serialize(what, outt, indent, max_lv)
|
||||||
if not max_lv then
|
if not max_lv then
|
||||||
max_lv = math.huge
|
max_lv = math.huge
|
||||||
end
|
end
|
||||||
|
|
||||||
if indent > max_lv then
|
if indent > max_lv then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(what) == "table" then
|
if type(what) == "table" then
|
||||||
local didrun = false
|
local didrun = false
|
||||||
table.insert(outt, "{")
|
table.insert(outt, "{")
|
||||||
for k, v in pairs(what) do
|
for k, v in pairs(what) do
|
||||||
if didrun then
|
if didrun then
|
||||||
table.insert(outt, ",")
|
table.insert(outt, ",")
|
||||||
end
|
end
|
||||||
table.insert(outt, "\n")
|
table.insert(outt, "\n")
|
||||||
table.insert(outt, string.rep("\t", indent+1))
|
table.insert(outt, string.rep("\t", indent+1))
|
||||||
table.insert(outt, "[")
|
table.insert(outt, "[")
|
||||||
self:_serialize(k, outt, indent+1, max_lv)
|
self:_serialize(k, outt, indent+1, max_lv)
|
||||||
table.insert(outt, "] = ")
|
table.insert(outt, "] = ")
|
||||||
self:_serialize(v, outt, indent+1, max_lv)
|
self:_serialize(v, outt, indent+1, max_lv)
|
||||||
didrun = true
|
didrun = true
|
||||||
end
|
end
|
||||||
if didrun then
|
if didrun then
|
||||||
table.insert(outt, "\n")
|
table.insert(outt, "\n")
|
||||||
table.insert(outt, string.rep("\t", indent))
|
table.insert(outt, string.rep("\t", indent))
|
||||||
end
|
end
|
||||||
table.insert(outt, "}")
|
table.insert(outt, "}")
|
||||||
elseif type(what) == "string" then
|
elseif type(what) == "string" then
|
||||||
table.insert(outt, string.format("%q", what))
|
table.insert(outt, string.format("%q", what))
|
||||||
elseif type(what) == "number" or type(what) == "boolean" then
|
elseif type(what) == "number" or type(what) == "boolean" then
|
||||||
table.insert(outt, tostring(what))
|
table.insert(outt, tostring(what))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:flush()
|
function DocSettings:flush()
|
||||||
-- write a serialized version of the data table
|
-- write a serialized version of the data table
|
||||||
if not self.file then
|
if not self.file then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local f_out = io.open(self.file, "w")
|
local f_out = io.open(self.file, "w")
|
||||||
if f_out ~= nil then
|
if f_out ~= nil then
|
||||||
os.setlocale('C', 'numeric')
|
os.setlocale('C', 'numeric')
|
||||||
local out = {"-- we can read Lua syntax here!\nreturn "}
|
local out = {"-- we can read Lua syntax here!\nreturn "}
|
||||||
self:_serialize(self.data, out, 0)
|
self:_serialize(self.data, out, 0)
|
||||||
table.insert(out, "\n")
|
table.insert(out, "\n")
|
||||||
f_out:write(table.concat(out))
|
f_out:write(table.concat(out))
|
||||||
f_out:close()
|
f_out:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocSettings:close()
|
function DocSettings:close()
|
||||||
self:flush()
|
self:flush()
|
||||||
end
|
end
|
||||||
|
|
||||||
return DocSettings
|
return DocSettings
|
||||||
|
|||||||
@@ -10,140 +10,140 @@ local DEBUG = require("dbg")
|
|||||||
-- TBD: DrawContext
|
-- TBD: DrawContext
|
||||||
|
|
||||||
local CreDocument = Document:new{
|
local CreDocument = Document:new{
|
||||||
-- this is defined in kpvcrlib/crengine/crengine/include/lvdocview.h
|
-- this is defined in kpvcrlib/crengine/crengine/include/lvdocview.h
|
||||||
SCROLL_VIEW_MODE = 0,
|
SCROLL_VIEW_MODE = 0,
|
||||||
PAGE_VIEW_MODE = 1,
|
PAGE_VIEW_MODE = 1,
|
||||||
|
|
||||||
_document = false,
|
_document = false,
|
||||||
engine_initilized = false,
|
engine_initilized = false,
|
||||||
|
|
||||||
line_space_percent = 100,
|
line_space_percent = 100,
|
||||||
default_font = G_reader_settings:readSetting("cre_font") or "FreeSerif",
|
default_font = G_reader_settings:readSetting("cre_font") or "FreeSerif",
|
||||||
header_font = G_reader_settings:readSetting("header_font") or "FreeSans",
|
header_font = G_reader_settings:readSetting("header_font") or "FreeSans",
|
||||||
fallback_font = G_reader_settings:readSetting("fallback_font") or "Droid Sans Fallback",
|
fallback_font = G_reader_settings:readSetting("fallback_font") or "Droid Sans Fallback",
|
||||||
default_css = "./data/cr3.css",
|
default_css = "./data/cr3.css",
|
||||||
options = CreOptions,
|
options = CreOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- NuPogodi, 20.05.12: inspect the zipfile content
|
-- NuPogodi, 20.05.12: inspect the zipfile content
|
||||||
function CreDocument.zipContentExt(self, fname)
|
function CreDocument.zipContentExt(self, fname)
|
||||||
local outfile = "./data/zip_content"
|
local outfile = "./data/zip_content"
|
||||||
local s = ""
|
local s = ""
|
||||||
os.execute("unzip ".."-l \""..fname.."\" > "..outfile)
|
os.execute("unzip ".."-l \""..fname.."\" > "..outfile)
|
||||||
local i = 1
|
local i = 1
|
||||||
if io.open(outfile,"r") then
|
if io.open(outfile,"r") then
|
||||||
for lines in io.lines(outfile) do
|
for lines in io.lines(outfile) do
|
||||||
if i == 4 then s = lines break else i = i + 1 end
|
if i == 4 then s = lines break else i = i + 1 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- return the extention
|
-- return the extention
|
||||||
return string.lower(string.match(s, ".+%.([^.]+)"))
|
return string.lower(string.match(s, ".+%.([^.]+)"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:engineInit()
|
function CreDocument:engineInit()
|
||||||
if not engine_initilized then
|
if not engine_initilized then
|
||||||
-- initialize cache
|
-- initialize cache
|
||||||
cre.initCache(1024*1024*64)
|
cre.initCache(1024*1024*64)
|
||||||
|
|
||||||
-- we need to initialize the CRE font list
|
-- we need to initialize the CRE font list
|
||||||
local fonts = Font:getFontList()
|
local fonts = Font:getFontList()
|
||||||
for _k, _v in ipairs(fonts) do
|
for _k, _v in ipairs(fonts) do
|
||||||
if _v ~= "Dingbats.cff" and _v ~= "StandardSymL.cff" then
|
if _v ~= "Dingbats.cff" and _v ~= "StandardSymL.cff" then
|
||||||
local ok, err = pcall(cre.registerFont, Font.fontdir..'/'.._v)
|
local ok, err = pcall(cre.registerFont, Font.fontdir..'/'.._v)
|
||||||
if not ok then
|
if not ok then
|
||||||
DEBUG(err)
|
DEBUG(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
engine_initilized = true
|
engine_initilized = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:init()
|
function CreDocument:init()
|
||||||
require "libs/libkoreader-cre"
|
require "libs/libkoreader-cre"
|
||||||
self:engineInit()
|
self:engineInit()
|
||||||
self.configurable:loadDefaults(self.options)
|
self.configurable:loadDefaults(self.options)
|
||||||
|
|
||||||
local ok
|
local ok
|
||||||
local file_type = string.lower(string.match(self.file, ".+%.([^.]+)"))
|
local file_type = string.lower(string.match(self.file, ".+%.([^.]+)"))
|
||||||
if file_type == "zip" then
|
if file_type == "zip" then
|
||||||
-- NuPogodi, 20.05.12: read the content of zip-file
|
-- NuPogodi, 20.05.12: read the content of zip-file
|
||||||
-- and return extention of the 1st file
|
-- and return extention of the 1st file
|
||||||
file_type = self:zipContentExt(self.file)
|
file_type = self:zipContentExt(self.file)
|
||||||
end
|
end
|
||||||
-- these two format use the same css file
|
-- these two format use the same css file
|
||||||
if file_type == "html" then
|
if file_type == "html" then
|
||||||
file_type = "htm"
|
file_type = "htm"
|
||||||
end
|
end
|
||||||
-- if native css-file doesn't exist, one needs to use default cr3.css
|
-- if native css-file doesn't exist, one needs to use default cr3.css
|
||||||
if not io.open("./data/"..file_type..".css") then
|
if not io.open("./data/"..file_type..".css") then
|
||||||
file_type = "cr3"
|
file_type = "cr3"
|
||||||
end
|
end
|
||||||
self.default_css = "./data/"..file_type..".css"
|
self.default_css = "./data/"..file_type..".css"
|
||||||
|
|
||||||
-- @TODO check the default view_mode to a global user configurable
|
-- @TODO check the default view_mode to a global user configurable
|
||||||
-- variable 22.12 2012 (houqp)
|
-- variable 22.12 2012 (houqp)
|
||||||
ok, self._document = pcall(cre.newDocView,
|
ok, self._document = pcall(cre.newDocView,
|
||||||
Screen:getWidth(), Screen:getHeight(), self.PAGE_VIEW_MODE
|
Screen:getWidth(), Screen:getHeight(), self.PAGE_VIEW_MODE
|
||||||
)
|
)
|
||||||
if not ok then
|
if not ok then
|
||||||
self.error_message = self.doc -- will contain error message
|
self.error_message = self.doc -- will contain error message
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- adjust font sizes according to screen dpi
|
-- adjust font sizes according to screen dpi
|
||||||
self._document:adjustFontSizes(Screen:getDPI())
|
self._document:adjustFontSizes(Screen:getDPI())
|
||||||
|
|
||||||
-- set fallback font face
|
-- set fallback font face
|
||||||
self._document:setStringProperty("crengine.font.fallback.face", self.fallback_font)
|
self._document:setStringProperty("crengine.font.fallback.face", self.fallback_font)
|
||||||
|
|
||||||
self.is_open = true
|
self.is_open = true
|
||||||
self.info.has_pages = false
|
self.info.has_pages = false
|
||||||
self:_readMetadata()
|
self:_readMetadata()
|
||||||
self.info.configurable = true
|
self.info.configurable = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:loadDocument()
|
function CreDocument:loadDocument()
|
||||||
self._document:loadDocument(self.file)
|
self._document:loadDocument(self.file)
|
||||||
if not self.info.has_pages then
|
if not self.info.has_pages then
|
||||||
self.info.doc_height = self._document:getFullHeight()
|
self.info.doc_height = self._document:getFullHeight()
|
||||||
end
|
end
|
||||||
if Device:getModel() ~= "KindleDXG" then
|
if Device:getModel() ~= "KindleDXG" then
|
||||||
self:setVisiblePageCount(1)
|
self:setVisiblePageCount(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:close()
|
function CreDocument:close()
|
||||||
self._document:saveDefaults()
|
self._document:saveDefaults()
|
||||||
Document.close(self)
|
Document.close(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getPageCount()
|
function CreDocument:getPageCount()
|
||||||
return self._document:getPages()
|
return self._document:getPages()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getWordFromPosition(pos)
|
function CreDocument:getWordFromPosition(pos)
|
||||||
local word_box = self._document:getWordFromPosition(pos.x, pos.y)
|
local word_box = self._document:getWordFromPosition(pos.x, pos.y)
|
||||||
local text_range = self._document:getTextFromPositions(pos.x, pos.y, pos.x, pos.y)
|
local text_range = self._document:getTextFromPositions(pos.x, pos.y, pos.x, pos.y)
|
||||||
if word_box.word then
|
if word_box.word then
|
||||||
return {
|
return {
|
||||||
word = text_range.text == "" and word_box.word or text_range.text,
|
word = text_range.text == "" and word_box.word or text_range.text,
|
||||||
page = self._document:getCurrentPage(),
|
page = self._document:getCurrentPage(),
|
||||||
sbox = Geom:new{
|
sbox = Geom:new{
|
||||||
x = word_box.x0, y = word_box.y0,
|
x = word_box.x0, y = word_box.y0,
|
||||||
w = word_box.x1 - word_box.x0,
|
w = word_box.x1 - word_box.x0,
|
||||||
h = word_box.y1 - word_box.y0,
|
h = word_box.y1 - word_box.y0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getTextFromPositions(pos0, pos1)
|
function CreDocument:getTextFromPositions(pos0, pos1)
|
||||||
local text_range = self._document:getTextFromPositions(pos0.x, pos0.y, pos1.x, pos1.y)
|
local text_range = self._document:getTextFromPositions(pos0.x, pos0.y, pos1.x, pos1.y)
|
||||||
DEBUG("CreDocument: get text range", text_range)
|
DEBUG("CreDocument: get text range", text_range)
|
||||||
local line_boxes = self:getScreenBoxesFromPositions(text_range.pos0, text_range.pos1)
|
local line_boxes = self:getScreenBoxesFromPositions(text_range.pos0, text_range.pos1)
|
||||||
return {
|
return {
|
||||||
text = text_range.text,
|
text = text_range.text,
|
||||||
pos0 = text_range.pos0,
|
pos0 = text_range.pos0,
|
||||||
pos1 = text_range.pos1,
|
pos1 = text_range.pos1,
|
||||||
@@ -152,38 +152,38 @@ function CreDocument:getTextFromPositions(pos0, pos1)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getScreenBoxesFromPositions(pos0, pos1)
|
function CreDocument:getScreenBoxesFromPositions(pos0, pos1)
|
||||||
local line_boxes = {}
|
local line_boxes = {}
|
||||||
if pos0 and pos1 then
|
if pos0 and pos1 then
|
||||||
local word_boxes = self._document:getWordBoxesFromPositions(pos0, pos1)
|
local word_boxes = self._document:getWordBoxesFromPositions(pos0, pos1)
|
||||||
--DEBUG("word boxes", word_boxes)
|
--DEBUG("word boxes", word_boxes)
|
||||||
for i = 1, #word_boxes do
|
for i = 1, #word_boxes do
|
||||||
local line_box = word_boxes[i]
|
local line_box = word_boxes[i]
|
||||||
table.insert(line_boxes, Geom:new{
|
table.insert(line_boxes, Geom:new{
|
||||||
x = line_box.x0, y = line_box.y0,
|
x = line_box.x0, y = line_box.y0,
|
||||||
w = line_box.x1 - line_box.x0,
|
w = line_box.x1 - line_box.x0,
|
||||||
h = line_box.y1 - line_box.y0,
|
h = line_box.y1 - line_box.y0,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
--DEBUG("line boxes", line_boxes)
|
--DEBUG("line boxes", line_boxes)
|
||||||
end
|
end
|
||||||
return line_boxes
|
return line_boxes
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:drawCurrentView(target, x, y, rect, pos)
|
function CreDocument:drawCurrentView(target, x, y, rect, pos)
|
||||||
tile_bb = Blitbuffer.new(rect.w, rect.h)
|
tile_bb = Blitbuffer.new(rect.w, rect.h)
|
||||||
self._document:drawCurrentPage(tile_bb)
|
self._document:drawCurrentPage(tile_bb)
|
||||||
target:blitFrom(tile_bb, x, y, 0, 0, rect.w, rect.h)
|
target:blitFrom(tile_bb, x, y, 0, 0, rect.w, rect.h)
|
||||||
tile_bb:free()
|
tile_bb:free()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:drawCurrentViewByPos(target, x, y, rect, pos)
|
function CreDocument:drawCurrentViewByPos(target, x, y, rect, pos)
|
||||||
self._document:gotoPos(pos)
|
self._document:gotoPos(pos)
|
||||||
self:drawCurrentView(target, x, y, rect)
|
self:drawCurrentView(target, x, y, rect)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:drawCurrentViewByPage(target, x, y, rect, page)
|
function CreDocument:drawCurrentViewByPage(target, x, y, rect, page)
|
||||||
self._document:gotoPage(page)
|
self._document:gotoPage(page)
|
||||||
self:drawCurrentView(target, x, y, rect)
|
self:drawCurrentView(target, x, y, rect)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:hintPage(pageno, zoom, rotation)
|
function CreDocument:hintPage(pageno, zoom, rotation)
|
||||||
@@ -196,182 +196,182 @@ function CreDocument:renderPage(pageno, rect, zoom, rotation)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:gotoXPointer(xpointer)
|
function CreDocument:gotoXPointer(xpointer)
|
||||||
DEBUG("CreDocument: goto xpointer", xpointer)
|
DEBUG("CreDocument: goto xpointer", xpointer)
|
||||||
self._document:gotoXPointer(xpointer)
|
self._document:gotoXPointer(xpointer)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getXPointer()
|
function CreDocument:getXPointer()
|
||||||
return self._document:getXPointer()
|
return self._document:getXPointer()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getPosFromXPointer(xp)
|
function CreDocument:getPosFromXPointer(xp)
|
||||||
return self._document:getPosFromXPointer(xp)
|
return self._document:getPosFromXPointer(xp)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getPageFromXPointer(xp)
|
function CreDocument:getPageFromXPointer(xp)
|
||||||
return self._document:getPageFromXPointer(xp)
|
return self._document:getPageFromXPointer(xp)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getFontFace()
|
function CreDocument:getFontFace()
|
||||||
return self._document:getFontFace()
|
return self._document:getFontFace()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getCurrentPos()
|
function CreDocument:getCurrentPos()
|
||||||
return self._document:getCurrentPos()
|
return self._document:getCurrentPos()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getPageLinks()
|
function CreDocument:getPageLinks()
|
||||||
return self._document:getPageLinks()
|
return self._document:getPageLinks()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getLinkFromPosition(pos)
|
function CreDocument:getLinkFromPosition(pos)
|
||||||
return self._document:getLinkFromPosition(pos.x, pos.y)
|
return self._document:getLinkFromPosition(pos.x, pos.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:gotoPos(pos)
|
function Document:gotoPos(pos)
|
||||||
DEBUG("CreDocument: goto position", pos)
|
DEBUG("CreDocument: goto position", pos)
|
||||||
self._document:gotoPos(pos)
|
self._document:gotoPos(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:gotoPage(page)
|
function CreDocument:gotoPage(page)
|
||||||
DEBUG("CreDocument: goto page", page)
|
DEBUG("CreDocument: goto page", page)
|
||||||
self._document:gotoPage(page)
|
self._document:gotoPage(page)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:gotoLink(link)
|
function CreDocument:gotoLink(link)
|
||||||
DEBUG("CreDocument: goto link", link)
|
DEBUG("CreDocument: goto link", link)
|
||||||
self._document:gotoLink(link)
|
self._document:gotoLink(link)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:goBack()
|
function CreDocument:goBack()
|
||||||
DEBUG("CreDocument: go back")
|
DEBUG("CreDocument: go back")
|
||||||
self._document:goBack()
|
self._document:goBack()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:goForward(link)
|
function CreDocument:goForward(link)
|
||||||
DEBUG("CreDocument: go forward")
|
DEBUG("CreDocument: go forward")
|
||||||
self._document:goForward()
|
self._document:goForward()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getCurrentPage()
|
function CreDocument:getCurrentPage()
|
||||||
return self._document:getCurrentPage()
|
return self._document:getCurrentPage()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setFontFace(new_font_face)
|
function CreDocument:setFontFace(new_font_face)
|
||||||
if new_font_face then
|
if new_font_face then
|
||||||
DEBUG("CreDocument: set font face", new_font_face)
|
DEBUG("CreDocument: set font face", new_font_face)
|
||||||
self._document:setFontFace(new_font_face)
|
self._document:setFontFace(new_font_face)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:clearSelection()
|
function CreDocument:clearSelection()
|
||||||
self._document:clearSelection()
|
self._document:clearSelection()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:getFontSize()
|
function CreDocument:getFontSize()
|
||||||
return self._document:getFontSize()
|
return self._document:getFontSize()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setFontSize(new_font_size)
|
function CreDocument:setFontSize(new_font_size)
|
||||||
if new_font_size then
|
if new_font_size then
|
||||||
DEBUG("CreDocument: set font size", new_font_size)
|
DEBUG("CreDocument: set font size", new_font_size)
|
||||||
self._document:setFontSize(new_font_size)
|
self._document:setFontSize(new_font_size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setViewMode(new_mode)
|
function CreDocument:setViewMode(new_mode)
|
||||||
if new_mode then
|
if new_mode then
|
||||||
DEBUG("CreDocument: set view mode", new_mode)
|
DEBUG("CreDocument: set view mode", new_mode)
|
||||||
if new_mode == "scroll" then
|
if new_mode == "scroll" then
|
||||||
self._document:setViewMode(self.SCROLL_VIEW_MODE)
|
self._document:setViewMode(self.SCROLL_VIEW_MODE)
|
||||||
else
|
else
|
||||||
self._document:setViewMode(self.PAGE_VIEW_MODE)
|
self._document:setViewMode(self.PAGE_VIEW_MODE)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setHeaderFont(new_font)
|
function CreDocument:setHeaderFont(new_font)
|
||||||
if new_font then
|
if new_font then
|
||||||
DEBUG("CreDocument: set header font", new_font)
|
DEBUG("CreDocument: set header font", new_font)
|
||||||
self._document:setHeaderFont(new_font)
|
self._document:setHeaderFont(new_font)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:zoomFont(delta)
|
function CreDocument:zoomFont(delta)
|
||||||
DEBUG("CreDocument: zoom font", delta)
|
DEBUG("CreDocument: zoom font", delta)
|
||||||
self._document:zoomFont(delta)
|
self._document:zoomFont(delta)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setInterlineSpacePercent(percent)
|
function CreDocument:setInterlineSpacePercent(percent)
|
||||||
DEBUG("CreDocument: set interline space", percent)
|
DEBUG("CreDocument: set interline space", percent)
|
||||||
self._document:setDefaultInterlineSpace(percent)
|
self._document:setDefaultInterlineSpace(percent)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:toggleFontBolder()
|
function CreDocument:toggleFontBolder()
|
||||||
DEBUG("CreDocument: toggle font bolder")
|
DEBUG("CreDocument: toggle font bolder")
|
||||||
self._document:toggleFontBolder()
|
self._document:toggleFontBolder()
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setGammaIndex(index)
|
function CreDocument:setGammaIndex(index)
|
||||||
DEBUG("CreDocument: set gamma index", index)
|
DEBUG("CreDocument: set gamma index", index)
|
||||||
cre.setGammaIndex(index)
|
cre.setGammaIndex(index)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setStyleSheet(new_css)
|
function CreDocument:setStyleSheet(new_css)
|
||||||
DEBUG("CreDocument: set style sheet", new_css)
|
DEBUG("CreDocument: set style sheet", new_css)
|
||||||
self._document:setStyleSheet(new_css)
|
self._document:setStyleSheet(new_css)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setEmbeddedStyleSheet(toggle)
|
function CreDocument:setEmbeddedStyleSheet(toggle)
|
||||||
DEBUG("CreDocument: set embedded style sheet", toggle)
|
DEBUG("CreDocument: set embedded style sheet", toggle)
|
||||||
self._document:setEmbeddedStyleSheet(toggle)
|
self._document:setEmbeddedStyleSheet(toggle)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setPageMargins(left, top, right, bottom)
|
function CreDocument:setPageMargins(left, top, right, bottom)
|
||||||
DEBUG("CreDocument: set page margins", left, top, right, bottom)
|
DEBUG("CreDocument: set page margins", left, top, right, bottom)
|
||||||
self._document:setPageMargins(left, top, right, bottom)
|
self._document:setPageMargins(left, top, right, bottom)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setFloatingPunctuation(enabled)
|
function CreDocument:setFloatingPunctuation(enabled)
|
||||||
DEBUG("CreDocument: set floating punctuation", enabled)
|
DEBUG("CreDocument: set floating punctuation", enabled)
|
||||||
self._document:setIntProperty("crengine.style.floating.punctuation.enabled", enabled)
|
self._document:setIntProperty("crengine.style.floating.punctuation.enabled", enabled)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setVisiblePageCount(new_count)
|
function CreDocument:setVisiblePageCount(new_count)
|
||||||
DEBUG("CreDocument: set visible page count", new_count)
|
DEBUG("CreDocument: set visible page count", new_count)
|
||||||
self._document:setVisiblePageCount(new_count)
|
self._document:setVisiblePageCount(new_count)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setBatteryState(state)
|
function CreDocument:setBatteryState(state)
|
||||||
DEBUG("CreDocument: set battery state", state)
|
DEBUG("CreDocument: set battery state", state)
|
||||||
self._document:setBatteryState(state)
|
self._document:setBatteryState(state)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:isXPointerInCurrentPage(xp)
|
function CreDocument:isXPointerInCurrentPage(xp)
|
||||||
DEBUG("CreDocument: check in page", xp)
|
DEBUG("CreDocument: check in page", xp)
|
||||||
return self._document:isXPointerInCurrentPage(xp)
|
return self._document:isXPointerInCurrentPage(xp)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:setStatusLineProp(prop)
|
function CreDocument:setStatusLineProp(prop)
|
||||||
DEBUG("CreDocument: set status line property", prop)
|
DEBUG("CreDocument: set status line property", prop)
|
||||||
self._document:setStringProperty("window.status.line", prop)
|
self._document:setStringProperty("window.status.line", prop)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreDocument:register(registry)
|
function CreDocument:register(registry)
|
||||||
registry:addProvider("txt", "application/txt", self)
|
registry:addProvider("txt", "application/txt", self)
|
||||||
registry:addProvider("epub", "application/epub", self)
|
registry:addProvider("epub", "application/epub", self)
|
||||||
registry:addProvider("fb2", "application/fb2", self)
|
registry:addProvider("fb2", "application/fb2", self)
|
||||||
registry:addProvider("html", "application/html", self)
|
registry:addProvider("html", "application/html", self)
|
||||||
registry:addProvider("htm", "application/htm", self)
|
registry:addProvider("htm", "application/htm", self)
|
||||||
registry:addProvider("zip", "application/zip", self)
|
registry:addProvider("zip", "application/zip", self)
|
||||||
registry:addProvider("rtf", "application/rtf", self)
|
registry:addProvider("rtf", "application/rtf", self)
|
||||||
registry:addProvider("mobi", "application/mobi", self)
|
registry:addProvider("mobi", "application/mobi", self)
|
||||||
registry:addProvider("prc", "application/prc", self)
|
registry:addProvider("prc", "application/prc", self)
|
||||||
registry:addProvider("azw", "application/azw", self)
|
registry:addProvider("azw", "application/azw", self)
|
||||||
registry:addProvider("chm", "application/chm", self)
|
registry:addProvider("chm", "application/chm", self)
|
||||||
registry:addProvider("pdb", "application/pdb", self)
|
registry:addProvider("pdb", "application/pdb", self)
|
||||||
registry:addProvider("doc", "application/doc", self)
|
registry:addProvider("doc", "application/doc", self)
|
||||||
registry:addProvider("tcr", "application/tcr", self)
|
registry:addProvider("tcr", "application/tcr", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return CreDocument
|
return CreDocument
|
||||||
|
|||||||
@@ -7,113 +7,113 @@ local Configurable = require("ui/reader/configurable")
|
|||||||
local DrawContext = require("ffi/drawcontext")
|
local DrawContext = require("ffi/drawcontext")
|
||||||
|
|
||||||
local DjvuDocument = Document:new{
|
local DjvuDocument = Document:new{
|
||||||
_document = false,
|
_document = false,
|
||||||
-- libdjvulibre manages its own additional cache, default value is hard written in c module.
|
-- libdjvulibre manages its own additional cache, default value is hard written in c module.
|
||||||
djvulibre_cache_size = nil,
|
djvulibre_cache_size = nil,
|
||||||
dc_null = DrawContext.new(),
|
dc_null = DrawContext.new(),
|
||||||
options = KoptOptions,
|
options = KoptOptions,
|
||||||
koptinterface = nil,
|
koptinterface = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- check DjVu magic string to validate
|
-- check DjVu magic string to validate
|
||||||
local function validDjvuFile(filename)
|
local function validDjvuFile(filename)
|
||||||
f = io.open(filename, "r")
|
f = io.open(filename, "r")
|
||||||
if not f then return false end
|
if not f then return false end
|
||||||
local magic = f:read(8)
|
local magic = f:read(8)
|
||||||
f:close()
|
f:close()
|
||||||
if not magic or magic ~= "AT&TFORM" then return false end
|
if not magic or magic ~= "AT&TFORM" then return false end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:init()
|
function DjvuDocument:init()
|
||||||
local djvu = require("libs/libkoreader-djvu")
|
local djvu = require("libs/libkoreader-djvu")
|
||||||
self.koptinterface = require("document/koptinterface")
|
self.koptinterface = require("document/koptinterface")
|
||||||
self.configurable:loadDefaults(self.options)
|
self.configurable:loadDefaults(self.options)
|
||||||
if not validDjvuFile(self.file) then
|
if not validDjvuFile(self.file) then
|
||||||
self.error_message = "Not a valid DjVu file"
|
self.error_message = "Not a valid DjVu file"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local ok
|
local ok
|
||||||
ok, self._document = pcall(djvu.openDocument, self.file, self.djvulibre_cache_size)
|
ok, self._document = pcall(djvu.openDocument, self.file, self.djvulibre_cache_size)
|
||||||
if not ok then
|
if not ok then
|
||||||
self.error_message = self.doc -- will contain error message
|
self.error_message = self.doc -- will contain error message
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.is_open = true
|
self.is_open = true
|
||||||
self.info.has_pages = true
|
self.info.has_pages = true
|
||||||
self.info.configurable = true
|
self.info.configurable = true
|
||||||
self:_readMetadata()
|
self:_readMetadata()
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:invertTextYAxel(pageno, text_table)
|
function DjvuDocument:invertTextYAxel(pageno, text_table)
|
||||||
local _, height = self.doc:getOriginalPageSize(pageno)
|
local _, height = self.doc:getOriginalPageSize(pageno)
|
||||||
for _,text in pairs(text_table) do
|
for _,text in pairs(text_table) do
|
||||||
for _,line in ipairs(text) do
|
for _,line in ipairs(text) do
|
||||||
line.y0, line.y1 = (height - line.y1), (height - line.y0)
|
line.y0, line.y1 = (height - line.y1), (height - line.y0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return text_table
|
return text_table
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getPageTextBoxes(pageno)
|
function DjvuDocument:getPageTextBoxes(pageno)
|
||||||
return self._document:getPageText(pageno)
|
return self._document:getPageText(pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getWordFromPosition(spos)
|
function DjvuDocument:getWordFromPosition(spos)
|
||||||
return self.koptinterface:getWordFromPosition(self, spos)
|
return self.koptinterface:getWordFromPosition(self, spos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getTextFromPositions(spos0, spos1)
|
function DjvuDocument:getTextFromPositions(spos0, spos1)
|
||||||
return self.koptinterface:getTextFromPositions(self, spos0, spos1)
|
return self.koptinterface:getTextFromPositions(self, spos0, spos1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getPageBoxesFromPositions(pageno, ppos0, ppos1)
|
function DjvuDocument:getPageBoxesFromPositions(pageno, ppos0, ppos1)
|
||||||
return self.koptinterface:getPageBoxesFromPositions(self, pageno, ppos0, ppos1)
|
return self.koptinterface:getPageBoxesFromPositions(self, pageno, ppos0, ppos1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getOCRWord(pageno, wbox)
|
function DjvuDocument:getOCRWord(pageno, wbox)
|
||||||
return self.koptinterface:getOCRWord(self, pageno, wbox)
|
return self.koptinterface:getOCRWord(self, pageno, wbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getOCRText(pageno, tboxes)
|
function DjvuDocument:getOCRText(pageno, tboxes)
|
||||||
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getPageRegions(pageno)
|
function DjvuDocument:getPageRegions(pageno)
|
||||||
return self.koptinterface:getPageRegions(self, pageno)
|
return self.koptinterface:getPageRegions(self, pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getUsedBBox(pageno)
|
function DjvuDocument:getUsedBBox(pageno)
|
||||||
-- djvu does not support usedbbox, so fake it.
|
-- djvu does not support usedbbox, so fake it.
|
||||||
local used = {}
|
local used = {}
|
||||||
local native_dim = self:getNativePageDimensions(pageno)
|
local native_dim = self:getNativePageDimensions(pageno)
|
||||||
used.x0, used.y0, used.x1, used.y1 = 0, 0, native_dim.w, native_dim.h
|
used.x0, used.y0, used.x1, used.y1 = 0, 0, native_dim.w, native_dim.h
|
||||||
return used
|
return used
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getPageBBox(pageno)
|
function DjvuDocument:getPageBBox(pageno)
|
||||||
return self.koptinterface:getPageBBox(self, pageno)
|
return self.koptinterface:getPageBBox(self, pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:getPageDimensions(pageno, zoom, rotation)
|
function DjvuDocument:getPageDimensions(pageno, zoom, rotation)
|
||||||
return self.koptinterface:getPageDimensions(self, pageno, zoom, rotation)
|
return self.koptinterface:getPageDimensions(self, pageno, zoom, rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
function DjvuDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DjvuDocument:register(registry)
|
function DjvuDocument:register(registry)
|
||||||
registry:addProvider("djvu", "application/djvu", self)
|
registry:addProvider("djvu", "application/djvu", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return DjvuDocument
|
return DjvuDocument
|
||||||
|
|||||||
@@ -11,55 +11,55 @@ local DEBUG = require("dbg")
|
|||||||
This is an abstract interface to a document
|
This is an abstract interface to a document
|
||||||
]]--
|
]]--
|
||||||
local Document = {
|
local Document = {
|
||||||
-- file name
|
-- file name
|
||||||
file = nil,
|
file = nil,
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
-- whether the document is pageable
|
-- whether the document is pageable
|
||||||
has_pages = false,
|
has_pages = false,
|
||||||
-- whether words can be provided
|
-- whether words can be provided
|
||||||
has_words = false,
|
has_words = false,
|
||||||
-- whether hyperlinks can be provided
|
-- whether hyperlinks can be provided
|
||||||
has_hyperlinks = false,
|
has_hyperlinks = false,
|
||||||
-- whether (native to format) annotations can be provided
|
-- whether (native to format) annotations can be provided
|
||||||
has_annotations = false,
|
has_annotations = false,
|
||||||
|
|
||||||
-- whether pages can be rotated
|
-- whether pages can be rotated
|
||||||
is_rotatable = false,
|
is_rotatable = false,
|
||||||
|
|
||||||
number_of_pages = 0,
|
number_of_pages = 0,
|
||||||
-- if not pageable, length of the document in pixels
|
-- if not pageable, length of the document in pixels
|
||||||
doc_height = 0,
|
doc_height = 0,
|
||||||
|
|
||||||
-- other metadata
|
-- other metadata
|
||||||
title = "",
|
title = "",
|
||||||
author = "",
|
author = "",
|
||||||
date = ""
|
date = ""
|
||||||
},
|
},
|
||||||
|
|
||||||
links = {},
|
links = {},
|
||||||
|
|
||||||
GAMMA_NO_GAMMA = 1.0,
|
GAMMA_NO_GAMMA = 1.0,
|
||||||
|
|
||||||
-- override bbox from orignal page's getUsedBBox
|
-- override bbox from orignal page's getUsedBBox
|
||||||
bbox = {},
|
bbox = {},
|
||||||
|
|
||||||
-- flag to show whether the document was opened successfully
|
-- flag to show whether the document was opened successfully
|
||||||
is_open = false,
|
is_open = false,
|
||||||
error_message = nil,
|
error_message = nil,
|
||||||
|
|
||||||
-- flag to show that the document needs to be unlocked by a password
|
-- flag to show that the document needs to be unlocked by a password
|
||||||
is_locked = false,
|
is_locked = false,
|
||||||
|
|
||||||
configurable = Configurable,
|
configurable = Configurable,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Document:new(o)
|
function Document:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
if o.init then o:init() end
|
if o.init then o:init() end
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
-- override this method to open a document
|
-- override this method to open a document
|
||||||
@@ -68,195 +68,195 @@ end
|
|||||||
|
|
||||||
-- this might be overridden by a document implementation
|
-- this might be overridden by a document implementation
|
||||||
function Document:unlock(password)
|
function Document:unlock(password)
|
||||||
-- return true instead when the password provided unlocked the document
|
-- return true instead when the password provided unlocked the document
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- this might be overridden by a document implementation
|
-- this might be overridden by a document implementation
|
||||||
function Document:close()
|
function Document:close()
|
||||||
if self.is_open then
|
if self.is_open then
|
||||||
self.is_open = false
|
self.is_open = false
|
||||||
self._document:close()
|
self._document:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- this might be overridden by a document implementation
|
-- this might be overridden by a document implementation
|
||||||
function Document:getNativePageDimensions(pageno)
|
function Document:getNativePageDimensions(pageno)
|
||||||
local hash = "pgdim|"..self.file.."|"..pageno
|
local hash = "pgdim|"..self.file.."|"..pageno
|
||||||
local cached = Cache:check(hash)
|
local cached = Cache:check(hash)
|
||||||
if cached then
|
if cached then
|
||||||
return cached[1]
|
return cached[1]
|
||||||
end
|
end
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local page_size_w, page_size_h = page:getSize(self.dc_null)
|
local page_size_w, page_size_h = page:getSize(self.dc_null)
|
||||||
local page_size = Geom:new{ w = page_size_w, h = page_size_h }
|
local page_size = Geom:new{ w = page_size_w, h = page_size_h }
|
||||||
Cache:insert(hash, CacheItem:new{ page_size })
|
Cache:insert(hash, CacheItem:new{ page_size })
|
||||||
page:close()
|
page:close()
|
||||||
return page_size
|
return page_size
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:_readMetadata()
|
function Document:_readMetadata()
|
||||||
self.info.number_of_pages = self._document:getPages()
|
self.info.number_of_pages = self._document:getPages()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getPageCount()
|
function Document:getPageCount()
|
||||||
return self.info.number_of_pages
|
return self.info.number_of_pages
|
||||||
end
|
end
|
||||||
|
|
||||||
-- calculates page dimensions
|
-- calculates page dimensions
|
||||||
function Document:getPageDimensions(pageno, zoom, rotation)
|
function Document:getPageDimensions(pageno, zoom, rotation)
|
||||||
local native_dimen = self:getNativePageDimensions(pageno):copy()
|
local native_dimen = self:getNativePageDimensions(pageno):copy()
|
||||||
if rotation == 90 or rotation == 270 then
|
if rotation == 90 or rotation == 270 then
|
||||||
-- switch orientation
|
-- switch orientation
|
||||||
native_dimen.w, native_dimen.h = native_dimen.h, native_dimen.w
|
native_dimen.w, native_dimen.h = native_dimen.h, native_dimen.w
|
||||||
end
|
end
|
||||||
native_dimen:scaleBy(zoom)
|
native_dimen:scaleBy(zoom)
|
||||||
--DEBUG("dimen for pageno", pageno, "zoom", zoom, "rotation", rotation, "is", native_dimen)
|
--DEBUG("dimen for pageno", pageno, "zoom", zoom, "rotation", rotation, "is", native_dimen)
|
||||||
return native_dimen
|
return native_dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getPageBBox(pageno)
|
function Document:getPageBBox(pageno)
|
||||||
local bbox = self.bbox[pageno] -- exact
|
local bbox = self.bbox[pageno] -- exact
|
||||||
if bbox ~= nil then
|
if bbox ~= nil then
|
||||||
--DEBUG("bbox from", pageno)
|
--DEBUG("bbox from", pageno)
|
||||||
return bbox
|
return bbox
|
||||||
else
|
else
|
||||||
local oddEven = Math.oddEven(pageno)
|
local oddEven = Math.oddEven(pageno)
|
||||||
bbox = self.bbox[oddEven] -- odd/even
|
bbox = self.bbox[oddEven] -- odd/even
|
||||||
end
|
end
|
||||||
if bbox ~= nil then -- last used up to this page
|
if bbox ~= nil then -- last used up to this page
|
||||||
--DEBUG("bbox from", oddEven)
|
--DEBUG("bbox from", oddEven)
|
||||||
return bbox
|
return bbox
|
||||||
else
|
else
|
||||||
for i = 0,pageno do
|
for i = 0,pageno do
|
||||||
bbox = self.bbox[ pageno - i ]
|
bbox = self.bbox[ pageno - i ]
|
||||||
if bbox ~= nil then
|
if bbox ~= nil then
|
||||||
--DEBUG("bbox from", pageno - i)
|
--DEBUG("bbox from", pageno - i)
|
||||||
return bbox
|
return bbox
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if bbox == nil then -- fallback bbox
|
if bbox == nil then -- fallback bbox
|
||||||
bbox = self:getUsedBBox(pageno)
|
bbox = self:getUsedBBox(pageno)
|
||||||
--DEBUG("bbox from ORIGINAL page")
|
--DEBUG("bbox from ORIGINAL page")
|
||||||
end
|
end
|
||||||
--DEBUG("final bbox", bbox)
|
--DEBUG("final bbox", bbox)
|
||||||
return bbox
|
return bbox
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
This method returns pagesize if bbox is corrupted
|
This method returns pagesize if bbox is corrupted
|
||||||
--]]
|
--]]
|
||||||
function Document:getUsedBBoxDimensions(pageno, zoom, rotation)
|
function Document:getUsedBBoxDimensions(pageno, zoom, rotation)
|
||||||
local bbox = self:getPageBBox(pageno)
|
local bbox = self:getPageBBox(pageno)
|
||||||
-- clipping page bbox
|
-- clipping page bbox
|
||||||
if bbox.x0 < 0 then bbox.x0 = 0 end
|
if bbox.x0 < 0 then bbox.x0 = 0 end
|
||||||
if bbox.y0 < 0 then bbox.y0 = 0 end
|
if bbox.y0 < 0 then bbox.y0 = 0 end
|
||||||
if bbox.x1 < 0 then bbox.x1 = 0 end
|
if bbox.x1 < 0 then bbox.x1 = 0 end
|
||||||
if bbox.y1 < 0 then bbox.y1 = 0 end
|
if bbox.y1 < 0 then bbox.y1 = 0 end
|
||||||
local ubbox_dimen = nil
|
local ubbox_dimen = nil
|
||||||
if (bbox.x0 > bbox.x1) or (bbox.y0 > bbox.y1) then
|
if (bbox.x0 > bbox.x1) or (bbox.y0 > bbox.y1) then
|
||||||
-- if document's bbox info is corrupted, we use the page size
|
-- if document's bbox info is corrupted, we use the page size
|
||||||
ubbox_dimen = self:getPageDimensions(pageno, zoom, rotation)
|
ubbox_dimen = self:getPageDimensions(pageno, zoom, rotation)
|
||||||
else
|
else
|
||||||
ubbox_dimen = Geom:new{
|
ubbox_dimen = Geom:new{
|
||||||
x = bbox.x0,
|
x = bbox.x0,
|
||||||
y = bbox.y0,
|
y = bbox.y0,
|
||||||
w = bbox.x1 - bbox.x0,
|
w = bbox.x1 - bbox.x0,
|
||||||
h = bbox.y1 - bbox.y0,
|
h = bbox.y1 - bbox.y0,
|
||||||
}
|
}
|
||||||
if zoom ~= 1 then
|
if zoom ~= 1 then
|
||||||
ubbox_dimen:transformByScale(zoom)
|
ubbox_dimen:transformByScale(zoom)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return ubbox_dimen
|
return ubbox_dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getToc()
|
function Document:getToc()
|
||||||
return self._document:getToc()
|
return self._document:getToc()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getPageLinks(pageno)
|
function Document:getPageLinks(pageno)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getLinkFromPosition(pageno, pos)
|
function Document:getLinkFromPosition(pageno, pos)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getTextBoxes(pageno)
|
function Document:getTextBoxes(pageno)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getOCRWord(pageno, rect)
|
function Document:getOCRWord(pageno, rect)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
local hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
local hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
||||||
local page_size = self:getPageDimensions(pageno, zoom, rotation)
|
local page_size = self:getPageDimensions(pageno, zoom, rotation)
|
||||||
-- this will be the size we actually render
|
-- this will be the size we actually render
|
||||||
local size = page_size
|
local size = page_size
|
||||||
-- we prefer to render the full page, if it fits into cache
|
-- we prefer to render the full page, if it fits into cache
|
||||||
if not Cache:willAccept(size.w * size.h / 2) then
|
if not Cache:willAccept(size.w * size.h / 2) then
|
||||||
-- whole page won't fit into cache
|
-- whole page won't fit into cache
|
||||||
DEBUG("rendering only part of the page")
|
DEBUG("rendering only part of the page")
|
||||||
-- TODO: figure out how to better segment the page
|
-- TODO: figure out how to better segment the page
|
||||||
if not rect then
|
if not rect then
|
||||||
DEBUG("aborting, since we do not have a specification for that part")
|
DEBUG("aborting, since we do not have a specification for that part")
|
||||||
-- required part not given, so abort
|
-- required part not given, so abort
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- only render required part
|
-- only render required part
|
||||||
hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode.."|"..tostring(rect)
|
hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode.."|"..tostring(rect)
|
||||||
size = rect
|
size = rect
|
||||||
end
|
end
|
||||||
|
|
||||||
-- prepare cache item with contained blitbuffer
|
-- prepare cache item with contained blitbuffer
|
||||||
local tile = TileCacheItem:new{
|
local tile = TileCacheItem:new{
|
||||||
size = size.w * size.h / 2 + 64, -- estimation
|
size = size.w * size.h / 2 + 64, -- estimation
|
||||||
excerpt = size,
|
excerpt = size,
|
||||||
pageno = pageno,
|
pageno = pageno,
|
||||||
bb = Blitbuffer.new(size.w, size.h)
|
bb = Blitbuffer.new(size.w, size.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
-- create a draw context
|
-- create a draw context
|
||||||
local dc = DrawContext.new()
|
local dc = DrawContext.new()
|
||||||
|
|
||||||
dc:setRotate(rotation)
|
dc:setRotate(rotation)
|
||||||
-- correction of rotation
|
-- correction of rotation
|
||||||
if rotation == 90 then
|
if rotation == 90 then
|
||||||
dc:setOffset(page_size.w, 0)
|
dc:setOffset(page_size.w, 0)
|
||||||
elseif rotation == 180 then
|
elseif rotation == 180 then
|
||||||
dc:setOffset(page_size.w, page_size.h)
|
dc:setOffset(page_size.w, page_size.h)
|
||||||
elseif rotation == 270 then
|
elseif rotation == 270 then
|
||||||
dc:setOffset(0, page_size.h)
|
dc:setOffset(0, page_size.h)
|
||||||
end
|
end
|
||||||
dc:setZoom(zoom)
|
dc:setZoom(zoom)
|
||||||
|
|
||||||
if gamma ~= self.GAMMA_NO_GAMMA then
|
if gamma ~= self.GAMMA_NO_GAMMA then
|
||||||
--DEBUG("gamma correction: ", gamma)
|
--DEBUG("gamma correction: ", gamma)
|
||||||
dc:setGamma(gamma)
|
dc:setGamma(gamma)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- render
|
-- render
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
page:draw(dc, tile.bb, size.x, size.y, render_mode)
|
page:draw(dc, tile.bb, size.x, size.y, render_mode)
|
||||||
page:close()
|
page:close()
|
||||||
Cache:insert(hash, tile)
|
Cache:insert(hash, tile)
|
||||||
|
|
||||||
return tile
|
return tile
|
||||||
end
|
end
|
||||||
|
|
||||||
-- a hint for the cache engine to paint a full page to the cache
|
-- a hint for the cache engine to paint a full page to the cache
|
||||||
-- TODO: this should trigger a background operation
|
-- TODO: this should trigger a background operation
|
||||||
function Document:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
function Document:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
||||||
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
||||||
if not Cache:check(hash_full_page) then
|
if not Cache:check(hash_full_page) then
|
||||||
DEBUG("hinting page", pageno)
|
DEBUG("hinting page", pageno)
|
||||||
self:renderPage(pageno, nil, zoom, rotation, gamma, render_mode)
|
self:renderPage(pageno, nil, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -268,59 +268,59 @@ Draw page content to blitbuffer.
|
|||||||
@rect: visible_area inside document page
|
@rect: visible_area inside document page
|
||||||
--]]
|
--]]
|
||||||
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||||
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..gamma.."|"..render_mode
|
||||||
local hash_excerpt = hash_full_page.."|"..tostring(rect)
|
local hash_excerpt = hash_full_page.."|"..tostring(rect)
|
||||||
local tile = Cache:check(hash_full_page)
|
local tile = Cache:check(hash_full_page)
|
||||||
if not tile then
|
if not tile then
|
||||||
tile = Cache:check(hash_excerpt)
|
tile = Cache:check(hash_excerpt)
|
||||||
if not tile then
|
if not tile then
|
||||||
DEBUG("rendering")
|
DEBUG("rendering")
|
||||||
tile = self:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
tile = self:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
DEBUG("now painting", tile, rect)
|
DEBUG("now painting", tile, rect)
|
||||||
target:blitFrom(tile.bb,
|
target:blitFrom(tile.bb,
|
||||||
x, y,
|
x, y,
|
||||||
rect.x - tile.excerpt.x,
|
rect.x - tile.excerpt.x,
|
||||||
rect.y - tile.excerpt.y,
|
rect.y - tile.excerpt.y,
|
||||||
rect.w, rect.h)
|
rect.w, rect.h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:getPageText(pageno)
|
function Document:getPageText(pageno)
|
||||||
-- is this worth caching? not done yet.
|
-- is this worth caching? not done yet.
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local text = page:getPageText()
|
local text = page:getPageText()
|
||||||
page:close()
|
page:close()
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
function Document:saveHighlight(pageno, item)
|
function Document:saveHighlight(pageno, item)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
helper functions
|
helper functions
|
||||||
--]]
|
--]]
|
||||||
function Document:logMemoryUsage(pageno)
|
function Document:logMemoryUsage(pageno)
|
||||||
local status_file = io.open("/proc/self/status", "r")
|
local status_file = io.open("/proc/self/status", "r")
|
||||||
local log_file = io.open("mem_usage_log.txt", "a+")
|
local log_file = io.open("mem_usage_log.txt", "a+")
|
||||||
local data = -1
|
local data = -1
|
||||||
if status_file then
|
if status_file then
|
||||||
for line in status_file:lines() do
|
for line in status_file:lines() do
|
||||||
local s, n
|
local s, n
|
||||||
s, n = line:gsub("VmData:%s-(%d+) kB", "%1")
|
s, n = line:gsub("VmData:%s-(%d+) kB", "%1")
|
||||||
if n ~= 0 then data = tonumber(s) end
|
if n ~= 0 then data = tonumber(s) end
|
||||||
if data ~= -1 then break end
|
if data ~= -1 then break end
|
||||||
end
|
end
|
||||||
status_file:close()
|
status_file:close()
|
||||||
end
|
end
|
||||||
if log_file then
|
if log_file then
|
||||||
if log_file:seek("end") == 0 then -- write the header only once
|
if log_file:seek("end") == 0 then -- write the header only once
|
||||||
log_file:write("PAGE\tMEM\n")
|
log_file:write("PAGE\tMEM\n")
|
||||||
end
|
end
|
||||||
log_file:write(string.format("%s\t%s\n", pageno, data))
|
log_file:write(string.format("%s\t%s\n", pageno, data))
|
||||||
log_file:close()
|
log_file:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Document
|
return Document
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
This is a registry for document providers
|
This is a registry for document providers
|
||||||
]]--
|
]]--
|
||||||
local DocumentRegistry = {
|
local DocumentRegistry = {
|
||||||
providers = { }
|
providers = { }
|
||||||
}
|
}
|
||||||
|
|
||||||
function DocumentRegistry:addProvider(extension, mimetype, provider)
|
function DocumentRegistry:addProvider(extension, mimetype, provider)
|
||||||
table.insert(self.providers, { extension = extension, mimetype = mimetype, provider = provider })
|
table.insert(self.providers, { extension = extension, mimetype = mimetype, provider = provider })
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocumentRegistry:getProvider(file)
|
function DocumentRegistry:getProvider(file)
|
||||||
-- TODO: some implementation based on mime types?
|
-- TODO: some implementation based on mime types?
|
||||||
local extension = string.lower(string.match(file, ".+%.([^.]+)") or "")
|
local extension = string.lower(string.match(file, ".+%.([^.]+)") or "")
|
||||||
for _, provider in ipairs(self.providers) do
|
for _, provider in ipairs(self.providers) do
|
||||||
if extension == provider.extension then
|
if extension == provider.extension then
|
||||||
return provider.provider
|
return provider.provider
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DocumentRegistry:openDocument(file)
|
function DocumentRegistry:openDocument(file)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,211 +8,211 @@ local ffi = require("ffi")
|
|||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
typedef struct fz_point_s fz_point;
|
typedef struct fz_point_s fz_point;
|
||||||
struct fz_point_s {
|
struct fz_point_s {
|
||||||
float x, y;
|
float x, y;
|
||||||
};
|
};
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FZ_ANNOT_TEXT,
|
FZ_ANNOT_TEXT,
|
||||||
FZ_ANNOT_LINK,
|
FZ_ANNOT_LINK,
|
||||||
FZ_ANNOT_FREETEXT,
|
FZ_ANNOT_FREETEXT,
|
||||||
FZ_ANNOT_LINE,
|
FZ_ANNOT_LINE,
|
||||||
FZ_ANNOT_SQUARE,
|
FZ_ANNOT_SQUARE,
|
||||||
FZ_ANNOT_CIRCLE,
|
FZ_ANNOT_CIRCLE,
|
||||||
FZ_ANNOT_POLYGON,
|
FZ_ANNOT_POLYGON,
|
||||||
FZ_ANNOT_POLYLINE,
|
FZ_ANNOT_POLYLINE,
|
||||||
FZ_ANNOT_HIGHLIGHT,
|
FZ_ANNOT_HIGHLIGHT,
|
||||||
FZ_ANNOT_UNDERLINE,
|
FZ_ANNOT_UNDERLINE,
|
||||||
FZ_ANNOT_SQUIGGLY,
|
FZ_ANNOT_SQUIGGLY,
|
||||||
FZ_ANNOT_STRIKEOUT,
|
FZ_ANNOT_STRIKEOUT,
|
||||||
FZ_ANNOT_STAMP,
|
FZ_ANNOT_STAMP,
|
||||||
FZ_ANNOT_CARET,
|
FZ_ANNOT_CARET,
|
||||||
FZ_ANNOT_INK,
|
FZ_ANNOT_INK,
|
||||||
FZ_ANNOT_POPUP,
|
FZ_ANNOT_POPUP,
|
||||||
FZ_ANNOT_FILEATTACHMENT,
|
FZ_ANNOT_FILEATTACHMENT,
|
||||||
FZ_ANNOT_SOUND,
|
FZ_ANNOT_SOUND,
|
||||||
FZ_ANNOT_MOVIE,
|
FZ_ANNOT_MOVIE,
|
||||||
FZ_ANNOT_WIDGET,
|
FZ_ANNOT_WIDGET,
|
||||||
FZ_ANNOT_SCREEN,
|
FZ_ANNOT_SCREEN,
|
||||||
FZ_ANNOT_PRINTERMARK,
|
FZ_ANNOT_PRINTERMARK,
|
||||||
FZ_ANNOT_TRAPNET,
|
FZ_ANNOT_TRAPNET,
|
||||||
FZ_ANNOT_WATERMARK,
|
FZ_ANNOT_WATERMARK,
|
||||||
FZ_ANNOT_3D
|
FZ_ANNOT_3D
|
||||||
} fz_annot_type;
|
} fz_annot_type;
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local PdfDocument = Document:new{
|
local PdfDocument = Document:new{
|
||||||
_document = false,
|
_document = false,
|
||||||
-- muPDF manages its own additional cache
|
-- muPDF manages its own additional cache
|
||||||
mupdf_cache_size = 5 * 1024 * 1024,
|
mupdf_cache_size = 5 * 1024 * 1024,
|
||||||
dc_null = DrawContext.new(),
|
dc_null = DrawContext.new(),
|
||||||
options = KoptOptions,
|
options = KoptOptions,
|
||||||
koptinterface = nil,
|
koptinterface = nil,
|
||||||
annot_revision = 0,
|
annot_revision = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function PdfDocument:init()
|
function PdfDocument:init()
|
||||||
local pdf = require("libs/libkoreader-pdf")
|
local pdf = require("libs/libkoreader-pdf")
|
||||||
self.koptinterface = require("document/koptinterface")
|
self.koptinterface = require("document/koptinterface")
|
||||||
self.configurable:loadDefaults(self.options)
|
self.configurable:loadDefaults(self.options)
|
||||||
local ok
|
local ok
|
||||||
ok, self._document = pcall(pdf.openDocument, self.file, self.mupdf_cache_size)
|
ok, self._document = pcall(pdf.openDocument, self.file, self.mupdf_cache_size)
|
||||||
if not ok then
|
if not ok then
|
||||||
self.error_message = self.doc -- will contain error message
|
self.error_message = self.doc -- will contain error message
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.is_open = true
|
self.is_open = true
|
||||||
self.info.has_pages = true
|
self.info.has_pages = true
|
||||||
self.info.configurable = true
|
self.info.configurable = true
|
||||||
if self._document:needsPassword() then
|
if self._document:needsPassword() then
|
||||||
self.is_locked = true
|
self.is_locked = true
|
||||||
else
|
else
|
||||||
self:_readMetadata()
|
self:_readMetadata()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:unlock(password)
|
function PdfDocument:unlock(password)
|
||||||
if not self._document:authenticatePassword(password) then
|
if not self._document:authenticatePassword(password) then
|
||||||
self._document:close()
|
self._document:close()
|
||||||
return false, "wrong password"
|
return false, "wrong password"
|
||||||
end
|
end
|
||||||
self.is_locked = false
|
self.is_locked = false
|
||||||
return self:_readMetadata()
|
return self:_readMetadata()
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageTextBoxes(pageno)
|
function PdfDocument:getPageTextBoxes(pageno)
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local text = page:getPageText()
|
local text = page:getPageText()
|
||||||
page:close()
|
page:close()
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getWordFromPosition(spos)
|
function PdfDocument:getWordFromPosition(spos)
|
||||||
return self.koptinterface:getWordFromPosition(self, spos)
|
return self.koptinterface:getWordFromPosition(self, spos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getTextFromPositions(spos0, spos1)
|
function PdfDocument:getTextFromPositions(spos0, spos1)
|
||||||
return self.koptinterface:getTextFromPositions(self, spos0, spos1)
|
return self.koptinterface:getTextFromPositions(self, spos0, spos1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageBoxesFromPositions(pageno, ppos0, ppos1)
|
function PdfDocument:getPageBoxesFromPositions(pageno, ppos0, ppos1)
|
||||||
return self.koptinterface:getPageBoxesFromPositions(self, pageno, ppos0, ppos1)
|
return self.koptinterface:getPageBoxesFromPositions(self, pageno, ppos0, ppos1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getOCRWord(pageno, wbox)
|
function PdfDocument:getOCRWord(pageno, wbox)
|
||||||
return self.koptinterface:getOCRWord(self, pageno, wbox)
|
return self.koptinterface:getOCRWord(self, pageno, wbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getOCRText(pageno, tboxes)
|
function PdfDocument:getOCRText(pageno, tboxes)
|
||||||
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageRegions(pageno)
|
function PdfDocument:getPageRegions(pageno)
|
||||||
return self.koptinterface:getPageRegions(self, pageno)
|
return self.koptinterface:getPageRegions(self, pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getUsedBBox(pageno)
|
function PdfDocument:getUsedBBox(pageno)
|
||||||
local hash = "pgubbox|"..self.file.."|"..pageno
|
local hash = "pgubbox|"..self.file.."|"..pageno
|
||||||
local cached = Cache:check(hash)
|
local cached = Cache:check(hash)
|
||||||
if cached then
|
if cached then
|
||||||
return cached.ubbox
|
return cached.ubbox
|
||||||
end
|
end
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local used = {}
|
local used = {}
|
||||||
used.x0, used.y0, used.x1, used.y1 = page:getUsedBBox()
|
used.x0, used.y0, used.x1, used.y1 = page:getUsedBBox()
|
||||||
local pwidth, pheight = page:getSize(self.dc_null)
|
local pwidth, pheight = page:getSize(self.dc_null)
|
||||||
-- clamp to page BBox
|
-- clamp to page BBox
|
||||||
if used.x0 < 0 then used.x0 = 0 end
|
if used.x0 < 0 then used.x0 = 0 end
|
||||||
if used.x1 > pwidth then used.x1 = pwidth end
|
if used.x1 > pwidth then used.x1 = pwidth end
|
||||||
if used.y0 < 0 then used.y0 = 0 end
|
if used.y0 < 0 then used.y0 = 0 end
|
||||||
if used.y1 > pheight then used.y1 = pheight end
|
if used.y1 > pheight then used.y1 = pheight end
|
||||||
--@TODO give size for cacheitem? 02.12 2012 (houqp)
|
--@TODO give size for cacheitem? 02.12 2012 (houqp)
|
||||||
Cache:insert(hash, CacheItem:new{
|
Cache:insert(hash, CacheItem:new{
|
||||||
ubbox = used,
|
ubbox = used,
|
||||||
})
|
})
|
||||||
page:close()
|
page:close()
|
||||||
return used
|
return used
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageLinks(pageno)
|
function PdfDocument:getPageLinks(pageno)
|
||||||
local hash = "pglinks|"..self.file.."|"..pageno
|
local hash = "pglinks|"..self.file.."|"..pageno
|
||||||
local cached = Cache:check(hash)
|
local cached = Cache:check(hash)
|
||||||
if cached then
|
if cached then
|
||||||
return cached.links
|
return cached.links
|
||||||
end
|
end
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local links = page:getPageLinks()
|
local links = page:getPageLinks()
|
||||||
Cache:insert(hash, CacheItem:new{
|
Cache:insert(hash, CacheItem:new{
|
||||||
links = links,
|
links = links,
|
||||||
})
|
})
|
||||||
page:close()
|
page:close()
|
||||||
return links
|
return links
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:saveHighlight(pageno, item)
|
function PdfDocument:saveHighlight(pageno, item)
|
||||||
self.annot_revision = self.annot_revision + 1
|
self.annot_revision = self.annot_revision + 1
|
||||||
local n = #item.pboxes
|
local n = #item.pboxes
|
||||||
local quadpoints = ffi.new("fz_point[?]", 4*n)
|
local quadpoints = ffi.new("fz_point[?]", 4*n)
|
||||||
for i=1, n do
|
for i=1, n do
|
||||||
quadpoints[4*i-4].x = item.pboxes[i].x + item.pboxes[i].w
|
quadpoints[4*i-4].x = item.pboxes[i].x + item.pboxes[i].w
|
||||||
quadpoints[4*i-4].y = item.pboxes[i].y + item.pboxes[i].h
|
quadpoints[4*i-4].y = item.pboxes[i].y + item.pboxes[i].h
|
||||||
quadpoints[4*i-3].x = item.pboxes[i].x
|
quadpoints[4*i-3].x = item.pboxes[i].x
|
||||||
quadpoints[4*i-3].y = item.pboxes[i].y + item.pboxes[i].h
|
quadpoints[4*i-3].y = item.pboxes[i].y + item.pboxes[i].h
|
||||||
quadpoints[4*i-2].x = item.pboxes[i].x
|
quadpoints[4*i-2].x = item.pboxes[i].x
|
||||||
quadpoints[4*i-2].y = item.pboxes[i].y
|
quadpoints[4*i-2].y = item.pboxes[i].y
|
||||||
quadpoints[4*i-1].x = item.pboxes[i].x + item.pboxes[i].w
|
quadpoints[4*i-1].x = item.pboxes[i].x + item.pboxes[i].w
|
||||||
quadpoints[4*i-1].y = item.pboxes[i].y
|
quadpoints[4*i-1].y = item.pboxes[i].y
|
||||||
end
|
end
|
||||||
local page = self._document:openPage(pageno)
|
local page = self._document:openPage(pageno)
|
||||||
local annot_type = ffi.C.FZ_ANNOT_HIGHLIGHT
|
local annot_type = ffi.C.FZ_ANNOT_HIGHLIGHT
|
||||||
if item.drawer == "lighten" then
|
if item.drawer == "lighten" then
|
||||||
annot_type = ffi.C.FZ_ANNOT_HIGHLIGHT
|
annot_type = ffi.C.FZ_ANNOT_HIGHLIGHT
|
||||||
elseif item.drawer == "underscore" then
|
elseif item.drawer == "underscore" then
|
||||||
annot_type = ffi.C.FZ_ANNOT_UNDERLINE
|
annot_type = ffi.C.FZ_ANNOT_UNDERLINE
|
||||||
elseif item.drawer == "strikeout" then
|
elseif item.drawer == "strikeout" then
|
||||||
annot_type = ffi.C.FZ_ANNOT_STRIKEOUT
|
annot_type = ffi.C.FZ_ANNOT_STRIKEOUT
|
||||||
end
|
end
|
||||||
page:addMarkupAnnotation(quadpoints, 4*n, annot_type)
|
page:addMarkupAnnotation(quadpoints, 4*n, annot_type)
|
||||||
page:close()
|
page:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:writeDocument()
|
function PdfDocument:writeDocument()
|
||||||
self._document:writeDocument(self.file)
|
self._document:writeDocument(self.file)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:close()
|
function PdfDocument:close()
|
||||||
if self.annot_revision ~= 0 then
|
if self.annot_revision ~= 0 then
|
||||||
self:writeDocument()
|
self:writeDocument()
|
||||||
end
|
end
|
||||||
Document.close(self)
|
Document.close(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getLinkFromPosition(pageno, pos)
|
function PdfDocument:getLinkFromPosition(pageno, pos)
|
||||||
return self.koptinterface:getLinkFromPosition(self, pageno, pos)
|
return self.koptinterface:getLinkFromPosition(self, pageno, pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageBBox(pageno)
|
function PdfDocument:getPageBBox(pageno)
|
||||||
return self.koptinterface:getPageBBox(self, pageno)
|
return self.koptinterface:getPageBBox(self, pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:getPageDimensions(pageno, zoom, rotation)
|
function PdfDocument:getPageDimensions(pageno, zoom, rotation)
|
||||||
return self.koptinterface:getPageDimensions(self, pageno, zoom, rotation)
|
return self.koptinterface:getPageDimensions(self, pageno, zoom, rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
function PdfDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||||
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PdfDocument:register(registry)
|
function PdfDocument:register(registry)
|
||||||
registry:addProvider("pdf", "application/pdf", self)
|
registry:addProvider("pdf", "application/pdf", self)
|
||||||
registry:addProvider("cbz", "application/cbz", self)
|
registry:addProvider("cbz", "application/cbz", self)
|
||||||
registry:addProvider("xps", "application/xps", self)
|
registry:addProvider("xps", "application/xps", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return PdfDocument
|
return PdfDocument
|
||||||
|
|||||||
@@ -2,31 +2,31 @@ local Document = require("document/document")
|
|||||||
local DrawContext = require("ffi/drawcontext")
|
local DrawContext = require("ffi/drawcontext")
|
||||||
|
|
||||||
local PicDocument = Document:new{
|
local PicDocument = Document:new{
|
||||||
_document = false,
|
_document = false,
|
||||||
dc_null = DrawContext.new()
|
dc_null = DrawContext.new()
|
||||||
}
|
}
|
||||||
|
|
||||||
function PicDocument:init()
|
function PicDocument:init()
|
||||||
require "libs/libkoreader-pic"
|
require "libs/libkoreader-pic"
|
||||||
ok, self._document = pcall(pic.openDocument, self.file)
|
ok, self._document = pcall(pic.openDocument, self.file)
|
||||||
if not ok then
|
if not ok then
|
||||||
self.error_message = "failed to open jpeg image"
|
self.error_message = "failed to open jpeg image"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
self.info.has_pages = true
|
self.info.has_pages = true
|
||||||
self.info.configurable = false
|
self.info.configurable = false
|
||||||
|
|
||||||
self:readMetadata()
|
self:readMetadata()
|
||||||
end
|
end
|
||||||
|
|
||||||
function PicDocument:readMetadata()
|
function PicDocument:readMetadata()
|
||||||
self.info.number_of_pages = 1
|
self.info.number_of_pages = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function PicDocument:register(registry)
|
function PicDocument:register(registry)
|
||||||
registry:addProvider("jpeg", "application/jpeg", self)
|
registry:addProvider("jpeg", "application/jpeg", self)
|
||||||
registry:addProvider("jpg", "application/jpeg", self)
|
registry:addProvider("jpg", "application/jpeg", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return PicDocument
|
return PicDocument
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ local DEBUG = require("dbg")
|
|||||||
local TileCacheItem = CacheItem:new{}
|
local TileCacheItem = CacheItem:new{}
|
||||||
|
|
||||||
function TileCacheItem:onFree()
|
function TileCacheItem:onFree()
|
||||||
if self.bb.free then
|
if self.bb.free then
|
||||||
DEBUG("free blitbuffer", self.bb)
|
DEBUG("free blitbuffer", self.bb)
|
||||||
self.bb:free()
|
self.bb:free()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return TileCacheItem
|
return TileCacheItem
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ local GetText = {}
|
|||||||
local GetText_mt = {}
|
local GetText_mt = {}
|
||||||
|
|
||||||
function GetText_mt.__call(gettext, string)
|
function GetText_mt.__call(gettext, string)
|
||||||
return lua_gettext.translate(string)
|
return lua_gettext.translate(string)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetText.changeLang(new_lang)
|
function GetText.changeLang(new_lang)
|
||||||
lua_gettext.change_lang(new_lang)
|
lua_gettext.change_lang(new_lang)
|
||||||
end
|
end
|
||||||
|
|
||||||
setmetatable(GetText, GetText_mt)
|
setmetatable(GetText, GetText_mt)
|
||||||
|
|||||||
@@ -5,42 +5,42 @@ Simple math helper function
|
|||||||
local Math = {}
|
local Math = {}
|
||||||
|
|
||||||
function Math.roundAwayFromZero(num)
|
function Math.roundAwayFromZero(num)
|
||||||
if num > 0 then
|
if num > 0 then
|
||||||
return math.ceil(num)
|
return math.ceil(num)
|
||||||
else
|
else
|
||||||
return math.floor(num)
|
return math.floor(num)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Math.round(num)
|
function Math.round(num)
|
||||||
return math.floor(num + 0.5)
|
return math.floor(num + 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Math.oddEven(number)
|
function Math.oddEven(number)
|
||||||
if number % 2 == 1 then
|
if number % 2 == 1 then
|
||||||
return "odd"
|
return "odd"
|
||||||
else
|
else
|
||||||
return "even"
|
return "even"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tmin_max(tab, func, op)
|
local function tmin_max(tab, func, op)
|
||||||
if #tab == 0 then return nil, nil end
|
if #tab == 0 then return nil, nil end
|
||||||
local index, value = 1, tab[1]
|
local index, value = 1, tab[1]
|
||||||
for i = 2, #tab do
|
for i = 2, #tab do
|
||||||
if func then
|
if func then
|
||||||
if func(value, tab[i]) then
|
if func(value, tab[i]) then
|
||||||
index, value = i, tab[i]
|
index, value = i, tab[i]
|
||||||
end
|
end
|
||||||
elseif op == "min" then
|
elseif op == "min" then
|
||||||
if value > tab[i] then
|
if value > tab[i] then
|
||||||
index, value = i, tab[i]
|
index, value = i, tab[i]
|
||||||
end
|
end
|
||||||
elseif op == "max" then
|
elseif op == "max" then
|
||||||
if value < tab[i] then
|
if value < tab[i] then
|
||||||
index, value = i, tab[i]
|
index, value = i, tab[i]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return index, value
|
return index, value
|
||||||
end
|
end
|
||||||
@@ -50,7 +50,7 @@ Return the minimum element of a table.
|
|||||||
The optional argument func specifies a one-argument ordering function.
|
The optional argument func specifies a one-argument ordering function.
|
||||||
]]--
|
]]--
|
||||||
function Math.tmin(tab, func)
|
function Math.tmin(tab, func)
|
||||||
return tmin_max(tab, func, "min")
|
return tmin_max(tab, func, "min")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -58,7 +58,7 @@ Return the maximum element of a table.
|
|||||||
The optional argument func specifies a one-argument ordering function.
|
The optional argument func specifies a one-argument ordering function.
|
||||||
]]--
|
]]--
|
||||||
function Math.tmax(tab, func)
|
function Math.tmax(tab, func)
|
||||||
return tmin_max(tab, func, "max")
|
return tmin_max(tab, func, "max")
|
||||||
end
|
end
|
||||||
|
|
||||||
return Math
|
return Math
|
||||||
|
|||||||
@@ -5,144 +5,144 @@ local _ = require("gettext")
|
|||||||
|
|
||||||
-- add multiply operator to Aa dict
|
-- add multiply operator to Aa dict
|
||||||
local Aa = setmetatable({"Aa"}, {
|
local Aa = setmetatable({"Aa"}, {
|
||||||
__mul = function(t, mul)
|
__mul = function(t, mul)
|
||||||
local new = {}
|
local new = {}
|
||||||
for i = 1, mul do
|
for i = 1, mul do
|
||||||
for _, v in ipairs(t) do table.insert(new, v) end
|
for _, v in ipairs(t) do table.insert(new, v) end
|
||||||
end
|
end
|
||||||
return new
|
return new
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
local CreOptions = {
|
local CreOptions = {
|
||||||
prefix = 'copt',
|
prefix = 'copt',
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.transform.rotate.right.large.png",
|
icon = "resources/icons/appbar.transform.rotate.right.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "screen_mode",
|
name = "screen_mode",
|
||||||
name_text = S.SCREEN_MODE,
|
name_text = S.SCREEN_MODE,
|
||||||
toggle = {S.PORTRAIT, S.LANDSCAPE},
|
toggle = {S.PORTRAIT, S.LANDSCAPE},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
args = {"portrait", "landscape"},
|
args = {"portrait", "landscape"},
|
||||||
default_arg = "portrait",
|
default_arg = "portrait",
|
||||||
current_func = function() return Screen:getScreenMode() end,
|
current_func = function() return Screen:getScreenMode() end,
|
||||||
event = "ChangeScreenMode",
|
event = "ChangeScreenMode",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.column.two.large.png",
|
icon = "resources/icons/appbar.column.two.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "line_spacing",
|
name = "line_spacing",
|
||||||
name_text = S.LINE_SPACING,
|
name_text = S.LINE_SPACING,
|
||||||
toggle = {S.DECREASE, S.INCREASE},
|
toggle = {S.DECREASE, S.INCREASE},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
args = {"decrease", "increase"},
|
args = {"decrease", "increase"},
|
||||||
default_arg = "decrease",
|
default_arg = "decrease",
|
||||||
event = "ChangeLineSpace",
|
event = "ChangeLineSpace",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "page_margins",
|
name = "page_margins",
|
||||||
name_text = S.PAGE_MARGIN,
|
name_text = S.PAGE_MARGIN,
|
||||||
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
||||||
values = {
|
values = {
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_SMALL,
|
DCREREADER_CONFIG_MARGIN_SIZES_SMALL,
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_LARGE,
|
DCREREADER_CONFIG_MARGIN_SIZES_LARGE,
|
||||||
},
|
},
|
||||||
default_value = DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
default_value = DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
||||||
args = {
|
args = {
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_SMALL,
|
DCREREADER_CONFIG_MARGIN_SIZES_SMALL,
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM,
|
||||||
DCREREADER_CONFIG_MARGIN_SIZES_LARGE,
|
DCREREADER_CONFIG_MARGIN_SIZES_LARGE,
|
||||||
},
|
},
|
||||||
event = "SetPageMargins",
|
event = "SetPageMargins",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.text.size.large.png",
|
icon = "resources/icons/appbar.text.size.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "font_size",
|
name = "font_size",
|
||||||
item_text = Aa * #DCREREADER_CONFIG_FONT_SIZES,
|
item_text = Aa * #DCREREADER_CONFIG_FONT_SIZES,
|
||||||
item_align_center = 1.0,
|
item_align_center = 1.0,
|
||||||
spacing = 15,
|
spacing = 15,
|
||||||
item_font_size = DCREREADER_CONFIG_FONT_SIZES,
|
item_font_size = DCREREADER_CONFIG_FONT_SIZES,
|
||||||
values = DCREREADER_CONFIG_FONT_SIZES,
|
values = DCREREADER_CONFIG_FONT_SIZES,
|
||||||
default_value = DCREREADER_CONFIG_DEFAULT_FONT_SIZE,
|
default_value = DCREREADER_CONFIG_DEFAULT_FONT_SIZE,
|
||||||
args = DCREREADER_CONFIG_FONT_SIZES,
|
args = DCREREADER_CONFIG_FONT_SIZES,
|
||||||
event = "SetFontSize",
|
event = "SetFontSize",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "font_fine_tune",
|
name = "font_fine_tune",
|
||||||
name_text = S.FONTSIZE_FINE_TUNING,
|
name_text = S.FONTSIZE_FINE_TUNING,
|
||||||
toggle = {S.DECREASE, S.INCREASE},
|
toggle = {S.DECREASE, S.INCREASE},
|
||||||
event = "ChangeSize",
|
event = "ChangeSize",
|
||||||
args = {"decrease", "increase"},
|
args = {"decrease", "increase"},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
height = 60,
|
height = 60,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.grade.b.large.png",
|
icon = "resources/icons/appbar.grade.b.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "font_weight",
|
name = "font_weight",
|
||||||
name_text = S.FONT_WEIGHT,
|
name_text = S.FONT_WEIGHT,
|
||||||
toggle = {S.TOGGLE_BOLD},
|
toggle = {S.TOGGLE_BOLD},
|
||||||
default_arg = nil,
|
default_arg = nil,
|
||||||
event = "ToggleFontBolder",
|
event = "ToggleFontBolder",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "font_gamma",
|
name = "font_gamma",
|
||||||
name_text = S.CONTRAST,
|
name_text = S.CONTRAST,
|
||||||
toggle = {S.DECREASE, S.INCREASE},
|
toggle = {S.DECREASE, S.INCREASE},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
args = {"decrease", "increase"},
|
args = {"decrease", "increase"},
|
||||||
default_arg = "increase",
|
default_arg = "increase",
|
||||||
event = "ChangeFontGamma",
|
event = "ChangeFontGamma",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.settings.large.png",
|
icon = "resources/icons/appbar.settings.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "view_mode",
|
name = "view_mode",
|
||||||
name_text = S.VIEW_MODE,
|
name_text = S.VIEW_MODE,
|
||||||
toggle = {S.VIEW_SCROLL, S.VIEW_PAGE},
|
toggle = {S.VIEW_SCROLL, S.VIEW_PAGE},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = 0,
|
default_value = 0,
|
||||||
args = {"scroll", "page"},
|
args = {"scroll", "page"},
|
||||||
default_arg = "page",
|
default_arg = "page",
|
||||||
event = "SetViewMode",
|
event = "SetViewMode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "status_line",
|
name = "status_line",
|
||||||
name_text = S.PROGRESS_BAR,
|
name_text = S.PROGRESS_BAR,
|
||||||
toggle = {S.FULL, S.MINI},
|
toggle = {S.FULL, S.MINI},
|
||||||
values = {0, 1},
|
values = {0, 1},
|
||||||
default_value = DCREREADER_PROGRESS_BAR,
|
default_value = DCREREADER_PROGRESS_BAR,
|
||||||
args = {0, 1},
|
args = {0, 1},
|
||||||
default_arg = DCREREADER_PROGRESS_BAR,
|
default_arg = DCREREADER_PROGRESS_BAR,
|
||||||
event = "SetStatusLine",
|
event = "SetStatusLine",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "embedded_css",
|
name = "embedded_css",
|
||||||
name_text = S.EMBEDDED_STYLE,
|
name_text = S.EMBEDDED_STYLE,
|
||||||
toggle = {S.ON, S.OFF},
|
toggle = {S.ON, S.OFF},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = 1,
|
default_value = 1,
|
||||||
args = {true, false},
|
args = {true, false},
|
||||||
default_arg = nil,
|
default_arg = nil,
|
||||||
event = "ToggleEmbeddedStyleSheet",
|
event = "ToggleEmbeddedStyleSheet",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreOptions
|
return CreOptions
|
||||||
|
|||||||
@@ -4,222 +4,222 @@ local S = require("ui/data/strings")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local KoptOptions = {
|
local KoptOptions = {
|
||||||
prefix = 'kopt',
|
prefix = 'kopt',
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.transform.rotate.right.large.png",
|
icon = "resources/icons/appbar.transform.rotate.right.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "screen_mode",
|
name = "screen_mode",
|
||||||
name_text = S.SCREEN_MODE,
|
name_text = S.SCREEN_MODE,
|
||||||
toggle = {S.PORTRAIT, S.LANDSCAPE},
|
toggle = {S.PORTRAIT, S.LANDSCAPE},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
args = {"portrait", "landscape"},
|
args = {"portrait", "landscape"},
|
||||||
default_arg = "portrait",
|
default_arg = "portrait",
|
||||||
current_func = function() return Screen:getScreenMode() end,
|
current_func = function() return Screen:getScreenMode() end,
|
||||||
event = "SetScreenMode",
|
event = "SetScreenMode",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.crop.large.png",
|
icon = "resources/icons/appbar.crop.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "trim_page",
|
name = "trim_page",
|
||||||
name_text = S.PAGE_CROP,
|
name_text = S.PAGE_CROP,
|
||||||
width = 225,
|
width = 225,
|
||||||
toggle = {S.MANUAL, S.AUTO, S.SEMIAUTO},
|
toggle = {S.MANUAL, S.AUTO, S.SEMIAUTO},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
values = {0, 1, 2},
|
values = {0, 1, 2},
|
||||||
default_value = DKOPTREADER_CONFIG_TRIM_PAGE,
|
default_value = DKOPTREADER_CONFIG_TRIM_PAGE,
|
||||||
event = "PageCrop",
|
event = "PageCrop",
|
||||||
args = {"manual", "auto", "semi-auto"},
|
args = {"manual", "auto", "semi-auto"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.column.two.large.png",
|
icon = "resources/icons/appbar.column.two.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "page_scroll",
|
name = "page_scroll",
|
||||||
name_text = S.SCROLL_MODE,
|
name_text = S.SCROLL_MODE,
|
||||||
toggle = {S.ON, S.OFF},
|
toggle = {S.ON, S.OFF},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = DSCROLL_MODE,
|
default_value = DSCROLL_MODE,
|
||||||
event = "ToggleScrollMode",
|
event = "ToggleScrollMode",
|
||||||
args = {true, false},
|
args = {true, false},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "full_screen",
|
name = "full_screen",
|
||||||
name_text = S.PROGRESS_BAR,
|
name_text = S.PROGRESS_BAR,
|
||||||
toggle = {S.OFF, S.ON},
|
toggle = {S.OFF, S.ON},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = DFULL_SCREEN,
|
default_value = DFULL_SCREEN,
|
||||||
event = "SetFullScreen",
|
event = "SetFullScreen",
|
||||||
args = {true, false},
|
args = {true, false},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "page_margin",
|
name = "page_margin",
|
||||||
name_text = S.PAGE_MARGIN,
|
name_text = S.PAGE_MARGIN,
|
||||||
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
||||||
values = {0.05, 0.10, 0.15},
|
values = {0.05, 0.10, 0.15},
|
||||||
default_value = DKOPTREADER_CONFIG_PAGE_MARGIN,
|
default_value = DKOPTREADER_CONFIG_PAGE_MARGIN,
|
||||||
event = "MarginUpdate",
|
event = "MarginUpdate",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "line_spacing",
|
name = "line_spacing",
|
||||||
name_text = S.LINE_SPACING,
|
name_text = S.LINE_SPACING,
|
||||||
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
||||||
values = {1.0, 1.2, 1.4},
|
values = {1.0, 1.2, 1.4},
|
||||||
default_value = DKOPTREADER_CONFIG_LINE_SPACING,
|
default_value = DKOPTREADER_CONFIG_LINE_SPACING,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.text.size.large.png",
|
icon = "resources/icons/appbar.text.size.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "font_size",
|
name = "font_size",
|
||||||
item_text = {"Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa"},
|
item_text = {"Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa"},
|
||||||
item_align_center = 1.0,
|
item_align_center = 1.0,
|
||||||
spacing = 15,
|
spacing = 15,
|
||||||
height = 60,
|
height = 60,
|
||||||
item_font_size = {22,24,28,32,34,36,38,42,46,50},
|
item_font_size = {22,24,28,32,34,36,38,42,46,50},
|
||||||
values = {0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0, 4.0},
|
values = {0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0, 4.0},
|
||||||
default_value = DKOPTREADER_CONFIG_FONT_SIZE,
|
default_value = DKOPTREADER_CONFIG_FONT_SIZE,
|
||||||
event = "FontSizeUpdate",
|
event = "FontSizeUpdate",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "font_fine_tune",
|
name = "font_fine_tune",
|
||||||
name_text = S.FONTSIZE_FINE_TUNING,
|
name_text = S.FONTSIZE_FINE_TUNING,
|
||||||
toggle = {S.DECREASE, S.INCREASE},
|
toggle = {S.DECREASE, S.INCREASE},
|
||||||
values = {-0.05, 0.05},
|
values = {-0.05, 0.05},
|
||||||
default_value = 0.05,
|
default_value = 0.05,
|
||||||
event = "FineTuningFontSize",
|
event = "FineTuningFontSize",
|
||||||
args = {-0.05, 0.05},
|
args = {-0.05, 0.05},
|
||||||
alternate = false,
|
alternate = false,
|
||||||
height = 60,
|
height = 60,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.grade.b.large.png",
|
icon = "resources/icons/appbar.grade.b.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "contrast",
|
name = "contrast",
|
||||||
name_text = S.CONTRAST,
|
name_text = S.CONTRAST,
|
||||||
name_align_right = 0.2,
|
name_align_right = 0.2,
|
||||||
item_text = {S.LIGHTEST , S.LIGHTER, S.DEFAULT, S.DARKER, S.DARKEST},
|
item_text = {S.LIGHTEST , S.LIGHTER, S.DEFAULT, S.DARKER, S.DARKEST},
|
||||||
item_font_size = 18,
|
item_font_size = 18,
|
||||||
item_align_center = 0.8,
|
item_align_center = 0.8,
|
||||||
values = {2.0, 1.5, 1.0, 0.5, 0.2},
|
values = {2.0, 1.5, 1.0, 0.5, 0.2},
|
||||||
default_value = DKOPTREADER_CONFIG_CONTRAST,
|
default_value = DKOPTREADER_CONFIG_CONTRAST,
|
||||||
event = "GammaUpdate",
|
event = "GammaUpdate",
|
||||||
args = {0.5, 0.8, 1.0, 2.0, 4.0},
|
args = {0.5, 0.8, 1.0, 2.0, 4.0},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon = "resources/icons/appbar.settings.large.png",
|
icon = "resources/icons/appbar.settings.large.png",
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
name = "text_wrap",
|
name = "text_wrap",
|
||||||
name_text = _("Reflow"),
|
name_text = _("Reflow"),
|
||||||
toggle = {S.ON, S.OFF},
|
toggle = {S.ON, S.OFF},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = DKOPTREADER_CONFIG_TEXT_WRAP,
|
default_value = DKOPTREADER_CONFIG_TEXT_WRAP,
|
||||||
events = {
|
events = {
|
||||||
{
|
{
|
||||||
event = "RedrawCurrentPage",
|
event = "RedrawCurrentPage",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
event = "RestoreZoomMode",
|
event = "RestoreZoomMode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
event = "InitScrollPageStates",
|
event = "InitScrollPageStates",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name="doc_language",
|
name="doc_language",
|
||||||
name_text = S.DOC_LANG,
|
name_text = S.DOC_LANG,
|
||||||
toggle = DKOPTREADER_CONFIG_DOC_LANGS_TEXT,
|
toggle = DKOPTREADER_CONFIG_DOC_LANGS_TEXT,
|
||||||
values = DKOPTREADER_CONFIG_DOC_LANGS_CODE,
|
values = DKOPTREADER_CONFIG_DOC_LANGS_CODE,
|
||||||
default_value = DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE,
|
default_value = DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE,
|
||||||
event = "DocLangUpdate",
|
event = "DocLangUpdate",
|
||||||
args = DKOPTREADER_CONFIG_DOC_LANGS_CODE,
|
args = DKOPTREADER_CONFIG_DOC_LANGS_CODE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "word_spacing",
|
name = "word_spacing",
|
||||||
name_text = S.WORD_GAP,
|
name_text = S.WORD_GAP,
|
||||||
toggle = {S.SMALL, S.AUTO, S.LARGE},
|
toggle = {S.SMALL, S.AUTO, S.LARGE},
|
||||||
values = DKOPTREADER_CONFIG_WORD_SAPCINGS,
|
values = DKOPTREADER_CONFIG_WORD_SAPCINGS,
|
||||||
default_value = DKOPTREADER_CONFIG_DEFAULT_WORD_SAPCING,
|
default_value = DKOPTREADER_CONFIG_DEFAULT_WORD_SAPCING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "writing_direction",
|
name = "writing_direction",
|
||||||
name_text = S.WRITING_DIR,
|
name_text = S.WRITING_DIR,
|
||||||
toggle = {S.LTR, S.RTL, S.TBRTL},
|
toggle = {S.LTR, S.RTL, S.TBRTL},
|
||||||
values = {0, 1, 2},
|
values = {0, 1, 2},
|
||||||
default_value = 0,
|
default_value = 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "quality",
|
name = "quality",
|
||||||
name_text = S.RENDER_QUALITY,
|
name_text = S.RENDER_QUALITY,
|
||||||
toggle = {S.LOW, S.DEFAULT, S.HIGH},
|
toggle = {S.LOW, S.DEFAULT, S.HIGH},
|
||||||
values={0.5, 1.0, 1.5},
|
values={0.5, 1.0, 1.5},
|
||||||
default_value = DKOPTREADER_CONFIG_RENDER_QUALITY,
|
default_value = DKOPTREADER_CONFIG_RENDER_QUALITY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "max_columns",
|
name = "max_columns",
|
||||||
name_text = S.COLUMNS,
|
name_text = S.COLUMNS,
|
||||||
item_icons = {
|
item_icons = {
|
||||||
"resources/icons/appbar.column.one.png",
|
"resources/icons/appbar.column.one.png",
|
||||||
"resources/icons/appbar.column.two.png",
|
"resources/icons/appbar.column.two.png",
|
||||||
"resources/icons/appbar.column.three.png",
|
"resources/icons/appbar.column.three.png",
|
||||||
},
|
},
|
||||||
values = {1,2,3},
|
values = {1,2,3},
|
||||||
default_value = DKOPTREADER_CONFIG_MAX_COLUMNS,
|
default_value = DKOPTREADER_CONFIG_MAX_COLUMNS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "justification",
|
name = "justification",
|
||||||
name_text = S.TEXT_ALIGN,
|
name_text = S.TEXT_ALIGN,
|
||||||
item_icons = {
|
item_icons = {
|
||||||
"resources/icons/appbar.align.auto.png",
|
"resources/icons/appbar.align.auto.png",
|
||||||
"resources/icons/appbar.align.left.png",
|
"resources/icons/appbar.align.left.png",
|
||||||
"resources/icons/appbar.align.center.png",
|
"resources/icons/appbar.align.center.png",
|
||||||
"resources/icons/appbar.align.right.png",
|
"resources/icons/appbar.align.right.png",
|
||||||
"resources/icons/appbar.align.justify.png",
|
"resources/icons/appbar.align.justify.png",
|
||||||
},
|
},
|
||||||
values = {-1,0,1,2,3},
|
values = {-1,0,1,2,3},
|
||||||
default_value = DKOPTREADER_CONFIG_JUSTIFICATION,
|
default_value = DKOPTREADER_CONFIG_JUSTIFICATION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "defect_size",
|
name = "defect_size",
|
||||||
name_text = S.DEFECT_SIZE,
|
name_text = S.DEFECT_SIZE,
|
||||||
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
toggle = {S.SMALL, S.MEDIUM, S.LARGE},
|
||||||
values = {1.0, 3.0, 5.0},
|
values = {1.0, 3.0, 5.0},
|
||||||
default_value = DKOPTREADER_CONFIG_DEFECT_SIZE,
|
default_value = DKOPTREADER_CONFIG_DEFECT_SIZE,
|
||||||
event = "DefectSizeUpdate",
|
event = "DefectSizeUpdate",
|
||||||
show = false,
|
show = false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "auto_straighten",
|
name = "auto_straighten",
|
||||||
name_text = S.AUTO_STRAIGHTEN,
|
name_text = S.AUTO_STRAIGHTEN,
|
||||||
toggle = {S.ZERO_DEG, S.FIVE_DEG, S.TEN_DEG},
|
toggle = {S.ZERO_DEG, S.FIVE_DEG, S.TEN_DEG},
|
||||||
values = {0, 5, 10},
|
values = {0, 5, 10},
|
||||||
default_value = DKOPTREADER_CONFIG_AUTO_STRAIGHTEN,
|
default_value = DKOPTREADER_CONFIG_AUTO_STRAIGHTEN,
|
||||||
show = false,
|
show = false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "detect_indent",
|
name = "detect_indent",
|
||||||
name_text = S.INDENTATION,
|
name_text = S.INDENTATION,
|
||||||
toggle = {S.ON, S.OFF},
|
toggle = {S.ON, S.OFF},
|
||||||
values = {1, 0},
|
values = {1, 0},
|
||||||
default_value = DKOPTREADER_CONFIG_DETECT_INDENT,
|
default_value = DKOPTREADER_CONFIG_DETECT_INDENT,
|
||||||
show = false,
|
show = false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return KoptOptions
|
return KoptOptions
|
||||||
|
|||||||
@@ -6,229 +6,229 @@ local Screen = require("ui/device/screen")
|
|||||||
-- lfs
|
-- lfs
|
||||||
|
|
||||||
local Device = {
|
local Device = {
|
||||||
screen_saver_mode = false,
|
screen_saver_mode = false,
|
||||||
charging_mode = false,
|
charging_mode = false,
|
||||||
survive_screen_saver = false,
|
survive_screen_saver = false,
|
||||||
touch_dev = nil,
|
touch_dev = nil,
|
||||||
model = nil,
|
model = nil,
|
||||||
firmware_rev = nil,
|
firmware_rev = nil,
|
||||||
powerd = nil,
|
powerd = nil,
|
||||||
has_no_keyboard = nil,
|
has_no_keyboard = nil,
|
||||||
is_touch_device = nil,
|
is_touch_device = nil,
|
||||||
has_front_light = nil,
|
has_front_light = nil,
|
||||||
screen = Screen
|
screen = Screen
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen.device = Device
|
Screen.device = Device
|
||||||
|
|
||||||
function Set (list)
|
function Set (list)
|
||||||
local set = {}
|
local set = {}
|
||||||
for _, l in ipairs(list) do set[l] = true end
|
for _, l in ipairs(list) do set[l] = true end
|
||||||
return set
|
return set
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:getModel()
|
function Device:getModel()
|
||||||
if self.model then return self.model end
|
if self.model then return self.model end
|
||||||
if util.isEmulated() then
|
if util.isEmulated() then
|
||||||
self.model = "Emulator"
|
self.model = "Emulator"
|
||||||
return self.model
|
return self.model
|
||||||
end
|
end
|
||||||
self.model = nil
|
self.model = nil
|
||||||
local kindle_sn = io.open("/proc/usid", "r")
|
local kindle_sn = io.open("/proc/usid", "r")
|
||||||
if kindle_sn then
|
if kindle_sn then
|
||||||
local kindle_devcode = string.sub(kindle_sn:read(),3,4)
|
local kindle_devcode = string.sub(kindle_sn:read(),3,4)
|
||||||
kindle_sn:close()
|
kindle_sn:close()
|
||||||
-- NOTE: Update me when new models come out :)
|
-- NOTE: Update me when new models come out :)
|
||||||
local k2_set = Set { "02", "03" }
|
local k2_set = Set { "02", "03" }
|
||||||
local dx_set = Set { "04", "05" }
|
local dx_set = Set { "04", "05" }
|
||||||
local dxg_set = Set { "09" }
|
local dxg_set = Set { "09" }
|
||||||
local k3_set = Set { "08", "06", "0A" }
|
local k3_set = Set { "08", "06", "0A" }
|
||||||
local k4_set = Set { "0E", "23" }
|
local k4_set = Set { "0E", "23" }
|
||||||
local touch_set = Set { "0F", "11", "10", "12" }
|
local touch_set = Set { "0F", "11", "10", "12" }
|
||||||
local pw_set = Set { "24", "1B", "1D", "1F", "1C", "20" }
|
local pw_set = Set { "24", "1B", "1D", "1F", "1C", "20" }
|
||||||
local pw2_set = Set { "D4", "5A", "D5", "D7", "D8", "F2" }
|
local pw2_set = Set { "D4", "5A", "D5", "D7", "D8", "F2" }
|
||||||
|
|
||||||
if k2_set[kindle_devcode] then
|
if k2_set[kindle_devcode] then
|
||||||
self.model = "Kindle2"
|
self.model = "Kindle2"
|
||||||
elseif dx_set[kindle_devcode] then
|
elseif dx_set[kindle_devcode] then
|
||||||
self.model = "Kindle2"
|
self.model = "Kindle2"
|
||||||
elseif dxg_set[kindle_devcode] then
|
elseif dxg_set[kindle_devcode] then
|
||||||
self.model = "Kindle2"
|
self.model = "Kindle2"
|
||||||
elseif k3_set[kindle_devcode] then
|
elseif k3_set[kindle_devcode] then
|
||||||
self.model = "Kindle3"
|
self.model = "Kindle3"
|
||||||
elseif k4_set[kindle_devcode] then
|
elseif k4_set[kindle_devcode] then
|
||||||
self.model = "Kindle4"
|
self.model = "Kindle4"
|
||||||
elseif touch_set[kindle_devcode] then
|
elseif touch_set[kindle_devcode] then
|
||||||
self.model = "KindleTouch"
|
self.model = "KindleTouch"
|
||||||
elseif pw_set[kindle_devcode] then
|
elseif pw_set[kindle_devcode] then
|
||||||
self.model = "KindlePaperWhite"
|
self.model = "KindlePaperWhite"
|
||||||
elseif pw2_set[kindle_devcode] then
|
elseif pw2_set[kindle_devcode] then
|
||||||
self.model = "KindlePaperWhite2"
|
self.model = "KindlePaperWhite2"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local kg_test_fd = lfs.attributes("/bin/kobo_config.sh")
|
local kg_test_fd = lfs.attributes("/bin/kobo_config.sh")
|
||||||
if kg_test_fd then
|
if kg_test_fd then
|
||||||
local std_out = io.popen("/bin/kobo_config.sh", "r")
|
local std_out = io.popen("/bin/kobo_config.sh", "r")
|
||||||
local codename = std_out:read()
|
local codename = std_out:read()
|
||||||
self.model = "Kobo_" .. codename
|
self.model = "Kobo_" .. codename
|
||||||
local version_file = io.open("/mnt/onboard/.kobo/version", "r")
|
local version_file = io.open("/mnt/onboard/.kobo/version", "r")
|
||||||
self.firmware_rev = string.sub(version_file:read(),24,28)
|
self.firmware_rev = string.sub(version_file:read(),24,28)
|
||||||
version_file:close()
|
version_file:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self.model
|
return self.model
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:getFirmVer()
|
function Device:getFirmVer()
|
||||||
if not self.model then self:getModel() end
|
if not self.model then self:getModel() end
|
||||||
return self.firmware_rev
|
return self.firmware_rev
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:isKindle4()
|
function Device:isKindle4()
|
||||||
return (self:getModel() == "Kindle4")
|
return (self:getModel() == "Kindle4")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:isKindle3()
|
function Device:isKindle3()
|
||||||
return (self:getModel() == "Kindle3")
|
return (self:getModel() == "Kindle3")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:isKindle2()
|
function Device:isKindle2()
|
||||||
return (self:getModel() == "Kindle2")
|
return (self:getModel() == "Kindle2")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:isKobo()
|
function Device:isKobo()
|
||||||
return string.find(self:getModel(),"Kobo_") == 1
|
return string.find(self:getModel(),"Kobo_") == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:hasNoKeyboard()
|
function Device:hasNoKeyboard()
|
||||||
if self.has_no_keyboard ~= nil then return self.has_no_keyboard end
|
if self.has_no_keyboard ~= nil then return self.has_no_keyboard end
|
||||||
local model = self:getModel()
|
local model = self:getModel()
|
||||||
self.has_no_keyboard = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
self.has_no_keyboard = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
||||||
or (model == "KindleTouch") or self:isKobo()
|
or (model == "KindleTouch") or self:isKobo()
|
||||||
return self.has_no_keyboard
|
return self.has_no_keyboard
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:hasKeyboard()
|
function Device:hasKeyboard()
|
||||||
return not self:hasNoKeyboard()
|
return not self:hasNoKeyboard()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:isTouchDevice()
|
function Device:isTouchDevice()
|
||||||
if self.is_touch_device ~= nil then return self.is_touch_device end
|
if self.is_touch_device ~= nil then return self.is_touch_device end
|
||||||
local model = self:getModel()
|
local model = self:getModel()
|
||||||
self.is_touch_device = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
self.is_touch_device = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
||||||
or (model == "KindleTouch") or self:isKobo() or util.isEmulated()
|
or (model == "KindleTouch") or self:isKobo() or util.isEmulated()
|
||||||
return self.is_touch_device
|
return self.is_touch_device
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:hasFrontlight()
|
function Device:hasFrontlight()
|
||||||
if self.has_front_light ~= nil then return self.has_front_light end
|
if self.has_front_light ~= nil then return self.has_front_light end
|
||||||
local model = self:getModel()
|
local model = self:getModel()
|
||||||
self.has_front_light = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
self.has_front_light = (model == "KindlePaperWhite") or (model == "KindlePaperWhite2")
|
||||||
or (model == "Kobo_dragon") or (model == "Kobo_kraken") or (model == "Kobo_phoenix")
|
or (model == "Kobo_dragon") or (model == "Kobo_kraken") or (model == "Kobo_phoenix")
|
||||||
or util.isEmulated()
|
or util.isEmulated()
|
||||||
return self.has_front_light
|
return self.has_front_light
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:setTouchInputDev(dev)
|
function Device:setTouchInputDev(dev)
|
||||||
self.touch_dev = dev
|
self.touch_dev = dev
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:getTouchInputDev()
|
function Device:getTouchInputDev()
|
||||||
return self.touch_dev
|
return self.touch_dev
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:intoScreenSaver()
|
function Device:intoScreenSaver()
|
||||||
--os.execute("echo 'screensaver in' >> /mnt/us/event_test.txt")
|
--os.execute("echo 'screensaver in' >> /mnt/us/event_test.txt")
|
||||||
if self.charging_mode == false and self.screen_saver_mode == false then
|
if self.charging_mode == false and self.screen_saver_mode == false then
|
||||||
self.screen:saveCurrentBB()
|
self.screen:saveCurrentBB()
|
||||||
--UIManager:show(InfoMessage:new{
|
--UIManager:show(InfoMessage:new{
|
||||||
--text = "Going into screensaver... ",
|
--text = "Going into screensaver... ",
|
||||||
--timeout = 2,
|
--timeout = 2,
|
||||||
--})
|
--})
|
||||||
--util.sleep(1)
|
--util.sleep(1)
|
||||||
--os.execute("killall -cont cvm")
|
--os.execute("killall -cont cvm")
|
||||||
self.screen_saver_mode = true
|
self.screen_saver_mode = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:outofScreenSaver()
|
function Device:outofScreenSaver()
|
||||||
--os.execute("echo 'screensaver out' >> /mnt/us/event_test.txt")
|
--os.execute("echo 'screensaver out' >> /mnt/us/event_test.txt")
|
||||||
if self.screen_saver_mode == true and self.charging_mode == false then
|
if self.screen_saver_mode == true and self.charging_mode == false then
|
||||||
-- wait for native system update screen before we recover saved
|
-- wait for native system update screen before we recover saved
|
||||||
-- Blitbuffer.
|
-- Blitbuffer.
|
||||||
util.usleep(1500000)
|
util.usleep(1500000)
|
||||||
--os.execute("killall -stop cvm")
|
--os.execute("killall -stop cvm")
|
||||||
self.screen:restoreFromSavedBB()
|
self.screen:restoreFromSavedBB()
|
||||||
self.screen:refresh(0)
|
self.screen:refresh(0)
|
||||||
self.survive_screen_saver = true
|
self.survive_screen_saver = true
|
||||||
end
|
end
|
||||||
self.screen_saver_mode = false
|
self.screen_saver_mode = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:prepareSuspend() -- currently only used for kobo devices
|
function Device:prepareSuspend() -- currently only used for kobo devices
|
||||||
local powerd = self:getPowerDevice()
|
local powerd = self:getPowerDevice()
|
||||||
if powerd ~= nil then
|
if powerd ~= nil then
|
||||||
powerd.fl:sleep()
|
powerd.fl:sleep()
|
||||||
end
|
end
|
||||||
self.screen:refresh(0)
|
self.screen:refresh(0)
|
||||||
self.screen_saver_mode = true
|
self.screen_saver_mode = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:Suspend() -- currently only used for kobo devices
|
function Device:Suspend() -- currently only used for kobo devices
|
||||||
os.execute("./kobo_suspend.sh")
|
os.execute("./kobo_suspend.sh")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:Resume() -- currently only used for kobo devices
|
function Device:Resume() -- currently only used for kobo devices
|
||||||
os.execute("echo 0 > /sys/power/state-extended")
|
os.execute("echo 0 > /sys/power/state-extended")
|
||||||
self.screen:refresh(0)
|
self.screen:refresh(0)
|
||||||
local powerd = self:getPowerDevice()
|
local powerd = self:getPowerDevice()
|
||||||
if powerd ~= nil then
|
if powerd ~= nil then
|
||||||
powerd.fl:restore()
|
powerd.fl:restore()
|
||||||
end
|
end
|
||||||
self.screen_saver_mode = false
|
self.screen_saver_mode = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:usbPlugIn()
|
function Device:usbPlugIn()
|
||||||
--os.execute("echo 'usb in' >> /mnt/us/event_test.txt")
|
--os.execute("echo 'usb in' >> /mnt/us/event_test.txt")
|
||||||
if self.charging_mode == false and self.screen_saver_mode == false then
|
if self.charging_mode == false and self.screen_saver_mode == false then
|
||||||
self.screen:saveCurrentBB()
|
self.screen:saveCurrentBB()
|
||||||
--UIManager:show(InfoMessage:new{
|
--UIManager:show(InfoMessage:new{
|
||||||
--text = "Going into USB mode... ",
|
--text = "Going into USB mode... ",
|
||||||
--timeout = 2,
|
--timeout = 2,
|
||||||
--})
|
--})
|
||||||
--util.sleep(1)
|
--util.sleep(1)
|
||||||
--os.execute("killall -cont cvm")
|
--os.execute("killall -cont cvm")
|
||||||
end
|
end
|
||||||
self.charging_mode = true
|
self.charging_mode = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:usbPlugOut()
|
function Device:usbPlugOut()
|
||||||
--os.execute("echo 'usb out' >> /mnt/us/event_test.txt")
|
--os.execute("echo 'usb out' >> /mnt/us/event_test.txt")
|
||||||
if self.charging_mode == true and self.screen_saver_mode == false then
|
if self.charging_mode == true and self.screen_saver_mode == false then
|
||||||
--util.usleep(1500000)
|
--util.usleep(1500000)
|
||||||
--os.execute("killall -stop cvm")
|
--os.execute("killall -stop cvm")
|
||||||
self.screen:restoreFromSavedBB()
|
self.screen:restoreFromSavedBB()
|
||||||
self.screen:refresh(0)
|
self.screen:refresh(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
--@TODO signal filemanager for file changes 13.06 2012 (houqp)
|
--@TODO signal filemanager for file changes 13.06 2012 (houqp)
|
||||||
self.charging_mode = false
|
self.charging_mode = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function Device:getPowerDevice()
|
function Device:getPowerDevice()
|
||||||
if self.powerd ~= nil then
|
if self.powerd ~= nil then
|
||||||
return self.powerd
|
return self.powerd
|
||||||
else
|
else
|
||||||
local model = self:getModel()
|
local model = self:getModel()
|
||||||
if model == "KindleTouch" or model == "KindlePaperWhite" or model == "KindlePaperWhite2" then
|
if model == "KindleTouch" or model == "KindlePaperWhite" or model == "KindlePaperWhite2" then
|
||||||
self.powerd = KindlePowerD:new{model = model}
|
self.powerd = KindlePowerD:new{model = model}
|
||||||
elseif self:isKobo() then
|
elseif self:isKobo() then
|
||||||
self.powerd = KoboPowerD:new()
|
self.powerd = KoboPowerD:new()
|
||||||
else -- emulated FrontLight
|
else -- emulated FrontLight
|
||||||
self.powerd = BasePowerD:new()
|
self.powerd = BasePowerD:new()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self.powerd
|
return self.powerd
|
||||||
end
|
end
|
||||||
|
|
||||||
return Device
|
return Device
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
local BasePowerD = {
|
local BasePowerD = {
|
||||||
fl_min = 0, -- min frontlight intensity
|
fl_min = 0, -- min frontlight intensity
|
||||||
fl_max = 10, -- max frontlight intensity
|
fl_max = 10, -- max frontlight intensity
|
||||||
flIntensity = nil, -- frontlight intensity
|
flIntensity = nil, -- frontlight intensity
|
||||||
battCapacity = nil, -- battery capacity
|
battCapacity = nil, -- battery capacity
|
||||||
model = nil, -- device model
|
model = nil, -- device model
|
||||||
|
|
||||||
capacity_pulled_count = 0,
|
capacity_pulled_count = 0,
|
||||||
capacity_cached_count = 10,
|
capacity_cached_count = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
function BasePowerD:new(o)
|
function BasePowerD:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
if o.init then o:init() end
|
if o.init then o:init() end
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:init() end
|
function BasePowerD:init() end
|
||||||
@@ -26,39 +26,39 @@ function BasePowerD:suspendHW() end
|
|||||||
function BasePowerD:wakeUpHW() end
|
function BasePowerD:wakeUpHW() end
|
||||||
|
|
||||||
function BasePowerD:read_int_file(file)
|
function BasePowerD:read_int_file(file)
|
||||||
local f = io.open(file, "r")
|
local f = io.open(file, "r")
|
||||||
local sysint = tonumber(f:read("*all"):match("%d+"))
|
local sysint = tonumber(f:read("*all"):match("%d+"))
|
||||||
f:close()
|
f:close()
|
||||||
return sysint
|
return sysint
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:setIntensity(intensity)
|
function BasePowerD:setIntensity(intensity)
|
||||||
intensity = intensity < self.fl_min and self.fl_min or intensity
|
intensity = intensity < self.fl_min and self.fl_min or intensity
|
||||||
intensity = intensity > self.fl_max and self.fl_max or intensity
|
intensity = intensity > self.fl_max and self.fl_max or intensity
|
||||||
self.flIntensity = intensity
|
self.flIntensity = intensity
|
||||||
self:setIntensityHW()
|
self:setIntensityHW()
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:getCapacity()
|
function BasePowerD:getCapacity()
|
||||||
if capacity_pulled_count == capacity_cached_count then
|
if capacity_pulled_count == capacity_cached_count then
|
||||||
capacity_pulled_count = 0
|
capacity_pulled_count = 0
|
||||||
return self:getCapacityHW()
|
return self:getCapacityHW()
|
||||||
else
|
else
|
||||||
capacity_pulled_count = capacity_pulled_count + 1
|
capacity_pulled_count = capacity_pulled_count + 1
|
||||||
return self.battCapacity or self:getCapacityHW()
|
return self.battCapacity or self:getCapacityHW()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:isCharging()
|
function BasePowerD:isCharging()
|
||||||
return self:isChargingHW()
|
return self:isChargingHW()
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:suspend()
|
function BasePowerD:suspend()
|
||||||
return self:suspendHW()
|
return self:suspendHW()
|
||||||
end
|
end
|
||||||
|
|
||||||
function BasePowerD:wakeUp()
|
function BasePowerD:wakeUp()
|
||||||
return self:wakeUpHW()
|
return self:wakeUpHW()
|
||||||
end
|
end
|
||||||
|
|
||||||
return BasePowerD
|
return BasePowerD
|
||||||
|
|||||||
@@ -2,85 +2,85 @@ local BasePowerD = require("ui/device/basepowerd")
|
|||||||
-- liblipclua, see require below
|
-- liblipclua, see require below
|
||||||
|
|
||||||
local KindlePowerD = BasePowerD:new{
|
local KindlePowerD = BasePowerD:new{
|
||||||
fl_min = 0, fl_max = 24,
|
fl_min = 0, fl_max = 24,
|
||||||
kpw1_frontlight = "/sys/devices/system/fl_tps6116x/fl_tps6116x0/fl_intensity",
|
kpw1_frontlight = "/sys/devices/system/fl_tps6116x/fl_tps6116x0/fl_intensity",
|
||||||
kpw2_frontlight = "/sys/class/backlight/max77696-bl/brightness",
|
kpw2_frontlight = "/sys/class/backlight/max77696-bl/brightness",
|
||||||
kt_kpw_capacity = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity",
|
kt_kpw_capacity = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity",
|
||||||
kpw_charging = "/sys/devices/platform/aplite_charger.0/charging",
|
kpw_charging = "/sys/devices/platform/aplite_charger.0/charging",
|
||||||
kt_charging = "/sys/devices/platform/fsl-usb2-udc/charging",
|
kt_charging = "/sys/devices/platform/fsl-usb2-udc/charging",
|
||||||
|
|
||||||
flIntensity = nil,
|
flIntensity = nil,
|
||||||
battCapacity = nil,
|
battCapacity = nil,
|
||||||
is_charging = nil,
|
is_charging = nil,
|
||||||
lipc_handle = nil,
|
lipc_handle = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function KindlePowerD:new(o)
|
function KindlePowerD:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
if o.init then o:init(o.model) end
|
if o.init then o:init(o.model) end
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function KindlePowerD:init(model)
|
function KindlePowerD:init(model)
|
||||||
local lipc = require("liblipclua")
|
local lipc = require("liblipclua")
|
||||||
if lipc then
|
if lipc then
|
||||||
self.lipc_handle = lipc.init("com.github.koreader")
|
self.lipc_handle = lipc.init("com.github.koreader")
|
||||||
end
|
end
|
||||||
|
|
||||||
if model == "KindleTouch" then
|
if model == "KindleTouch" then
|
||||||
self.batt_capacity_file = self.kt_kpw_capacity
|
self.batt_capacity_file = self.kt_kpw_capacity
|
||||||
self.is_charging_file = self.kt_charging
|
self.is_charging_file = self.kt_charging
|
||||||
elseif model == "KindlePaperWhite" then
|
elseif model == "KindlePaperWhite" then
|
||||||
self.fl_intensity_file = self.kpw1_frontlight
|
self.fl_intensity_file = self.kpw1_frontlight
|
||||||
self.batt_capacity_file = self.kt_kpw_capacity
|
self.batt_capacity_file = self.kt_kpw_capacity
|
||||||
self.is_charging_file = self.kpw_charging
|
self.is_charging_file = self.kpw_charging
|
||||||
elseif model == "KindlePaperWhite2" then
|
elseif model == "KindlePaperWhite2" then
|
||||||
self.fl_intensity_file = self.kpw2_frontlight
|
self.fl_intensity_file = self.kpw2_frontlight
|
||||||
self.batt_capacity_file = self.kt_kpw_capacity
|
self.batt_capacity_file = self.kt_kpw_capacity
|
||||||
self.is_charging_file = self.kpw_charging
|
self.is_charging_file = self.kpw_charging
|
||||||
end
|
end
|
||||||
if self.lipc_handle then
|
if self.lipc_handle then
|
||||||
self.flIntensity = self.lipc_handle:get_int_property("com.lab126.powerd", "flIntensity")
|
self.flIntensity = self.lipc_handle:get_int_property("com.lab126.powerd", "flIntensity")
|
||||||
else
|
else
|
||||||
self.flIntensity = self:read_int_file(self.fl_intensity_file)
|
self.flIntensity = self:read_int_file(self.fl_intensity_file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function KindlePowerD:toggleFrontlight()
|
function KindlePowerD:toggleFrontlight()
|
||||||
local sysint = self:read_int_file(self.fl_intensity_file)
|
local sysint = self:read_int_file(self.fl_intensity_file)
|
||||||
if sysint == 0 then
|
if sysint == 0 then
|
||||||
self:setIntensity(self.flIntensity)
|
self:setIntensity(self.flIntensity)
|
||||||
else
|
else
|
||||||
os.execute("echo -n 0 > " .. self.fl_intensity_file)
|
os.execute("echo -n 0 > " .. self.fl_intensity_file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function KindlePowerD:setIntensityHW()
|
function KindlePowerD:setIntensityHW()
|
||||||
if self.lipc_handle ~= nil then
|
if self.lipc_handle ~= nil then
|
||||||
self.lipc_handle:set_int_property("com.lab126.powerd", "flIntensity", self.flIntensity)
|
self.lipc_handle:set_int_property("com.lab126.powerd", "flIntensity", self.flIntensity)
|
||||||
else
|
else
|
||||||
os.execute("echo -n ".. self.flIntensity .." > " .. self.fl_intensity_file)
|
os.execute("echo -n ".. self.flIntensity .." > " .. self.fl_intensity_file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function KindlePowerD:getCapacityHW()
|
function KindlePowerD:getCapacityHW()
|
||||||
if self.lipc_handle ~= nil then
|
if self.lipc_handle ~= nil then
|
||||||
self.battCapacity = self.lipc_handle:get_int_property("com.lab126.powerd", "battLevel")
|
self.battCapacity = self.lipc_handle:get_int_property("com.lab126.powerd", "battLevel")
|
||||||
else
|
else
|
||||||
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
||||||
end
|
end
|
||||||
return self.battCapacity
|
return self.battCapacity
|
||||||
end
|
end
|
||||||
|
|
||||||
function KindlePowerD:isChargingHW()
|
function KindlePowerD:isChargingHW()
|
||||||
if self.lipc_handle ~= nil then
|
if self.lipc_handle ~= nil then
|
||||||
self.is_charging = self.lipc_handle:get_int_property("com.lab126.powerd", "isCharging")
|
self.is_charging = self.lipc_handle:get_int_property("com.lab126.powerd", "isCharging")
|
||||||
else
|
else
|
||||||
self.is_charging = self:read_int_file(self.is_charging_file)
|
self.is_charging = self:read_int_file(self.is_charging_file)
|
||||||
end
|
end
|
||||||
return self.is_charging == 1
|
return self.is_charging == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
return KindlePowerD
|
return KindlePowerD
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
local BasePowerD = require("ui/device/basepowerd")
|
local BasePowerD = require("ui/device/basepowerd")
|
||||||
|
|
||||||
local KoboPowerD = BasePowerD:new{
|
local KoboPowerD = BasePowerD:new{
|
||||||
fl_min = 1, fl_max = 100,
|
fl_min = 1, fl_max = 100,
|
||||||
flIntensity = 20,
|
flIntensity = 20,
|
||||||
restore_settings = true,
|
restore_settings = true,
|
||||||
fl = nil,
|
fl = nil,
|
||||||
|
|
||||||
batt_capacity_file = "/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/capacity",
|
batt_capacity_file = "/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/capacity",
|
||||||
is_charging_file = "/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/charge_now",
|
is_charging_file = "/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/charge_now",
|
||||||
battCapacity = nil,
|
battCapacity = nil,
|
||||||
is_charging = nil,
|
is_charging = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function KoboPowerD:init()
|
function KoboPowerD:init()
|
||||||
self.fl = kobolight.open()
|
self.fl = kobolight.open()
|
||||||
end
|
end
|
||||||
|
|
||||||
function KoboPowerD:toggleFrontlight()
|
function KoboPowerD:toggleFrontlight()
|
||||||
if self.fl ~= nil then
|
if self.fl ~= nil then
|
||||||
self.fl:toggle()
|
self.fl:toggle()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function KoboPowerD:setIntensityHW()
|
function KoboPowerD:setIntensityHW()
|
||||||
if self.fl ~= nil then
|
if self.fl ~= nil then
|
||||||
self.fl:setBrightness(self.flIntensity)
|
self.fl:setBrightness(self.flIntensity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function KoboPowerD:getCapacityHW()
|
function KoboPowerD:getCapacityHW()
|
||||||
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
||||||
return self.battCapacity
|
return self.battCapacity
|
||||||
end
|
end
|
||||||
|
|
||||||
function KoboPowerD:isChargingHW()
|
function KoboPowerD:isChargingHW()
|
||||||
self.is_charging = self:read_int_file(self.is_charging_file)
|
self.is_charging = self:read_int_file(self.is_charging_file)
|
||||||
return self.is_charging == 1
|
return self.is_charging == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
return KoboPowerD
|
return KoboPowerD
|
||||||
|
|||||||
@@ -29,131 +29,131 @@ Codes for rotation modes:
|
|||||||
|
|
||||||
|
|
||||||
local Screen = {
|
local Screen = {
|
||||||
cur_rotation_mode = 0,
|
cur_rotation_mode = 0,
|
||||||
native_rotation_mode = nil,
|
native_rotation_mode = nil,
|
||||||
blitbuffer_rotation_mode = 0,
|
blitbuffer_rotation_mode = 0,
|
||||||
|
|
||||||
bb = nil,
|
bb = nil,
|
||||||
saved_bb = nil,
|
saved_bb = nil,
|
||||||
|
|
||||||
fb = einkfb.open("/dev/fb0"),
|
fb = einkfb.open("/dev/fb0"),
|
||||||
-- will be set upon loading by Device class:
|
-- will be set upon loading by Device class:
|
||||||
device = nil,
|
device = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Screen:init()
|
function Screen:init()
|
||||||
self.bb = self.fb.bb
|
self.bb = self.fb.bb
|
||||||
self.blitbuffer_rotation_mode = self.bb:getRotation()
|
self.blitbuffer_rotation_mode = self.bb:getRotation()
|
||||||
-- asking the framebuffer for orientation is error prone,
|
-- asking the framebuffer for orientation is error prone,
|
||||||
-- so we do this simple heuristic (for now)
|
-- so we do this simple heuristic (for now)
|
||||||
if self:getWidth() > self:getHeight() then
|
if self:getWidth() > self:getHeight() then
|
||||||
self.native_rotation_mode = 1
|
self.native_rotation_mode = 1
|
||||||
else
|
else
|
||||||
self.native_rotation_mode = 0
|
self.native_rotation_mode = 0
|
||||||
end
|
end
|
||||||
self.cur_rotation_mode = self.native_rotation_mode
|
self.cur_rotation_mode = self.native_rotation_mode
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:refresh(refresh_type, waveform_mode, x, y, w, h)
|
function Screen:refresh(refresh_type, waveform_mode, x, y, w, h)
|
||||||
self.fb:refresh(refresh_type, waveform_mode, x, y, w, h)
|
self.fb:refresh(refresh_type, waveform_mode, x, y, w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getSize()
|
function Screen:getSize()
|
||||||
return Geom:new{w = self.bb:getWidth(), h = self.bb:getHeight()}
|
return Geom:new{w = self.bb:getWidth(), h = self.bb:getHeight()}
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getWidth()
|
function Screen:getWidth()
|
||||||
return self.bb:getWidth()
|
return self.bb:getWidth()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getHeight()
|
function Screen:getHeight()
|
||||||
return self.bb:getHeight()
|
return self.bb:getHeight()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getDPI()
|
function Screen:getDPI()
|
||||||
if(self.device:getModel() == "KindlePaperWhite")
|
if(self.device:getModel() == "KindlePaperWhite")
|
||||||
or (self.device:getModel() == "Kobo_kraken")
|
or (self.device:getModel() == "Kobo_kraken")
|
||||||
or (self.device:getModel() == "Kobo_phoenix") then
|
or (self.device:getModel() == "Kobo_phoenix") then
|
||||||
return 212
|
return 212
|
||||||
elseif self.device:getModel() == "Kobo_dragon" then
|
elseif self.device:getModel() == "Kobo_dragon" then
|
||||||
return 265
|
return 265
|
||||||
elseif self.device:getModel() == "Kobo_pixie" then
|
elseif self.device:getModel() == "Kobo_pixie" then
|
||||||
return 200
|
return 200
|
||||||
else
|
else
|
||||||
return 167
|
return 167
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:scaleByDPI(px)
|
function Screen:scaleByDPI(px)
|
||||||
return math.floor(px * self:getDPI()/167)
|
return math.floor(px * self:getDPI()/167)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:rescaleByDPI(px)
|
function Screen:rescaleByDPI(px)
|
||||||
return math.ceil(px * 167/self:getDPI())
|
return math.ceil(px * 167/self:getDPI())
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getRotationMode()
|
function Screen:getRotationMode()
|
||||||
return self.cur_rotation_mode
|
return self.cur_rotation_mode
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getScreenMode()
|
function Screen:getScreenMode()
|
||||||
if self:getWidth() > self:getHeight() then
|
if self:getWidth() > self:getHeight() then
|
||||||
return "landscape"
|
return "landscape"
|
||||||
else
|
else
|
||||||
return "portrait"
|
return "portrait"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:setRotationMode(mode)
|
function Screen:setRotationMode(mode)
|
||||||
self.fb.bb:rotateAbsolute(-90 * (mode - self.native_rotation_mode - self.blitbuffer_rotation_mode))
|
self.fb.bb:rotateAbsolute(-90 * (mode - self.native_rotation_mode - self.blitbuffer_rotation_mode))
|
||||||
self.cur_rotation_mode = mode
|
self.cur_rotation_mode = mode
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:setScreenMode(mode)
|
function Screen:setScreenMode(mode)
|
||||||
if mode == "portrait" then
|
if mode == "portrait" then
|
||||||
if self.cur_rotation_mode ~= 0 then
|
if self.cur_rotation_mode ~= 0 then
|
||||||
self:setRotationMode(0)
|
self:setRotationMode(0)
|
||||||
end
|
end
|
||||||
elseif mode == "landscape" then
|
elseif mode == "landscape" then
|
||||||
if self.cur_rotation_mode == 0 or self.cur_rotation_mode == 2 then
|
if self.cur_rotation_mode == 0 or self.cur_rotation_mode == 2 then
|
||||||
self:setRotationMode(DLANDSCAPE_CLOCKWISE_ROTATION and 1 or 3)
|
self:setRotationMode(DLANDSCAPE_CLOCKWISE_ROTATION and 1 or 3)
|
||||||
elseif self.cur_rotation_mode == 1 or self.cur_rotation_mode == 3 then
|
elseif self.cur_rotation_mode == 1 or self.cur_rotation_mode == 3 then
|
||||||
self:setRotationMode((self.cur_rotation_mode + 2) % 4)
|
self:setRotationMode((self.cur_rotation_mode + 2) % 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:saveCurrentBB()
|
function Screen:saveCurrentBB()
|
||||||
local width, height = self:getWidth(), self:getHeight()
|
local width, height = self:getWidth(), self:getHeight()
|
||||||
|
|
||||||
if not self.saved_bb then
|
if not self.saved_bb then
|
||||||
self.saved_bb = Blitbuffer.new(width, height)
|
self.saved_bb = Blitbuffer.new(width, height)
|
||||||
end
|
end
|
||||||
if self.saved_bb:getWidth() ~= width then
|
if self.saved_bb:getWidth() ~= width then
|
||||||
self.saved_bb:free()
|
self.saved_bb:free()
|
||||||
self.saved_bb = Blitbuffer.new(width, height)
|
self.saved_bb = Blitbuffer.new(width, height)
|
||||||
end
|
end
|
||||||
self.saved_bb:blitFullFrom(self.bb)
|
self.saved_bb:blitFullFrom(self.bb)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:restoreFromSavedBB()
|
function Screen:restoreFromSavedBB()
|
||||||
self:restoreFromBB(self.saved_bb)
|
self:restoreFromBB(self.saved_bb)
|
||||||
-- free data
|
-- free data
|
||||||
self.saved_bb = nil
|
self.saved_bb = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:getCurrentScreenBB()
|
function Screen:getCurrentScreenBB()
|
||||||
local bb = Blitbuffer.new(self:getWidth(), self:getHeight())
|
local bb = Blitbuffer.new(self:getWidth(), self:getHeight())
|
||||||
bb:blitFullFrom(self.bb)
|
bb:blitFullFrom(self.bb)
|
||||||
return bb
|
return bb
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:restoreFromBB(bb)
|
function Screen:restoreFromBB(bb)
|
||||||
if bb then
|
if bb then
|
||||||
self.bb:blitFullFrom(bb)
|
self.bb:blitFullFrom(bb)
|
||||||
else
|
else
|
||||||
DEBUG("Got nil bb in restoreFromSavedBB!")
|
DEBUG("Got nil bb in restoreFromSavedBB!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Screen
|
return Screen
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ below.
|
|||||||
local Event = {}
|
local Event = {}
|
||||||
|
|
||||||
function Event:new(name, ...)
|
function Event:new(name, ...)
|
||||||
local o = {
|
local o = {
|
||||||
handler = "on"..name,
|
handler = "on"..name,
|
||||||
args = {...}
|
args = {...}
|
||||||
}
|
}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
return Event
|
return Event
|
||||||
|
|||||||
@@ -2,102 +2,102 @@ local Screen = require("ui/screen")
|
|||||||
local DEBUG = require("dbg")
|
local DEBUG = require("dbg")
|
||||||
|
|
||||||
local Font = {
|
local Font = {
|
||||||
fontmap = {
|
fontmap = {
|
||||||
-- default font for menu contents
|
-- default font for menu contents
|
||||||
cfont = "droid/DroidSans.ttf",
|
cfont = "droid/DroidSans.ttf",
|
||||||
-- default font for title
|
-- default font for title
|
||||||
--tfont = "NimbusSanL-BoldItal.cff",
|
--tfont = "NimbusSanL-BoldItal.cff",
|
||||||
tfont = "droid/DroidSans.ttf",
|
tfont = "droid/DroidSans.ttf",
|
||||||
-- default font for footer
|
-- default font for footer
|
||||||
ffont = "droid/DroidSans.ttf",
|
ffont = "droid/DroidSans.ttf",
|
||||||
|
|
||||||
-- default font for reading position info
|
-- default font for reading position info
|
||||||
rifont = "droid/DroidSans.ttf",
|
rifont = "droid/DroidSans.ttf",
|
||||||
|
|
||||||
-- default font for pagination display
|
-- default font for pagination display
|
||||||
pgfont = "droid/DroidSans.ttf",
|
pgfont = "droid/DroidSans.ttf",
|
||||||
|
|
||||||
-- selectmenu: font for item shortcut
|
-- selectmenu: font for item shortcut
|
||||||
scfont = "droid/DroidSansMono.ttf",
|
scfont = "droid/DroidSansMono.ttf",
|
||||||
|
|
||||||
-- help page: font for displaying keys
|
-- help page: font for displaying keys
|
||||||
hpkfont = "droid/DroidSansMono.ttf",
|
hpkfont = "droid/DroidSansMono.ttf",
|
||||||
-- font for displaying help messages
|
-- font for displaying help messages
|
||||||
hfont = "droid/DroidSans.ttf",
|
hfont = "droid/DroidSans.ttf",
|
||||||
|
|
||||||
-- font for displaying input content
|
-- font for displaying input content
|
||||||
-- we have to use mono here for better distance controlling
|
-- we have to use mono here for better distance controlling
|
||||||
infont = "droid/DroidSansMono.ttf",
|
infont = "droid/DroidSansMono.ttf",
|
||||||
|
|
||||||
-- font for info messages
|
-- font for info messages
|
||||||
infofont = "droid/DroidSans.ttf",
|
infofont = "droid/DroidSans.ttf",
|
||||||
},
|
},
|
||||||
fallbacks = {
|
fallbacks = {
|
||||||
[1] = "droid/DroidSansFallback.ttf",
|
[1] = "droid/DroidSansFallback.ttf",
|
||||||
[2] = "droid/DroidSans.ttf",
|
[2] = "droid/DroidSans.ttf",
|
||||||
[3] = "freefont/FreeSans.ttf",
|
[3] = "freefont/FreeSans.ttf",
|
||||||
},
|
},
|
||||||
|
|
||||||
fontdir = os.getenv("FONTDIR") or "./fonts",
|
fontdir = os.getenv("FONTDIR") or "./fonts",
|
||||||
|
|
||||||
-- face table
|
-- face table
|
||||||
faces = {},
|
faces = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Font:getFace(font, size)
|
function Font:getFace(font, size)
|
||||||
if not font then
|
if not font then
|
||||||
-- default to content font
|
-- default to content font
|
||||||
font = self.cfont
|
font = self.cfont
|
||||||
end
|
end
|
||||||
|
|
||||||
local size = Screen:scaleByDPI(size)
|
local size = Screen:scaleByDPI(size)
|
||||||
|
|
||||||
local face = self.faces[font..size]
|
local face = self.faces[font..size]
|
||||||
-- build face if not found
|
-- build face if not found
|
||||||
if not face then
|
if not face then
|
||||||
local realname = self.fontmap[font]
|
local realname = self.fontmap[font]
|
||||||
if not realname then
|
if not realname then
|
||||||
realname = font
|
realname = font
|
||||||
end
|
end
|
||||||
realname = self.fontdir.."/"..realname
|
realname = self.fontdir.."/"..realname
|
||||||
ok, face = pcall(freetype.newFace, realname, size)
|
ok, face = pcall(freetype.newFace, realname, size)
|
||||||
if not ok then
|
if not ok then
|
||||||
DEBUG("#! Font "..font.." ("..realname..") not supported: "..face)
|
DEBUG("#! Font "..font.." ("..realname..") not supported: "..face)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
self.faces[font..size] = face
|
self.faces[font..size] = face
|
||||||
--DEBUG("getFace, found: "..realname.." size:"..size)
|
--DEBUG("getFace, found: "..realname.." size:"..size)
|
||||||
end
|
end
|
||||||
return { size = size, ftface = face, hash = font..size }
|
return { size = size, ftface = face, hash = font..size }
|
||||||
end
|
end
|
||||||
|
|
||||||
function Font:_readList(target, dir, effective_dir)
|
function Font:_readList(target, dir, effective_dir)
|
||||||
for f in lfs.dir(dir) do
|
for f in lfs.dir(dir) do
|
||||||
if lfs.attributes(dir.."/"..f, "mode") == "directory" and f ~= "." and f ~= ".." then
|
if lfs.attributes(dir.."/"..f, "mode") == "directory" and f ~= "." and f ~= ".." then
|
||||||
self:_readList(target, dir.."/"..f, effective_dir..f.."/")
|
self:_readList(target, dir.."/"..f, effective_dir..f.."/")
|
||||||
else
|
else
|
||||||
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
|
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
|
||||||
if file_type == "ttf" or file_type == "cff" or file_type == "otf" then
|
if file_type == "ttf" or file_type == "cff" or file_type == "otf" then
|
||||||
table.insert(target, effective_dir..f)
|
table.insert(target, effective_dir..f)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Font:getFontList()
|
function Font:getFontList()
|
||||||
fontlist = {}
|
fontlist = {}
|
||||||
self:_readList(fontlist, self.fontdir, "")
|
self:_readList(fontlist, self.fontdir, "")
|
||||||
table.sort(fontlist)
|
table.sort(fontlist)
|
||||||
return fontlist
|
return fontlist
|
||||||
end
|
end
|
||||||
|
|
||||||
function Font:update()
|
function Font:update()
|
||||||
for _k, _v in ipairs(self.faces) do
|
for _k, _v in ipairs(self.faces) do
|
||||||
_v:done()
|
_v:done()
|
||||||
end
|
end
|
||||||
self.faces = {}
|
self.faces = {}
|
||||||
clearGlyphCache()
|
clearGlyphCache()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Font
|
return Font
|
||||||
|
|||||||
@@ -12,48 +12,48 @@ just use it on simple tables that have x, y and/or w, h
|
|||||||
or define your own types using this as a metatable
|
or define your own types using this as a metatable
|
||||||
]]--
|
]]--
|
||||||
local Geom = {
|
local Geom = {
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
w = 0,
|
w = 0,
|
||||||
h = 0
|
h = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function Geom:new(o)
|
function Geom:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function Geom:copy()
|
function Geom:copy()
|
||||||
local n = Geom:new()
|
local n = Geom:new()
|
||||||
n.x = self.x
|
n.x = self.x
|
||||||
n.y = self.y
|
n.y = self.y
|
||||||
n.w = self.w
|
n.w = self.w
|
||||||
n.h = self.h
|
n.h = self.h
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
function Geom:__tostring()
|
function Geom:__tostring()
|
||||||
return self.w.."x"..self.h.."+"..self.x.."+"..self.y
|
return self.w.."x"..self.h.."+"..self.x.."+"..self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
offset rectangle or point by relative values
|
offset rectangle or point by relative values
|
||||||
]]--
|
]]--
|
||||||
function Geom:offsetBy(dx, dy)
|
function Geom:offsetBy(dx, dy)
|
||||||
self.x = self.x + dx
|
self.x = self.x + dx
|
||||||
self.y = self.y + dy
|
self.y = self.y + dy
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
offset rectangle or point to certain coordinates
|
offset rectangle or point to certain coordinates
|
||||||
]]--
|
]]--
|
||||||
function Geom:offsetTo(x, y)
|
function Geom:offsetTo(x, y)
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -62,29 +62,29 @@ scale rectangle (grow to bottom and to the right) or dimension
|
|||||||
if a single factor is given, it is applied to both width and height
|
if a single factor is given, it is applied to both width and height
|
||||||
]]--
|
]]--
|
||||||
function Geom:scaleBy(zx, zy)
|
function Geom:scaleBy(zx, zy)
|
||||||
self.w = self.w * zx
|
self.w = self.w * zx
|
||||||
self.h = self.h * (zy or zx)
|
self.h = self.h * (zy or zx)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
this method also takes care of x and y
|
this method also takes care of x and y
|
||||||
]]--
|
]]--
|
||||||
function Geom:transformByScale(zx, zy)
|
function Geom:transformByScale(zx, zy)
|
||||||
self.x = self.x * zx
|
self.x = self.x * zx
|
||||||
self.y = self.y * (zx or zy)
|
self.y = self.y * (zx or zy)
|
||||||
self:scaleBy(zx, zy)
|
self:scaleBy(zx, zy)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
return size of geom
|
return size of geom
|
||||||
]]--
|
]]--
|
||||||
function Geom:sizeof()
|
function Geom:sizeof()
|
||||||
if not self.w or not self.h then
|
if not self.w or not self.h then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return self.w * self.h
|
return self.w * self.h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -93,9 +93,9 @@ enlarges or shrinks dimensions or rectangles
|
|||||||
note that for rectangles the offset stays the same
|
note that for rectangles the offset stays the same
|
||||||
]]--
|
]]--
|
||||||
function Geom:changeSizeBy(dw, dh)
|
function Geom:changeSizeBy(dw, dh)
|
||||||
self.w = self.w + dw
|
self.w = self.w + dw
|
||||||
self.h = self.h + dh
|
self.h = self.h + dh
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -104,25 +104,25 @@ return the outer rectangle that contains both us and a given rectangle
|
|||||||
works for rectangles, dimensions and points
|
works for rectangles, dimensions and points
|
||||||
]]--
|
]]--
|
||||||
function Geom:combine(rect_b)
|
function Geom:combine(rect_b)
|
||||||
local combined = self:copy()
|
local combined = self:copy()
|
||||||
if not rect_b or rect_b:sizeof() == 0 then return combined end
|
if not rect_b or rect_b:sizeof() == 0 then return combined end
|
||||||
if combined.x > rect_b.x then
|
if combined.x > rect_b.x then
|
||||||
combined.x = rect_b.x
|
combined.x = rect_b.x
|
||||||
end
|
end
|
||||||
if combined.y > rect_b.y then
|
if combined.y > rect_b.y then
|
||||||
combined.y = rect_b.y
|
combined.y = rect_b.y
|
||||||
end
|
end
|
||||||
if self.x + self.w > rect_b.x + rect_b.w then
|
if self.x + self.w > rect_b.x + rect_b.w then
|
||||||
combined.w = self.x + self.w - combined.x
|
combined.w = self.x + self.w - combined.x
|
||||||
else
|
else
|
||||||
combined.w = rect_b.x + rect_b.w - combined.x
|
combined.w = rect_b.x + rect_b.w - combined.x
|
||||||
end
|
end
|
||||||
if self.y + self.h > rect_b.y + rect_b.h then
|
if self.y + self.h > rect_b.y + rect_b.h then
|
||||||
combined.h = self.y + self.h - combined.y
|
combined.h = self.y + self.h - combined.y
|
||||||
else
|
else
|
||||||
combined.h = rect_b.y + rect_b.h - combined.y
|
combined.h = rect_b.y + rect_b.h - combined.y
|
||||||
end
|
end
|
||||||
return combined
|
return combined
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -131,47 +131,47 @@ returns a rectangle for the part that we and a given rectangle share
|
|||||||
TODO: what happens if there is no rectangle shared? currently behaviour is undefined.
|
TODO: what happens if there is no rectangle shared? currently behaviour is undefined.
|
||||||
]]--
|
]]--
|
||||||
function Geom:intersect(rect_b)
|
function Geom:intersect(rect_b)
|
||||||
-- make a copy of self
|
-- make a copy of self
|
||||||
local intersected = self:copy()
|
local intersected = self:copy()
|
||||||
if self.x < rect_b.x then
|
if self.x < rect_b.x then
|
||||||
intersected.x = rect_b.x
|
intersected.x = rect_b.x
|
||||||
end
|
end
|
||||||
if self.y < rect_b.y then
|
if self.y < rect_b.y then
|
||||||
intersected.y = rect_b.y
|
intersected.y = rect_b.y
|
||||||
end
|
end
|
||||||
if self.x + self.w < rect_b.x + rect_b.w then
|
if self.x + self.w < rect_b.x + rect_b.w then
|
||||||
intersected.w = self.x + self.w - intersected.x
|
intersected.w = self.x + self.w - intersected.x
|
||||||
else
|
else
|
||||||
intersected.w = rect_b.x + rect_b.w - intersected.x
|
intersected.w = rect_b.x + rect_b.w - intersected.x
|
||||||
end
|
end
|
||||||
if self.y + self.h < rect_b.y + rect_b.h then
|
if self.y + self.h < rect_b.y + rect_b.h then
|
||||||
intersected.h = self.y + self.h - intersected.y
|
intersected.h = self.y + self.h - intersected.y
|
||||||
else
|
else
|
||||||
intersected.h = rect_b.y + rect_b.h - intersected.y
|
intersected.h = rect_b.y + rect_b.h - intersected.y
|
||||||
end
|
end
|
||||||
return intersected
|
return intersected
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
return true if self does not share any area with rect_b
|
return true if self does not share any area with rect_b
|
||||||
]]--
|
]]--
|
||||||
function Geom:notIntersectWith(rect_b)
|
function Geom:notIntersectWith(rect_b)
|
||||||
if (self.x >= (rect_b.x + rect_b.w))
|
if (self.x >= (rect_b.x + rect_b.w))
|
||||||
or (self.y >= (rect_b.y + rect_b.h))
|
or (self.y >= (rect_b.y + rect_b.h))
|
||||||
or (rect_b.x >= (self.x + self.w))
|
or (rect_b.x >= (self.x + self.w))
|
||||||
or (rect_b.y >= (self.y + self.h)) then
|
or (rect_b.y >= (self.y + self.h)) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
set size of dimension or rectangle to size of given dimension/rectangle
|
set size of dimension or rectangle to size of given dimension/rectangle
|
||||||
]]--
|
]]--
|
||||||
function Geom:setSizeTo(rect_b)
|
function Geom:setSizeTo(rect_b)
|
||||||
self.w = rect_b.w
|
self.w = rect_b.w
|
||||||
self.h = rect_b.h
|
self.h = rect_b.h
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -181,14 +181,14 @@ works for dimensions, too
|
|||||||
for points, it is basically an equality check
|
for points, it is basically an equality check
|
||||||
]]--
|
]]--
|
||||||
function Geom:contains(rect_b)
|
function Geom:contains(rect_b)
|
||||||
if self.x <= rect_b.x
|
if self.x <= rect_b.x
|
||||||
and self.y <= rect_b.y
|
and self.y <= rect_b.y
|
||||||
and self.x + self.w >= rect_b.x + rect_b.w
|
and self.x + self.w >= rect_b.x + rect_b.w
|
||||||
and self.y + self.h >= rect_b.y + rect_b.h
|
and self.y + self.h >= rect_b.y + rect_b.h
|
||||||
then
|
then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -197,48 +197,48 @@ check for equality
|
|||||||
works for rectangles, points, dimensions
|
works for rectangles, points, dimensions
|
||||||
]]--
|
]]--
|
||||||
function Geom:__eq(rect_b)
|
function Geom:__eq(rect_b)
|
||||||
if self.x == rect_b.x
|
if self.x == rect_b.x
|
||||||
and self.y == rect_b.y
|
and self.y == rect_b.y
|
||||||
and self:equalSize(rect_b)
|
and self:equalSize(rect_b)
|
||||||
then
|
then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
check size of dimension/rectangle for equality
|
check size of dimension/rectangle for equality
|
||||||
]]--
|
]]--
|
||||||
function Geom:equalSize(rect_b)
|
function Geom:equalSize(rect_b)
|
||||||
if self.w == rect_b.w
|
if self.w == rect_b.w
|
||||||
and self.h == rect_b.h
|
and self.h == rect_b.h
|
||||||
then
|
then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
check if our size is smaller than the size of the given dimension/rectangle
|
check if our size is smaller than the size of the given dimension/rectangle
|
||||||
]]--
|
]]--
|
||||||
function Geom:__lt(rect_b)
|
function Geom:__lt(rect_b)
|
||||||
DEBUG("lt:",self,rect_b)
|
DEBUG("lt:",self,rect_b)
|
||||||
if self.w < rect_b.w and self.h < rect_b.h then
|
if self.w < rect_b.w and self.h < rect_b.h then
|
||||||
DEBUG("lt+")
|
DEBUG("lt+")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
DEBUG("lt-")
|
DEBUG("lt-")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
check if our size is smaller or equal the size of the given dimension/rectangle
|
check if our size is smaller or equal the size of the given dimension/rectangle
|
||||||
]]--
|
]]--
|
||||||
function Geom:__le(rect_b)
|
function Geom:__le(rect_b)
|
||||||
if self.w <= rect_b.w and self.h <= rect_b.h then
|
if self.w <= rect_b.w and self.h <= rect_b.h then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -249,92 +249,92 @@ this can also be called with dx=0 and dy=0, which will fit the current
|
|||||||
rectangle into the given rectangle
|
rectangle into the given rectangle
|
||||||
]]--
|
]]--
|
||||||
function Geom:offsetWithin(rect_b, dx, dy)
|
function Geom:offsetWithin(rect_b, dx, dy)
|
||||||
-- check size constraints and shrink us when we're too big
|
-- check size constraints and shrink us when we're too big
|
||||||
if self.w > rect_b.w then
|
if self.w > rect_b.w then
|
||||||
self.w = rect_b.w
|
self.w = rect_b.w
|
||||||
end
|
end
|
||||||
if self.h > rect_b.h then
|
if self.h > rect_b.h then
|
||||||
self.h = rect_b.h
|
self.h = rect_b.h
|
||||||
end
|
end
|
||||||
-- offset
|
-- offset
|
||||||
self.x = self.x + dx
|
self.x = self.x + dx
|
||||||
self.y = self.y + dy
|
self.y = self.y + dy
|
||||||
-- check offsets
|
-- check offsets
|
||||||
if self.x < rect_b.x then
|
if self.x < rect_b.x then
|
||||||
self.x = rect_b.x
|
self.x = rect_b.x
|
||||||
end
|
end
|
||||||
if self.y < rect_b.y then
|
if self.y < rect_b.y then
|
||||||
self.y = rect_b.y
|
self.y = rect_b.y
|
||||||
end
|
end
|
||||||
if self.x + self.w > rect_b.x + rect_b.w then
|
if self.x + self.w > rect_b.x + rect_b.w then
|
||||||
self.x = rect_b.x + rect_b.w - self.w
|
self.x = rect_b.x + rect_b.w - self.w
|
||||||
end
|
end
|
||||||
if self.y + self.h > rect_b.y + rect_b.h then
|
if self.y + self.h > rect_b.y + rect_b.h then
|
||||||
self.y = rect_b.y + rect_b.h - self.h
|
self.y = rect_b.y + rect_b.h - self.h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
center the current rectangle at position x and y of a given rectangle
|
center the current rectangle at position x and y of a given rectangle
|
||||||
]]--
|
]]--
|
||||||
function Geom:centerWithin(rect_b, x, y)
|
function Geom:centerWithin(rect_b, x, y)
|
||||||
-- check size constraints and shrink us when we're too big
|
-- check size constraints and shrink us when we're too big
|
||||||
if self.w > rect_b.w then
|
if self.w > rect_b.w then
|
||||||
self.w = rect_b.w
|
self.w = rect_b.w
|
||||||
end
|
end
|
||||||
if self.h > rect_b.h then
|
if self.h > rect_b.h then
|
||||||
self.h = rect_b.h
|
self.h = rect_b.h
|
||||||
end
|
end
|
||||||
-- place to center
|
-- place to center
|
||||||
self.x = x - self.w/2
|
self.x = x - self.w/2
|
||||||
self.y = y - self.h/2
|
self.y = y - self.h/2
|
||||||
-- check boundary
|
-- check boundary
|
||||||
if self.x < rect_b.x then
|
if self.x < rect_b.x then
|
||||||
self.x = rect_b.x
|
self.x = rect_b.x
|
||||||
end
|
end
|
||||||
if self.y < rect_b.y then
|
if self.y < rect_b.y then
|
||||||
self.y = rect_b.y
|
self.y = rect_b.y
|
||||||
end
|
end
|
||||||
if self.x + self.w > rect_b.x + rect_b.w then
|
if self.x + self.w > rect_b.x + rect_b.w then
|
||||||
self.x = rect_b.x + rect_b.w - self.w
|
self.x = rect_b.x + rect_b.w - self.w
|
||||||
end
|
end
|
||||||
if self.y + self.h > rect_b.y + rect_b.h then
|
if self.y + self.h > rect_b.y + rect_b.h then
|
||||||
self.y = rect_b.y + rect_b.h - self.h
|
self.y = rect_b.y + rect_b.h - self.h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Geom:shrinkInside(rect_b, dx, dy)
|
function Geom:shrinkInside(rect_b, dx, dy)
|
||||||
self:offsetBy(dx, dy)
|
self:offsetBy(dx, dy)
|
||||||
return self:intersect(rect_b)
|
return self:intersect(rect_b)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
return the Euclidean distance between two geoms
|
return the Euclidean distance between two geoms
|
||||||
]]--
|
]]--
|
||||||
function Geom:distance(geom)
|
function Geom:distance(geom)
|
||||||
return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2))
|
return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
return the midpoint of two geoms
|
return the midpoint of two geoms
|
||||||
]]--
|
]]--
|
||||||
function Geom:midpoint(geom)
|
function Geom:midpoint(geom)
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
x = (self.x + geom.x) / 2,
|
x = (self.x + geom.x) / 2,
|
||||||
y = (self.y + geom.y) / 2,
|
y = (self.y + geom.y) / 2,
|
||||||
w = 0, h = 0,
|
w = 0, h = 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
return center point in this geom
|
return center point in this geom
|
||||||
]]--
|
]]--
|
||||||
function Geom:center()
|
function Geom:center()
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
x = self.x + self.w / 2,
|
x = self.x + self.w / 2,
|
||||||
y = self.y + self.h / 2,
|
y = self.y + self.h / 2,
|
||||||
w = 0, h = 0,
|
w = 0, h = 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return Geom
|
return Geom
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +1,50 @@
|
|||||||
local TimeVal = require("ui/timeval")
|
local TimeVal = require("ui/timeval")
|
||||||
|
|
||||||
local GestureRange = {
|
local GestureRange = {
|
||||||
ges = nil,
|
ges = nil,
|
||||||
-- spatial range limits the gesture emitting position
|
-- spatial range limits the gesture emitting position
|
||||||
range = nil,
|
range = nil,
|
||||||
-- temproal range limits the gesture emitting rate
|
-- temproal range limits the gesture emitting rate
|
||||||
rate = nil,
|
rate = nil,
|
||||||
-- span limits of this gesture
|
-- span limits of this gesture
|
||||||
scale = nil,
|
scale = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function GestureRange:new(o)
|
function GestureRange:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function GestureRange:match(gs)
|
function GestureRange:match(gs)
|
||||||
if gs.ges ~= self.ges then
|
if gs.ges ~= self.ges then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if self.range then
|
if self.range then
|
||||||
if not self.range:contains(gs.pos) then
|
if not self.range:contains(gs.pos) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.rate then
|
if self.rate then
|
||||||
local last_time = self.last_time or TimeVal:new{}
|
local last_time = self.last_time or TimeVal:new{}
|
||||||
if gs.time - last_time > TimeVal:new{usec = 1000000 / self.rate} then
|
if gs.time - last_time > TimeVal:new{usec = 1000000 / self.rate} then
|
||||||
self.last_time = gs.time
|
self.last_time = gs.time
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.scale then
|
if self.scale then
|
||||||
if self.scale[1] > gs.span or self.scale[2] < gs.span then
|
if self.scale[1] > gs.span or self.scale[2] < gs.span then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.direction then
|
if self.direction then
|
||||||
if self.direction ~= gs.direction then
|
if self.direction ~= gs.direction then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return GestureRange
|
return GestureRange
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,47 +7,47 @@ local _ = require("gettext")
|
|||||||
Language = {}
|
Language = {}
|
||||||
|
|
||||||
function Language:changeLanguage(lang_locale)
|
function Language:changeLanguage(lang_locale)
|
||||||
_.changeLang(lang_locale)
|
_.changeLang(lang_locale)
|
||||||
G_reader_settings:saveSetting("language", lang_locale)
|
G_reader_settings:saveSetting("language", lang_locale)
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Please restart reader for new language setting to take effect."),
|
text = _("Please restart reader for new language setting to take effect."),
|
||||||
timeout = 3,
|
timeout = 3,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function Language:genLanguageSubItem(lang, lang_locale)
|
function Language:genLanguageSubItem(lang, lang_locale)
|
||||||
return {
|
return {
|
||||||
text = lang,
|
text = lang,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:changeLanguage(lang_locale)
|
self:changeLanguage(lang_locale)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function Language:getLangMenuTable()
|
function Language:getLangMenuTable()
|
||||||
-- cache menu table
|
-- cache menu table
|
||||||
if not self.LangMenuTable then
|
if not self.LangMenuTable then
|
||||||
self.LangMenuTable = {
|
self.LangMenuTable = {
|
||||||
text = _("Language"),
|
text = _("Language"),
|
||||||
-- NOTE: language with no translation are commented out for now
|
-- NOTE: language with no translation are commented out for now
|
||||||
sub_item_table = {
|
sub_item_table = {
|
||||||
self:genLanguageSubItem("English", "C"),
|
self:genLanguageSubItem("English", "C"),
|
||||||
self:genLanguageSubItem("čeština", "cs_CZ"),
|
self:genLanguageSubItem("čeština", "cs_CZ"),
|
||||||
self:genLanguageSubItem("Deutsch", "de"),
|
self:genLanguageSubItem("Deutsch", "de"),
|
||||||
self:genLanguageSubItem("français", "fr"),
|
self:genLanguageSubItem("français", "fr"),
|
||||||
--self:genLanguageSubItem("magyar", "hu"),
|
--self:genLanguageSubItem("magyar", "hu"),
|
||||||
self:genLanguageSubItem("Italiano", "it_IT"),
|
self:genLanguageSubItem("Italiano", "it_IT"),
|
||||||
self:genLanguageSubItem("Polski", "pl"),
|
self:genLanguageSubItem("Polski", "pl"),
|
||||||
self:genLanguageSubItem("Português do Brasil", "pt_BR"),
|
self:genLanguageSubItem("Português do Brasil", "pt_BR"),
|
||||||
self:genLanguageSubItem("Русский язык", "ru"),
|
self:genLanguageSubItem("Русский язык", "ru"),
|
||||||
--self:genLanguageSubItem("svenska", "sv"),
|
--self:genLanguageSubItem("svenska", "sv"),
|
||||||
self:genLanguageSubItem("Türkçe", "tr"),
|
self:genLanguageSubItem("Türkçe", "tr"),
|
||||||
--self:genLanguageSubItem("Tiếng Việt", "vi"),
|
--self:genLanguageSubItem("Tiếng Việt", "vi"),
|
||||||
self:genLanguageSubItem("简体中文", "zh_CN"),
|
self:genLanguageSubItem("简体中文", "zh_CN"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
return self.LangMenuTable
|
return self.LangMenuTable
|
||||||
end
|
end
|
||||||
|
|
||||||
return Language
|
return Language
|
||||||
|
|||||||
@@ -5,43 +5,43 @@ local Device = require("ui/device")
|
|||||||
local ReaderActivityIndicator = EventListener:new{}
|
local ReaderActivityIndicator = EventListener:new{}
|
||||||
|
|
||||||
function ReaderActivityIndicator:init()
|
function ReaderActivityIndicator:init()
|
||||||
local dev_mod = Device:getModel()
|
local dev_mod = Device:getModel()
|
||||||
if dev_mod == "KindlePaperWhite" or dev_mod == "KindlePaperWhite2" or dev_mod == "KindleTouch" then
|
if dev_mod == "KindlePaperWhite" or dev_mod == "KindlePaperWhite2" or dev_mod == "KindleTouch" then
|
||||||
require "liblipclua"
|
require "liblipclua"
|
||||||
self.lipc_handle = lipc.init("com.github.koreader.activityindicator")
|
self.lipc_handle = lipc.init("com.github.koreader.activityindicator")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderActivityIndicator:onStartActivityIndicator()
|
function ReaderActivityIndicator:onStartActivityIndicator()
|
||||||
if self.lipc_handle then
|
if self.lipc_handle then
|
||||||
-- check if activity indicator is needed
|
-- check if activity indicator is needed
|
||||||
if self.document.configurable.text_wrap == 1 then
|
if self.document.configurable.text_wrap == 1 then
|
||||||
-- start indicator depends on pillow being enabled
|
-- start indicator depends on pillow being enabled
|
||||||
self.lipc_handle:set_string_property(
|
self.lipc_handle:set_string_property(
|
||||||
"com.lab126.pillow", "activityIndicator",
|
"com.lab126.pillow", "activityIndicator",
|
||||||
'{"activityIndicator":{ \
|
'{"activityIndicator":{ \
|
||||||
"action":"start","timeout":10000, \
|
"action":"start","timeout":10000, \
|
||||||
"clientId":"com.github.koreader.activityindicator", \
|
"clientId":"com.github.koreader.activityindicator", \
|
||||||
"priority":true}}')
|
"priority":true}}')
|
||||||
self.indicator_started = true
|
self.indicator_started = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderActivityIndicator:onStopActivityIndicator()
|
function ReaderActivityIndicator:onStopActivityIndicator()
|
||||||
if self.lipc_handle and self.indicator_started then
|
if self.lipc_handle and self.indicator_started then
|
||||||
-- stop indicator depends on pillow being enabled
|
-- stop indicator depends on pillow being enabled
|
||||||
self.lipc_handle:set_string_property(
|
self.lipc_handle:set_string_property(
|
||||||
"com.lab126.pillow", "activityIndicator",
|
"com.lab126.pillow", "activityIndicator",
|
||||||
'{"activityIndicator":{ \
|
'{"activityIndicator":{ \
|
||||||
"action":"stop","timeout":10000, \
|
"action":"stop","timeout":10000, \
|
||||||
"clientId":"com.github.koreader.activityindicator", \
|
"clientId":"com.github.koreader.activityindicator", \
|
||||||
"priority":true}}')
|
"priority":true}}')
|
||||||
self.indicator_started = false
|
self.indicator_started = false
|
||||||
util.usleep(1000000)
|
util.usleep(1000000)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderActivityIndicator
|
return ReaderActivityIndicator
|
||||||
|
|||||||
@@ -11,218 +11,218 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderBookmark = InputContainer:new{
|
local ReaderBookmark = InputContainer:new{
|
||||||
bm_menu_title = _("Bookmarks"),
|
bm_menu_title = _("Bookmarks"),
|
||||||
bookmarks = nil,
|
bookmarks = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderBookmark:init()
|
function ReaderBookmark:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowBookmark = {
|
ShowBookmark = {
|
||||||
{ "B" },
|
{ "B" },
|
||||||
doc = _("show bookmarks") },
|
doc = _("show bookmarks") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
ShowBookmark = {
|
ShowBookmark = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "two_finger_swipe",
|
ges = "two_finger_swipe",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
},
|
},
|
||||||
direction = "west"
|
direction = "west"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onReadSettings(config)
|
function ReaderBookmark:onReadSettings(config)
|
||||||
self.bookmarks = config:readSetting("bookmarks") or {}
|
self.bookmarks = config:readSetting("bookmarks") or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onSaveSettings()
|
function ReaderBookmark:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("bookmarks", self.bookmarks)
|
self.ui.doc_settings:saveSetting("bookmarks", self.bookmarks)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onToggleBookmark()
|
function ReaderBookmark:onToggleBookmark()
|
||||||
local pn_or_xp = nil
|
local pn_or_xp = nil
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
pn_or_xp = self.view.state.page
|
pn_or_xp = self.view.state.page
|
||||||
else
|
else
|
||||||
pn_or_xp = self.ui.document:getXPointer()
|
pn_or_xp = self.ui.document:getXPointer()
|
||||||
end
|
end
|
||||||
self:toggleBookmark(pn_or_xp)
|
self:toggleBookmark(pn_or_xp)
|
||||||
self.view.dogear_visible = not self.view.dogear_visible
|
self.view.dogear_visible = not self.view.dogear_visible
|
||||||
UIManager:setDirty(self.view.dialog, "partial")
|
UIManager:setDirty(self.view.dialog, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:setDogearVisibility(pn_or_xp)
|
function ReaderBookmark:setDogearVisibility(pn_or_xp)
|
||||||
if self:isBookmarked(pn_or_xp) then
|
if self:isBookmarked(pn_or_xp) then
|
||||||
self.ui:handleEvent(Event:new("SetDogearVisibility", true))
|
self.ui:handleEvent(Event:new("SetDogearVisibility", true))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetDogearVisibility", false))
|
self.ui:handleEvent(Event:new("SetDogearVisibility", false))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onPageUpdate(pageno)
|
function ReaderBookmark:onPageUpdate(pageno)
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
self:setDogearVisibility(pageno)
|
self:setDogearVisibility(pageno)
|
||||||
else
|
else
|
||||||
-- FIXME: this is a dirty hack to prevent crash in isXPointerInCurrentPage
|
-- FIXME: this is a dirty hack to prevent crash in isXPointerInCurrentPage
|
||||||
if pageno ~= 1 then
|
if pageno ~= 1 then
|
||||||
self:setDogearVisibility("dummy")
|
self:setDogearVisibility("dummy")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onPosUpdate(pos)
|
function ReaderBookmark:onPosUpdate(pos)
|
||||||
self:setDogearVisibility("dummy")
|
self:setDogearVisibility("dummy")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onShowBookmark()
|
function ReaderBookmark:onShowBookmark()
|
||||||
-- build up item_table
|
-- build up item_table
|
||||||
for k, v in ipairs(self.bookmarks) do
|
for k, v in ipairs(self.bookmarks) do
|
||||||
local page = v.page
|
local page = v.page
|
||||||
-- for CREngine, bookmark page is xpointer
|
-- for CREngine, bookmark page is xpointer
|
||||||
if type(page) == "string" then
|
if type(page) == "string" then
|
||||||
page = self.ui.document:getPageFromXPointer(v.page)
|
page = self.ui.document:getPageFromXPointer(v.page)
|
||||||
end
|
end
|
||||||
v.text = "Page "..page.." "..v.notes.." @ "..v.datetime
|
v.text = "Page "..page.." "..v.notes.." @ "..v.datetime
|
||||||
end
|
end
|
||||||
|
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
|
|
||||||
local bm_menu = Menu:new{
|
local bm_menu = Menu:new{
|
||||||
title = "Bookmarks",
|
title = "Bookmarks",
|
||||||
item_table = self.bookmarks,
|
item_table = self.bookmarks,
|
||||||
width = Screen:getWidth()-50,
|
width = Screen:getWidth()-50,
|
||||||
height = Screen:getHeight()-50,
|
height = Screen:getHeight()-50,
|
||||||
show_parent = menu_container,
|
show_parent = menu_container,
|
||||||
}
|
}
|
||||||
|
|
||||||
table.insert(menu_container, bm_menu)
|
table.insert(menu_container, bm_menu)
|
||||||
|
|
||||||
-- buid up menu widget method as closure
|
-- buid up menu widget method as closure
|
||||||
local doc = self.ui.document
|
local doc = self.ui.document
|
||||||
local view = self.view
|
local view = self.view
|
||||||
local sendEv = function(ev)
|
local sendEv = function(ev)
|
||||||
self.ui:handleEvent(ev)
|
self.ui:handleEvent(ev)
|
||||||
end
|
end
|
||||||
function bm_menu:onMenuChoice(item)
|
function bm_menu:onMenuChoice(item)
|
||||||
if doc.info.has_pages then
|
if doc.info.has_pages then
|
||||||
sendEv(Event:new("PageUpdate", item.page))
|
sendEv(Event:new("PageUpdate", item.page))
|
||||||
elseif view.view_mode == "page" then
|
elseif view.view_mode == "page" then
|
||||||
sendEv(Event:new("PageUpdate", doc:getPageFromXPointer(item.page)))
|
sendEv(Event:new("PageUpdate", doc:getPageFromXPointer(item.page)))
|
||||||
else
|
else
|
||||||
sendEv(Event:new("PosUpdate", doc:getPosFromXPointer(item.page)))
|
sendEv(Event:new("PosUpdate", doc:getPosFromXPointer(item.page)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
bm_menu.close_callback = function()
|
bm_menu.close_callback = function()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:addToMainMenu(tab_item_table)
|
function ReaderBookmark:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.navi, {
|
table.insert(tab_item_table.navi, {
|
||||||
text = self.bm_menu_title,
|
text = self.bm_menu_title,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:onShowBookmark()
|
self:onShowBookmark()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:isBookmarked(pn_or_xp)
|
function ReaderBookmark:isBookmarked(pn_or_xp)
|
||||||
for k,v in ipairs(self.bookmarks) do
|
for k,v in ipairs(self.bookmarks) do
|
||||||
if (type(pn_or_xp) == "number" and v.page == pn_or_xp) or
|
if (type(pn_or_xp) == "number" and v.page == pn_or_xp) or
|
||||||
(type(pn_or_xp) == "string" and self.ui.document:isXPointerInCurrentPage(v.page)) then
|
(type(pn_or_xp) == "string" and self.ui.document:isXPointerInCurrentPage(v.page)) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:addBookmark(pn_or_xp)
|
function ReaderBookmark:addBookmark(pn_or_xp)
|
||||||
-- build notes from TOC
|
-- build notes from TOC
|
||||||
local notes = self.ui.toc:getTocTitleByPage(pn_or_xp)
|
local notes = self.ui.toc:getTocTitleByPage(pn_or_xp)
|
||||||
if notes ~= "" then
|
if notes ~= "" then
|
||||||
notes = "in "..notes
|
notes = "in "..notes
|
||||||
end
|
end
|
||||||
mark_item = {
|
mark_item = {
|
||||||
page = pn_or_xp,
|
page = pn_or_xp,
|
||||||
datetime = os.date("%Y-%m-%d %H:%M:%S"),
|
datetime = os.date("%Y-%m-%d %H:%M:%S"),
|
||||||
notes = notes,
|
notes = notes,
|
||||||
}
|
}
|
||||||
table.insert(self.bookmarks, mark_item)
|
table.insert(self.bookmarks, mark_item)
|
||||||
table.sort(self.bookmarks, function(a,b)
|
table.sort(self.bookmarks, function(a,b)
|
||||||
return self:isBookmarkInSequence(a, b)
|
return self:isBookmarkInSequence(a, b)
|
||||||
end)
|
end)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:isBookmarkInSequence(a, b)
|
function ReaderBookmark:isBookmarkInSequence(a, b)
|
||||||
return a.page < b.page
|
return a.page < b.page
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:toggleBookmark(pn_or_xp)
|
function ReaderBookmark:toggleBookmark(pn_or_xp)
|
||||||
for k,v in ipairs(self.bookmarks) do
|
for k,v in ipairs(self.bookmarks) do
|
||||||
if (type(pn_or_xp) == "number" and v.page == pn_or_xp) or
|
if (type(pn_or_xp) == "number" and v.page == pn_or_xp) or
|
||||||
(type(pn_or_xp) == "string" and self.ui.document:isXPointerInCurrentPage(v.page)) then
|
(type(pn_or_xp) == "string" and self.ui.document:isXPointerInCurrentPage(v.page)) then
|
||||||
table.remove(self.bookmarks, k)
|
table.remove(self.bookmarks, k)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:addBookmark(pn_or_xp)
|
self:addBookmark(pn_or_xp)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:getPreviousBookmarkedPage(pn_or_xp)
|
function ReaderBookmark:getPreviousBookmarkedPage(pn_or_xp)
|
||||||
for i = #self.bookmarks, 1, -1 do
|
for i = #self.bookmarks, 1, -1 do
|
||||||
if pn_or_xp > self.bookmarks[i].page then
|
if pn_or_xp > self.bookmarks[i].page then
|
||||||
return self.bookmarks[i].page
|
return self.bookmarks[i].page
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:getNextBookmarkedPage(pn_or_xp)
|
function ReaderBookmark:getNextBookmarkedPage(pn_or_xp)
|
||||||
for i = 1, #self.bookmarks do
|
for i = 1, #self.bookmarks do
|
||||||
if pn_or_xp < self.bookmarks[i].page then
|
if pn_or_xp < self.bookmarks[i].page then
|
||||||
return self.bookmarks[i].page
|
return self.bookmarks[i].page
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onGotoPreviousBookmark(pn_or_xp)
|
function ReaderBookmark:onGotoPreviousBookmark(pn_or_xp)
|
||||||
self:GotoBookmark(self:getPreviousBookmarkedPage(pn_or_xp))
|
self:GotoBookmark(self:getPreviousBookmarkedPage(pn_or_xp))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:onGotoNextBookmark(pn_or_xp)
|
function ReaderBookmark:onGotoNextBookmark(pn_or_xp)
|
||||||
self:GotoBookmark(self:getNextBookmarkedPage(pn_or_xp))
|
self:GotoBookmark(self:getNextBookmarkedPage(pn_or_xp))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderBookmark:GotoBookmark(pn_or_xp)
|
function ReaderBookmark:GotoBookmark(pn_or_xp)
|
||||||
if type(pn_or_xp) == "string" then
|
if type(pn_or_xp) == "string" then
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getPageFromXPointer(pn_or_xp)))
|
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getPageFromXPointer(pn_or_xp)))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("PosUpdate", self.ui.document:getPosFromXPointer(pn_or_xp)))
|
self.ui:handleEvent(Event:new("PosUpdate", self.ui.document:getPosFromXPointer(pn_or_xp)))
|
||||||
end
|
end
|
||||||
elseif type(pn_or_xp) == "number" then
|
elseif type(pn_or_xp) == "number" then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", pn_or_xp))
|
self.ui:handleEvent(Event:new("PageUpdate", pn_or_xp))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderBookmark
|
return ReaderBookmark
|
||||||
|
|||||||
@@ -9,87 +9,87 @@ local UIManager = require("ui/uimanager")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderConfig = InputContainer:new{
|
local ReaderConfig = InputContainer:new{
|
||||||
last_panel_index = 1,
|
last_panel_index = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderConfig:init()
|
function ReaderConfig:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowConfigMenu = { { "AA" }, doc = _("show config dialog") },
|
ShowConfigMenu = { { "AA" }, doc = _("show config dialog") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:initGesListener()
|
function ReaderConfig:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapShowConfigMenu = {
|
TapShowConfigMenu = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_CONFIG.x,
|
x = Screen:getWidth()*DTAP_ZONE_CONFIG.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_CONFIG.y,
|
y = Screen:getHeight()*DTAP_ZONE_CONFIG.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_CONFIG.w,
|
w = Screen:getWidth()*DTAP_ZONE_CONFIG.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_CONFIG.h,
|
h = Screen:getHeight()*DTAP_ZONE_CONFIG.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onShowConfigMenu()
|
function ReaderConfig:onShowConfigMenu()
|
||||||
self.config_dialog = ConfigDialog:new{
|
self.config_dialog = ConfigDialog:new{
|
||||||
dimen = self.dimen:copy(),
|
dimen = self.dimen:copy(),
|
||||||
ui = self.ui,
|
ui = self.ui,
|
||||||
configurable = self.configurable,
|
configurable = self.configurable,
|
||||||
config_options = self.options,
|
config_options = self.options,
|
||||||
is_always_active = true,
|
is_always_active = true,
|
||||||
close_callback = function() self:onCloseCallback() end,
|
close_callback = function() self:onCloseCallback() end,
|
||||||
}
|
}
|
||||||
self.ui:handleEvent(Event:new("DisableHinting"))
|
self.ui:handleEvent(Event:new("DisableHinting"))
|
||||||
-- show last used panel when opening config dialog
|
-- show last used panel when opening config dialog
|
||||||
self.config_dialog:onShowConfigPanel(self.last_panel_index)
|
self.config_dialog:onShowConfigPanel(self.last_panel_index)
|
||||||
UIManager:show(self.config_dialog)
|
UIManager:show(self.config_dialog)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onTapShowConfigMenu()
|
function ReaderConfig:onTapShowConfigMenu()
|
||||||
self:onShowConfigMenu()
|
self:onShowConfigMenu()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onSetDimensions(dimen)
|
function ReaderConfig:onSetDimensions(dimen)
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
-- since we cannot redraw config_dialog with new size, we close
|
-- since we cannot redraw config_dialog with new size, we close
|
||||||
-- the old one on screen size change
|
-- the old one on screen size change
|
||||||
if self.config_dialog then
|
if self.config_dialog then
|
||||||
self.config_dialog:closeDialog()
|
self.config_dialog:closeDialog()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onCloseCallback()
|
function ReaderConfig:onCloseCallback()
|
||||||
self.last_panel_index = self.config_dialog.panel_index
|
self.last_panel_index = self.config_dialog.panel_index
|
||||||
self.ui:handleEvent(Event:new("RestoreHinting"))
|
self.ui:handleEvent(Event:new("RestoreHinting"))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- event handler for readercropping
|
-- event handler for readercropping
|
||||||
function ReaderConfig:onCloseConfig()
|
function ReaderConfig:onCloseConfig()
|
||||||
self.config_dialog:closeDialog()
|
self.config_dialog:closeDialog()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onReadSettings(config)
|
function ReaderConfig:onReadSettings(config)
|
||||||
self.configurable:loadSettings(config, self.options.prefix.."_")
|
self.configurable:loadSettings(config, self.options.prefix.."_")
|
||||||
self.last_panel_index = config:readSetting("config_panel_index") or 1
|
self.last_panel_index = config:readSetting("config_panel_index") or 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderConfig:onSaveSettings()
|
function ReaderConfig:onSaveSettings()
|
||||||
self.configurable:saveSettings(self.ui.doc_settings, self.options.prefix.."_")
|
self.configurable:saveSettings(self.ui.doc_settings, self.options.prefix.."_")
|
||||||
self.ui.doc_settings:saveSetting("config_panel_index", self.last_panel_index)
|
self.ui.doc_settings:saveSetting("config_panel_index", self.last_panel_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderConfig
|
return ReaderConfig
|
||||||
|
|||||||
@@ -4,29 +4,29 @@ local Event = require("ui/event")
|
|||||||
local ReaderCoptListener = EventListener:new{}
|
local ReaderCoptListener = EventListener:new{}
|
||||||
|
|
||||||
function ReaderCoptListener:onReadSettings(config)
|
function ReaderCoptListener:onReadSettings(config)
|
||||||
local embedded_css = config:readSetting("copt_embedded_css")
|
local embedded_css = config:readSetting("copt_embedded_css")
|
||||||
local toggle_embedded_css = embedded_css == 0 and false or true
|
local toggle_embedded_css = embedded_css == 0 and false or true
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self.ui:handleEvent(Event:new("ToggleEmbeddedStyleSheet", toggle_embedded_css))
|
self.ui:handleEvent(Event:new("ToggleEmbeddedStyleSheet", toggle_embedded_css))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local view_mode = config:readSetting("copt_view_mode")
|
local view_mode = config:readSetting("copt_view_mode")
|
||||||
if view_mode == 0 then
|
if view_mode == 0 then
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self.ui:handleEvent(Event:new("SetViewMode", "page"))
|
self.ui:handleEvent(Event:new("SetViewMode", "page"))
|
||||||
end)
|
end)
|
||||||
elseif view_mode == 1 then
|
elseif view_mode == 1 then
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self.ui:handleEvent(Event:new("SetViewMode", "scroll"))
|
self.ui:handleEvent(Event:new("SetViewMode", "scroll"))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local status_line = config:readSetting("copt_status_line") or DCREREADER_PROGRESS_BAR
|
local status_line = config:readSetting("copt_status_line") or DCREREADER_PROGRESS_BAR
|
||||||
self.document:setStatusLineProp(status_line)
|
self.document:setStatusLineProp(status_line)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCoptListener:onSetFontSize(font_size)
|
function ReaderCoptListener:onSetFontSize(font_size)
|
||||||
self.document.configurable.font_size = font_size
|
self.document.configurable.font_size = font_size
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderCoptListener
|
return ReaderCoptListener
|
||||||
|
|||||||
@@ -15,149 +15,149 @@ local Math = require("optmath")
|
|||||||
local DEBUG = require("dbg")
|
local DEBUG = require("dbg")
|
||||||
|
|
||||||
local PageCropDialog = VerticalGroup:new{
|
local PageCropDialog = VerticalGroup:new{
|
||||||
ok_text = "OK",
|
ok_text = "OK",
|
||||||
cancel_text = "Cancel",
|
cancel_text = "Cancel",
|
||||||
ok_callback = function() end,
|
ok_callback = function() end,
|
||||||
cancel_callback = function() end,
|
cancel_callback = function() end,
|
||||||
button_width = math.floor(Screen:scaleByDPI(70)),
|
button_width = math.floor(Screen:scaleByDPI(70)),
|
||||||
}
|
}
|
||||||
|
|
||||||
function PageCropDialog:init()
|
function PageCropDialog:init()
|
||||||
local horizontal_group = HorizontalGroup:new{}
|
local horizontal_group = HorizontalGroup:new{}
|
||||||
local ok_button = Button:new{
|
local ok_button = Button:new{
|
||||||
text = self.ok_text,
|
text = self.ok_text,
|
||||||
callback = self.ok_callback,
|
callback = self.ok_callback,
|
||||||
width = self.button_width,
|
width = self.button_width,
|
||||||
bordersize = 2,
|
bordersize = 2,
|
||||||
radius = 7,
|
radius = 7,
|
||||||
text_font_face = "cfont",
|
text_font_face = "cfont",
|
||||||
text_font_size = 20,
|
text_font_size = 20,
|
||||||
}
|
}
|
||||||
local cancel_button = Button:new{
|
local cancel_button = Button:new{
|
||||||
text = self.cancel_text,
|
text = self.cancel_text,
|
||||||
callback = self.cancel_callback,
|
callback = self.cancel_callback,
|
||||||
width = self.button_width,
|
width = self.button_width,
|
||||||
bordersize = 2,
|
bordersize = 2,
|
||||||
radius = 7,
|
radius = 7,
|
||||||
text_font_face = "cfont",
|
text_font_face = "cfont",
|
||||||
text_font_size = 20,
|
text_font_size = 20,
|
||||||
}
|
}
|
||||||
local ok_container = RightContainer:new{
|
local ok_container = RightContainer:new{
|
||||||
dimen = Geom:new{ w = Screen:getWidth()*0.33, h = Screen:getHeight()/12},
|
dimen = Geom:new{ w = Screen:getWidth()*0.33, h = Screen:getHeight()/12},
|
||||||
ok_button,
|
ok_button,
|
||||||
}
|
}
|
||||||
local cancel_container = LeftContainer:new{
|
local cancel_container = LeftContainer:new{
|
||||||
dimen = Geom:new{ w = Screen:getWidth()*0.33, h = Screen:getHeight()/12},
|
dimen = Geom:new{ w = Screen:getWidth()*0.33, h = Screen:getHeight()/12},
|
||||||
cancel_button,
|
cancel_button,
|
||||||
}
|
}
|
||||||
table.insert(horizontal_group, ok_container)
|
table.insert(horizontal_group, ok_container)
|
||||||
table.insert(horizontal_group, HorizontalSpan:new{ width = Screen:getWidth()*0.34})
|
table.insert(horizontal_group, HorizontalSpan:new{ width = Screen:getWidth()*0.34})
|
||||||
table.insert(horizontal_group, cancel_container)
|
table.insert(horizontal_group, cancel_container)
|
||||||
self[2] = FrameContainer:new{
|
self[2] = FrameContainer:new{
|
||||||
horizontal_group,
|
horizontal_group,
|
||||||
background = 0,
|
background = 0,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local ReaderCropping = InputContainer:new{}
|
local ReaderCropping = InputContainer:new{}
|
||||||
|
|
||||||
function ReaderCropping:onPageCrop(mode)
|
function ReaderCropping:onPageCrop(mode)
|
||||||
if mode == "auto" then return end
|
if mode == "auto" then return end
|
||||||
self.ui:handleEvent(Event:new("CloseConfig"))
|
self.ui:handleEvent(Event:new("CloseConfig"))
|
||||||
-- backup original view dimen
|
-- backup original view dimen
|
||||||
self.orig_view_dimen = Geom:new{w = self.view.dimen.w, h = self.view.dimen.h}
|
self.orig_view_dimen = Geom:new{w = self.view.dimen.w, h = self.view.dimen.h}
|
||||||
-- backup original view bgcolor
|
-- backup original view bgcolor
|
||||||
self.orig_view_bgcolor = self.view.outer_page_color
|
self.orig_view_bgcolor = self.view.outer_page_color
|
||||||
self.view.outer_page_color = 7 -- gray bgcolor
|
self.view.outer_page_color = 7 -- gray bgcolor
|
||||||
-- backup original zoom mode as cropping use "page" zoom mode
|
-- backup original zoom mode as cropping use "page" zoom mode
|
||||||
self.orig_zoom_mode = self.view.zoom_mode
|
self.orig_zoom_mode = self.view.zoom_mode
|
||||||
-- backup original page scroll
|
-- backup original page scroll
|
||||||
self.orig_page_scroll = self.view.page_scroll
|
self.orig_page_scroll = self.view.page_scroll
|
||||||
self.view.page_scroll = false
|
self.view.page_scroll = false
|
||||||
-- backup and disable original hinting state
|
-- backup and disable original hinting state
|
||||||
self.ui:handleEvent(Event:new("DisableHinting"))
|
self.ui:handleEvent(Event:new("DisableHinting"))
|
||||||
-- backup original reflow mode as cropping use non-reflow mode
|
-- backup original reflow mode as cropping use non-reflow mode
|
||||||
self.orig_reflow_mode = self.document.configurable.text_wrap
|
self.orig_reflow_mode = self.document.configurable.text_wrap
|
||||||
if self.orig_reflow_mode == 1 then
|
if self.orig_reflow_mode == 1 then
|
||||||
self.document.configurable.text_wrap = 0
|
self.document.configurable.text_wrap = 0
|
||||||
-- if we are in reflow mode, then we are already in page
|
-- if we are in reflow mode, then we are already in page
|
||||||
-- mode, just force readerview to recalculate visible_area
|
-- mode, just force readerview to recalculate visible_area
|
||||||
self.view:recalculate()
|
self.view:recalculate()
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", "page", "cropping"))
|
self.ui:handleEvent(Event:new("SetZoomMode", "page", "cropping"))
|
||||||
end
|
end
|
||||||
self.ui:handleEvent(Event:new("SetDimensions",
|
self.ui:handleEvent(Event:new("SetDimensions",
|
||||||
Geom:new{w = Screen:getWidth(), h = Screen:getHeight()*11/12})
|
Geom:new{w = Screen:getWidth(), h = Screen:getHeight()*11/12})
|
||||||
)
|
)
|
||||||
self.bbox_widget = BBoxWidget:new{
|
self.bbox_widget = BBoxWidget:new{
|
||||||
crop = self,
|
crop = self,
|
||||||
ui = self.ui,
|
ui = self.ui,
|
||||||
view = self.view,
|
view = self.view,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
}
|
}
|
||||||
self.crop_dialog = PageCropDialog:new{
|
self.crop_dialog = PageCropDialog:new{
|
||||||
self.bbox_widget,
|
self.bbox_widget,
|
||||||
ok_callback = function() self:onConfirmPageCrop() end,
|
ok_callback = function() self:onConfirmPageCrop() end,
|
||||||
cancel_callback = function() self:onCancelPageCrop() end,
|
cancel_callback = function() self:onCancelPageCrop() end,
|
||||||
}
|
}
|
||||||
UIManager:show(self.crop_dialog)
|
UIManager:show(self.crop_dialog)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCropping:onConfirmPageCrop()
|
function ReaderCropping:onConfirmPageCrop()
|
||||||
--DEBUG("new bbox", new_bbox)
|
--DEBUG("new bbox", new_bbox)
|
||||||
UIManager:close(self.crop_dialog)
|
UIManager:close(self.crop_dialog)
|
||||||
local new_bbox = self.bbox_widget:getModifiedPageBBox()
|
local new_bbox = self.bbox_widget:getModifiedPageBBox()
|
||||||
self.ui:handleEvent(Event:new("BBoxUpdate", new_bbox))
|
self.ui:handleEvent(Event:new("BBoxUpdate", new_bbox))
|
||||||
local pageno = self.view.state.page
|
local pageno = self.view.state.page
|
||||||
self.document.bbox[pageno] = new_bbox
|
self.document.bbox[pageno] = new_bbox
|
||||||
self.document.bbox[Math.oddEven(pageno)] = new_bbox
|
self.document.bbox[Math.oddEven(pageno)] = new_bbox
|
||||||
self:exitPageCrop(true)
|
self:exitPageCrop(true)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCropping:onCancelPageCrop()
|
function ReaderCropping:onCancelPageCrop()
|
||||||
UIManager:close(self.crop_dialog)
|
UIManager:close(self.crop_dialog)
|
||||||
self:exitPageCrop(false)
|
self:exitPageCrop(false)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCropping:exitPageCrop(confirmed)
|
function ReaderCropping:exitPageCrop(confirmed)
|
||||||
-- restore hinting state
|
-- restore hinting state
|
||||||
self.ui:handleEvent(Event:new("RestoreHinting"))
|
self.ui:handleEvent(Event:new("RestoreHinting"))
|
||||||
-- restore page scroll
|
-- restore page scroll
|
||||||
self.view.page_scroll = self.orig_page_scroll
|
self.view.page_scroll = self.orig_page_scroll
|
||||||
-- restore view bgcolor
|
-- restore view bgcolor
|
||||||
self.view.outer_page_color = self.orig_view_bgcolor
|
self.view.outer_page_color = self.orig_view_bgcolor
|
||||||
-- restore reflow mode
|
-- restore reflow mode
|
||||||
self.document.configurable.text_wrap = self.orig_reflow_mode
|
self.document.configurable.text_wrap = self.orig_reflow_mode
|
||||||
-- restore view dimens
|
-- restore view dimens
|
||||||
self.ui:handleEvent(Event:new("RestoreDimensions", self.orig_view_dimen))
|
self.ui:handleEvent(Event:new("RestoreDimensions", self.orig_view_dimen))
|
||||||
self.view:recalculate()
|
self.view:recalculate()
|
||||||
-- Exiting should have the same look and feel with entering.
|
-- Exiting should have the same look and feel with entering.
|
||||||
if self.orig_reflow_mode == 1 then
|
if self.orig_reflow_mode == 1 then
|
||||||
self.ui:handleEvent(Event:new("RestoreZoomMode"))
|
self.ui:handleEvent(Event:new("RestoreZoomMode"))
|
||||||
else
|
else
|
||||||
if confirmed then
|
if confirmed then
|
||||||
-- if original zoom mode is not "content", set zoom mode to "contentwidth"
|
-- if original zoom mode is not "content", set zoom mode to "contentwidth"
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode",
|
self.ui:handleEvent(Event:new("SetZoomMode",
|
||||||
self.orig_zoom_mode:find("content") and self.orig_zoom_mode or "contentwidth"))
|
self.orig_zoom_mode:find("content") and self.orig_zoom_mode or "contentwidth"))
|
||||||
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode))
|
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCropping:onReadSettings(config)
|
function ReaderCropping:onReadSettings(config)
|
||||||
self.document.bbox = config:readSetting("bbox")
|
self.document.bbox = config:readSetting("bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderCropping:onSaveSettings()
|
function ReaderCropping:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("bbox", self.document.bbox)
|
self.ui.doc_settings:saveSetting("bbox", self.document.bbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderCropping
|
return ReaderCropping
|
||||||
|
|||||||
@@ -9,69 +9,69 @@ local DEBUG = require("dbg")
|
|||||||
local ReaderDictionary = EventListener:new{}
|
local ReaderDictionary = EventListener:new{}
|
||||||
|
|
||||||
function ReaderDictionary:onLookupWord(highlight, word, box)
|
function ReaderDictionary:onLookupWord(highlight, word, box)
|
||||||
self.highlight = highlight
|
self.highlight = highlight
|
||||||
self:stardictLookup(word, box)
|
self:stardictLookup(word, box)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDictionary:stardictLookup(word, box)
|
function ReaderDictionary:stardictLookup(word, box)
|
||||||
DEBUG("lookup word:", word, box)
|
DEBUG("lookup word:", word, box)
|
||||||
if word then
|
if word then
|
||||||
-- strip punctuation characters around selected word
|
-- strip punctuation characters around selected word
|
||||||
word = string.gsub(word, "^%p+", '')
|
word = string.gsub(word, "^%p+", '')
|
||||||
word = string.gsub(word, "%p+$", '')
|
word = string.gsub(word, "%p+$", '')
|
||||||
DEBUG("stripped word:", word)
|
DEBUG("stripped word:", word)
|
||||||
-- escape quotes and other funny characters in word
|
-- escape quotes and other funny characters in word
|
||||||
local std_out = io.popen("./sdcv --utf8-input --utf8-output -nj "..("%q"):format(word), "r")
|
local std_out = io.popen("./sdcv --utf8-input --utf8-output -nj "..("%q"):format(word), "r")
|
||||||
local results_str = nil
|
local results_str = nil
|
||||||
if std_out then results_str = std_out:read("*all") end
|
if std_out then results_str = std_out:read("*all") end
|
||||||
if results_str then
|
if results_str then
|
||||||
--DEBUG("result str:", word, results_str)
|
--DEBUG("result str:", word, results_str)
|
||||||
local ok, results = pcall(JSON.decode, JSON, results_str)
|
local ok, results = pcall(JSON.decode, JSON, results_str)
|
||||||
--DEBUG("lookup result table:", word, results)
|
--DEBUG("lookup result table:", word, results)
|
||||||
self:showDict(results, box)
|
self:showDict(results, box)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDictionary:showDict(results, box)
|
function ReaderDictionary:showDict(results, box)
|
||||||
if results and results[1] and box then
|
if results and results[1] and box then
|
||||||
DEBUG("showing quick lookup dictionary window")
|
DEBUG("showing quick lookup dictionary window")
|
||||||
local align = nil
|
local align = nil
|
||||||
local region = Geom:new{x = 0, w = Screen:getWidth()}
|
local region = Geom:new{x = 0, w = Screen:getWidth()}
|
||||||
if box.y + box.h/2 < Screen:getHeight()/2 then
|
if box.y + box.h/2 < Screen:getHeight()/2 then
|
||||||
region.y = box.y + box.h
|
region.y = box.y + box.h
|
||||||
region.h = Screen:getHeight() - box.y - box.h
|
region.h = Screen:getHeight() - box.y - box.h
|
||||||
align = "top"
|
align = "top"
|
||||||
else
|
else
|
||||||
region.y = 0
|
region.y = 0
|
||||||
region.h = box.y
|
region.h = box.y
|
||||||
align = "bottom"
|
align = "bottom"
|
||||||
end
|
end
|
||||||
UIManager:show(DictQuickLookup:new{
|
UIManager:show(DictQuickLookup:new{
|
||||||
ui = self.ui,
|
ui = self.ui,
|
||||||
highlight = self.highlight,
|
highlight = self.highlight,
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
results = results,
|
results = results,
|
||||||
dictionary = self.default_dictionary,
|
dictionary = self.default_dictionary,
|
||||||
width = Screen:getWidth() - Screen:scaleByDPI(80),
|
width = Screen:getWidth() - Screen:scaleByDPI(80),
|
||||||
height = math.min(region.h*0.7, Screen:getHeight()*0.5),
|
height = math.min(region.h*0.7, Screen:getHeight()*0.5),
|
||||||
region = region,
|
region = region,
|
||||||
align = align,
|
align = align,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDictionary:onUpdateDefaultDict(dict)
|
function ReaderDictionary:onUpdateDefaultDict(dict)
|
||||||
DEBUG("make default dictionary:", dict)
|
DEBUG("make default dictionary:", dict)
|
||||||
self.default_dictionary = dict
|
self.default_dictionary = dict
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDictionary:onReadSettings(config)
|
function ReaderDictionary:onReadSettings(config)
|
||||||
self.default_dictionary = config:readSetting("default_dictionary")
|
self.default_dictionary = config:readSetting("default_dictionary")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDictionary:onSaveSettings()
|
function ReaderDictionary:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("default_dictionary", self.default_dictionary)
|
self.ui.doc_settings:saveSetting("default_dictionary", self.default_dictionary)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderDictionary
|
return ReaderDictionary
|
||||||
|
|||||||
@@ -11,54 +11,54 @@ local Event = require("ui/event")
|
|||||||
local ReaderDogear = InputContainer:new{}
|
local ReaderDogear = InputContainer:new{}
|
||||||
|
|
||||||
function ReaderDogear:init()
|
function ReaderDogear:init()
|
||||||
local widget = ImageWidget:new{
|
local widget = ImageWidget:new{
|
||||||
file = "resources/icons/dogear.png",
|
file = "resources/icons/dogear.png",
|
||||||
}
|
}
|
||||||
self[1] = RightContainer:new{
|
self[1] = RightContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth(), h = widget:getSize().h},
|
dimen = Geom:new{w = Screen:getWidth(), h = widget:getSize().h},
|
||||||
widget,
|
widget,
|
||||||
}
|
}
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Tap = {
|
Tap = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_BOOKMARK.x,
|
x = Screen:getWidth()*DTAP_ZONE_BOOKMARK.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_BOOKMARK.y,
|
y = Screen:getHeight()*DTAP_ZONE_BOOKMARK.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_BOOKMARK.w,
|
w = Screen:getWidth()*DTAP_ZONE_BOOKMARK.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_BOOKMARK.h
|
h = Screen:getHeight()*DTAP_ZONE_BOOKMARK.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Hold = {
|
Hold = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold",
|
ges = "hold",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_BOOKMARK.x,
|
x = Screen:getWidth()*DTAP_ZONE_BOOKMARK.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_BOOKMARK.y,
|
y = Screen:getHeight()*DTAP_ZONE_BOOKMARK.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_BOOKMARK.w,
|
w = Screen:getWidth()*DTAP_ZONE_BOOKMARK.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_BOOKMARK.h
|
h = Screen:getHeight()*DTAP_ZONE_BOOKMARK.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDogear:onTap()
|
function ReaderDogear:onTap()
|
||||||
self.ui:handleEvent(Event:new("ToggleBookmark"))
|
self.ui:handleEvent(Event:new("ToggleBookmark"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDogear:onHold()
|
function ReaderDogear:onHold()
|
||||||
self.ui:handleEvent(Event:new("ToggleBookmarkFlipping"))
|
self.ui:handleEvent(Event:new("ToggleBookmarkFlipping"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderDogear:onSetDogearVisibility(visible)
|
function ReaderDogear:onSetDogearVisibility(visible)
|
||||||
self.view.dogear_visible = visible
|
self.view.dogear_visible = visible
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderDogear
|
return ReaderDogear
|
||||||
|
|||||||
@@ -8,37 +8,37 @@ local Screen = require("ui/screen")
|
|||||||
local Event = require("ui/event")
|
local Event = require("ui/event")
|
||||||
|
|
||||||
local ReaderFlipping = InputContainer:new{
|
local ReaderFlipping = InputContainer:new{
|
||||||
orig_reflow_mode = 0,
|
orig_reflow_mode = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderFlipping:init()
|
function ReaderFlipping:init()
|
||||||
local widget = ImageWidget:new{
|
local widget = ImageWidget:new{
|
||||||
file = "resources/icons/appbar.book.open.png",
|
file = "resources/icons/appbar.book.open.png",
|
||||||
}
|
}
|
||||||
self[1] = LeftContainer:new{
|
self[1] = LeftContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth(), h = widget:getSize().h},
|
dimen = Geom:new{w = Screen:getWidth(), h = widget:getSize().h},
|
||||||
widget,
|
widget,
|
||||||
}
|
}
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Tap = {
|
Tap = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_FLIPPING.x,
|
x = Screen:getWidth()*DTAP_ZONE_FLIPPING.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_FLIPPING.y,
|
y = Screen:getHeight()*DTAP_ZONE_FLIPPING.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_FLIPPING.w,
|
w = Screen:getWidth()*DTAP_ZONE_FLIPPING.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_FLIPPING.h
|
h = Screen:getHeight()*DTAP_ZONE_FLIPPING.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFlipping:onTap()
|
function ReaderFlipping:onTap()
|
||||||
self.ui:handleEvent(Event:new("TogglePageFlipping"))
|
self.ui:handleEvent(Event:new("TogglePageFlipping"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderFlipping
|
return ReaderFlipping
|
||||||
|
|||||||
@@ -12,220 +12,220 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderFont = InputContainer:new{
|
local ReaderFont = InputContainer:new{
|
||||||
font_face = nil,
|
font_face = nil,
|
||||||
font_size = nil,
|
font_size = nil,
|
||||||
line_space_percent = nil,
|
line_space_percent = nil,
|
||||||
font_menu_title = _("Change font"),
|
font_menu_title = _("Change font"),
|
||||||
face_table = nil,
|
face_table = nil,
|
||||||
-- default gamma from crengine's lvfntman.cpp
|
-- default gamma from crengine's lvfntman.cpp
|
||||||
gamma_index = nil,
|
gamma_index = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderFont:init()
|
function ReaderFont:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
-- add shortcut for keyboard
|
-- add shortcut for keyboard
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowFontMenu = { {"F"}, doc = _("show font menu") },
|
ShowFontMenu = { {"F"}, doc = _("show font menu") },
|
||||||
IncreaseSize = {
|
IncreaseSize = {
|
||||||
{ "Shift", Input.group.PgFwd },
|
{ "Shift", Input.group.PgFwd },
|
||||||
doc = _("increase font size"),
|
doc = _("increase font size"),
|
||||||
event = "ChangeSize", args = "increase" },
|
event = "ChangeSize", args = "increase" },
|
||||||
DecreaseSize = {
|
DecreaseSize = {
|
||||||
{ "Shift", Input.group.PgBack },
|
{ "Shift", Input.group.PgBack },
|
||||||
doc = _("decrease font size"),
|
doc = _("decrease font size"),
|
||||||
event = "ChangeSize", args = "decrease" },
|
event = "ChangeSize", args = "decrease" },
|
||||||
IncreaseLineSpace = {
|
IncreaseLineSpace = {
|
||||||
{ "Alt", Input.group.PgFwd },
|
{ "Alt", Input.group.PgFwd },
|
||||||
doc = _("increase line space"),
|
doc = _("increase line space"),
|
||||||
event = "ChangeLineSpace", args = "increase" },
|
event = "ChangeLineSpace", args = "increase" },
|
||||||
DecreaseLineSpace = {
|
DecreaseLineSpace = {
|
||||||
{ "Alt", Input.group.PgBack },
|
{ "Alt", Input.group.PgBack },
|
||||||
doc = _("decrease line space"),
|
doc = _("decrease line space"),
|
||||||
event = "ChangeLineSpace", args = "decrease" },
|
event = "ChangeLineSpace", args = "decrease" },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
-- build face_table for menu
|
-- build face_table for menu
|
||||||
self.face_table = {}
|
self.face_table = {}
|
||||||
local face_list = cre.getFontFaces()
|
local face_list = cre.getFontFaces()
|
||||||
for k,v in ipairs(face_list) do
|
for k,v in ipairs(face_list) do
|
||||||
table.insert(self.face_table, {
|
table.insert(self.face_table, {
|
||||||
text = v,
|
text = v,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:setFont(v)
|
self:setFont(v)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
face_list[k] = {text = v}
|
face_list[k] = {text = v}
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onSetDimensions(dimen)
|
function ReaderFont:onSetDimensions(dimen)
|
||||||
self.dimen = dimen
|
self.dimen = dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onReadSettings(config)
|
function ReaderFont:onReadSettings(config)
|
||||||
self.font_face = config:readSetting("font_face")
|
self.font_face = config:readSetting("font_face")
|
||||||
if not self.font_face then
|
if not self.font_face then
|
||||||
self.font_face = self.ui.document.default_font
|
self.font_face = self.ui.document.default_font
|
||||||
end
|
end
|
||||||
self.ui.document:setFontFace(self.font_face)
|
self.ui.document:setFontFace(self.font_face)
|
||||||
|
|
||||||
self.header_font_face = config:readSetting("header_font_face")
|
self.header_font_face = config:readSetting("header_font_face")
|
||||||
if not self.header_font_face then
|
if not self.header_font_face then
|
||||||
self.header_font_face = self.ui.document.header_font
|
self.header_font_face = self.ui.document.header_font
|
||||||
end
|
end
|
||||||
self.ui.document:setHeaderFont(self.header_font_face)
|
self.ui.document:setHeaderFont(self.header_font_face)
|
||||||
|
|
||||||
self.font_size = config:readSetting("font_size")
|
self.font_size = config:readSetting("font_size")
|
||||||
if not self.font_size then
|
if not self.font_size then
|
||||||
--@TODO change this! 12.01 2013 (houqp)
|
--@TODO change this! 12.01 2013 (houqp)
|
||||||
self.font_size = DCREREADER_CONFIG_DEFAULT_FONT_SIZE
|
self.font_size = DCREREADER_CONFIG_DEFAULT_FONT_SIZE
|
||||||
end
|
end
|
||||||
self.ui.document:setFontSize(Screen:scaleByDPI(self.font_size))
|
self.ui.document:setFontSize(Screen:scaleByDPI(self.font_size))
|
||||||
|
|
||||||
self.line_space_percent = config:readSetting("line_space_percent")
|
self.line_space_percent = config:readSetting("line_space_percent")
|
||||||
if not self.line_space_percent then
|
if not self.line_space_percent then
|
||||||
self.line_space_percent = 100
|
self.line_space_percent = 100
|
||||||
else
|
else
|
||||||
self.ui.document:setInterlineSpacePercent(self.line_space_percent)
|
self.ui.document:setInterlineSpacePercent(self.line_space_percent)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.gamma_index = config:readSetting("gamma_index")
|
self.gamma_index = config:readSetting("gamma_index")
|
||||||
if not self.gamma_index then
|
if not self.gamma_index then
|
||||||
self.gamma_index = 15
|
self.gamma_index = 15
|
||||||
end
|
end
|
||||||
self.ui.document:setGammaIndex(self.gamma_index)
|
self.ui.document:setGammaIndex(self.gamma_index)
|
||||||
|
|
||||||
-- Dirty hack: we have to add folloing call in order to set
|
-- Dirty hack: we have to add folloing call in order to set
|
||||||
-- m_is_rendered(member of LVDocView) to true. Otherwise position inside
|
-- m_is_rendered(member of LVDocView) to true. Otherwise position inside
|
||||||
-- document will be reset to 0 on first view render.
|
-- document will be reset to 0 on first view render.
|
||||||
-- So far, I don't know why this call will alter the value of m_is_rendered.
|
-- So far, I don't know why this call will alter the value of m_is_rendered.
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onShowFontMenu()
|
function ReaderFont:onShowFontMenu()
|
||||||
-- build menu widget
|
-- build menu widget
|
||||||
local main_menu = Menu:new{
|
local main_menu = Menu:new{
|
||||||
title = self.font_menu_title,
|
title = self.font_menu_title,
|
||||||
item_table = self.face_table,
|
item_table = self.face_table,
|
||||||
width = Screen:getWidth() - 100,
|
width = Screen:getWidth() - 100,
|
||||||
}
|
}
|
||||||
-- build container
|
-- build container
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
main_menu,
|
main_menu,
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
main_menu.close_callback = function ()
|
main_menu.close_callback = function ()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
-- show menu
|
-- show menu
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
UpdatePos event is used to tell ReaderRolling to update pos.
|
UpdatePos event is used to tell ReaderRolling to update pos.
|
||||||
--]]
|
--]]
|
||||||
function ReaderFont:onChangeSize(direction)
|
function ReaderFont:onChangeSize(direction)
|
||||||
local delta = direction == "decrease" and -1 or 1
|
local delta = direction == "decrease" and -1 or 1
|
||||||
self.font_size = self.font_size + delta
|
self.font_size = self.font_size + delta
|
||||||
self.ui:handleEvent(Event:new("SetFontSize", self.font_size))
|
self.ui:handleEvent(Event:new("SetFontSize", self.font_size))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onSetFontSize(new_size)
|
function ReaderFont:onSetFontSize(new_size)
|
||||||
if new_size > 72 then new_size = 72 end
|
if new_size > 72 then new_size = 72 end
|
||||||
if new_size < 12 then new_size = 12 end
|
if new_size < 12 then new_size = 12 end
|
||||||
|
|
||||||
self.font_size = new_size
|
self.font_size = new_size
|
||||||
UIManager:show(Notification:new{
|
UIManager:show(Notification:new{
|
||||||
text = _("Set font size to ")..self.font_size,
|
text = _("Set font size to ")..self.font_size,
|
||||||
timeout = 1,
|
timeout = 1,
|
||||||
})
|
})
|
||||||
self.ui.document:setFontSize(Screen:scaleByDPI(new_size))
|
self.ui.document:setFontSize(Screen:scaleByDPI(new_size))
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onChangeLineSpace(direction)
|
function ReaderFont:onChangeLineSpace(direction)
|
||||||
local msg = ""
|
local msg = ""
|
||||||
if direction == "decrease" then
|
if direction == "decrease" then
|
||||||
self.line_space_percent = self.line_space_percent - 10
|
self.line_space_percent = self.line_space_percent - 10
|
||||||
-- NuPogodi, 15.05.12: reduce lowest space_percent to 80
|
-- NuPogodi, 15.05.12: reduce lowest space_percent to 80
|
||||||
self.line_space_percent = math.max(self.line_space_percent, 80)
|
self.line_space_percent = math.max(self.line_space_percent, 80)
|
||||||
msg = _("Decrease line space to ")
|
msg = _("Decrease line space to ")
|
||||||
else
|
else
|
||||||
self.line_space_percent = self.line_space_percent + 10
|
self.line_space_percent = self.line_space_percent + 10
|
||||||
self.line_space_percent = math.min(self.line_space_percent, 200)
|
self.line_space_percent = math.min(self.line_space_percent, 200)
|
||||||
msg = _("Increase line space to ")
|
msg = _("Increase line space to ")
|
||||||
end
|
end
|
||||||
UIManager:show(Notification:new{
|
UIManager:show(Notification:new{
|
||||||
text = msg..self.line_space_percent.."%",
|
text = msg..self.line_space_percent.."%",
|
||||||
timeout = 1,
|
timeout = 1,
|
||||||
})
|
})
|
||||||
self.ui.document:setInterlineSpacePercent(self.line_space_percent)
|
self.ui.document:setInterlineSpacePercent(self.line_space_percent)
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onToggleFontBolder()
|
function ReaderFont:onToggleFontBolder()
|
||||||
self.ui.document:toggleFontBolder()
|
self.ui.document:toggleFontBolder()
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onChangeFontGamma(direction)
|
function ReaderFont:onChangeFontGamma(direction)
|
||||||
local msg = ""
|
local msg = ""
|
||||||
if direction == "increase" then
|
if direction == "increase" then
|
||||||
cre.setGammaIndex(self.gamma_index+2)
|
cre.setGammaIndex(self.gamma_index+2)
|
||||||
msg = _("Increase gamma to ")
|
msg = _("Increase gamma to ")
|
||||||
elseif direction == "decrease" then
|
elseif direction == "decrease" then
|
||||||
cre.setGammaIndex(self.gamma_index-2)
|
cre.setGammaIndex(self.gamma_index-2)
|
||||||
msg = _("Decrease gamma to ")
|
msg = _("Decrease gamma to ")
|
||||||
end
|
end
|
||||||
self.gamma_index = cre.getGammaIndex()
|
self.gamma_index = cre.getGammaIndex()
|
||||||
UIManager:show(Notification:new{
|
UIManager:show(Notification:new{
|
||||||
text = msg..self.gamma_index,
|
text = msg..self.gamma_index,
|
||||||
timeout = 1
|
timeout = 1
|
||||||
})
|
})
|
||||||
self.ui:handleEvent(Event:new("RedrawCurrentView"))
|
self.ui:handleEvent(Event:new("RedrawCurrentView"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:onSaveSettings()
|
function ReaderFont:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("font_face", self.font_face)
|
self.ui.doc_settings:saveSetting("font_face", self.font_face)
|
||||||
self.ui.doc_settings:saveSetting("header_font_face", self.header_font_face)
|
self.ui.doc_settings:saveSetting("header_font_face", self.header_font_face)
|
||||||
self.ui.doc_settings:saveSetting("font_size", self.font_size)
|
self.ui.doc_settings:saveSetting("font_size", self.font_size)
|
||||||
self.ui.doc_settings:saveSetting("line_space_percent", self.line_space_percent)
|
self.ui.doc_settings:saveSetting("line_space_percent", self.line_space_percent)
|
||||||
self.ui.doc_settings:saveSetting("gamma_index", self.gamma_index)
|
self.ui.doc_settings:saveSetting("gamma_index", self.gamma_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:setFont(face)
|
function ReaderFont:setFont(face)
|
||||||
if face and self.font_face ~= face then
|
if face and self.font_face ~= face then
|
||||||
self.font_face = face
|
self.font_face = face
|
||||||
UIManager:show(Notification:new{
|
UIManager:show(Notification:new{
|
||||||
text = _("Redrawing with font ")..face,
|
text = _("Redrawing with font ")..face,
|
||||||
timeout = 1,
|
timeout = 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
self.ui.document:setFontFace(face)
|
self.ui.document:setFontFace(face)
|
||||||
-- signal readerrolling to update pos in new height
|
-- signal readerrolling to update pos in new height
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
|
|
||||||
UIManager:close(msg)
|
UIManager:close(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFont:addToMainMenu(tab_item_table)
|
function ReaderFont:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.typeset, {
|
table.insert(tab_item_table.typeset, {
|
||||||
text = self.font_menu_title,
|
text = self.font_menu_title,
|
||||||
sub_item_table = self.face_table,
|
sub_item_table = self.face_table,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderFont
|
return ReaderFont
|
||||||
|
|||||||
@@ -16,136 +16,136 @@ local Font = require("ui/font")
|
|||||||
local DEBUG = require("dbg")
|
local DEBUG = require("dbg")
|
||||||
|
|
||||||
local ReaderFooter = InputContainer:new{
|
local ReaderFooter = InputContainer:new{
|
||||||
visible = true,
|
visible = true,
|
||||||
pageno = nil,
|
pageno = nil,
|
||||||
pages = nil,
|
pages = nil,
|
||||||
progress_percentage = 0.0,
|
progress_percentage = 0.0,
|
||||||
progress_text = "0 / 0",
|
progress_text = "0 / 0",
|
||||||
show_time = false,
|
show_time = false,
|
||||||
bar_width = 0.85,
|
bar_width = 0.85,
|
||||||
text_width = 0.15,
|
text_width = 0.15,
|
||||||
text_font_face = "ffont",
|
text_font_face = "ffont",
|
||||||
text_font_size = 14,
|
text_font_size = 14,
|
||||||
height = 19,
|
height = 19,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderFooter:init()
|
function ReaderFooter:init()
|
||||||
self.progress_bar = ProgressWidget:new{
|
self.progress_bar = ProgressWidget:new{
|
||||||
width = math.floor(Screen:getWidth()*(self.bar_width-0.02)),
|
width = math.floor(Screen:getWidth()*(self.bar_width-0.02)),
|
||||||
height = 7,
|
height = 7,
|
||||||
percentage = self.progress_percentage,
|
percentage = self.progress_percentage,
|
||||||
}
|
}
|
||||||
self.progress_text = TextWidget:new{
|
self.progress_text = TextWidget:new{
|
||||||
text = self.progress_text,
|
text = self.progress_text,
|
||||||
face = Font:getFace(self.text_font_face, self.text_font_size),
|
face = Font:getFace(self.text_font_face, self.text_font_size),
|
||||||
}
|
}
|
||||||
local _, text_height = self.progress_text:getSize()
|
local _, text_height = self.progress_text:getSize()
|
||||||
local horizontal_group = HorizontalGroup:new{}
|
local horizontal_group = HorizontalGroup:new{}
|
||||||
local bar_container = RightContainer:new{
|
local bar_container = RightContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth()*self.bar_width, h = self.height},
|
dimen = Geom:new{w = Screen:getWidth()*self.bar_width, h = self.height},
|
||||||
self.progress_bar,
|
self.progress_bar,
|
||||||
}
|
}
|
||||||
local text_container = CenterContainer:new{
|
local text_container = CenterContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth()*self.text_width, h = self.height},
|
dimen = Geom:new{w = Screen:getWidth()*self.text_width, h = self.height},
|
||||||
self.progress_text,
|
self.progress_text,
|
||||||
}
|
}
|
||||||
table.insert(horizontal_group, bar_container)
|
table.insert(horizontal_group, bar_container)
|
||||||
table.insert(horizontal_group, text_container)
|
table.insert(horizontal_group, text_container)
|
||||||
self[1] = BottomContainer:new{
|
self[1] = BottomContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
horizontal_group,
|
horizontal_group,
|
||||||
background = 0,
|
background = 0,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.dimen = self[1]:getSize()
|
self.dimen = self[1]:getSize()
|
||||||
self.pageno = self.view.state.page
|
self.pageno = self.view.state.page
|
||||||
self.pages = self.view.document.info.number_of_pages
|
self.pages = self.view.document.info.number_of_pages
|
||||||
self:updateFooterPage()
|
self:updateFooterPage()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapFooter = {
|
TapFooter = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self[1]:contentRange(),
|
range = self[1]:contentRange(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HoldFooter = {
|
HoldFooter = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold",
|
ges = "hold",
|
||||||
range = self[1]:contentRange(),
|
range = self[1]:contentRange(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:updateFooterPage()
|
function ReaderFooter:updateFooterPage()
|
||||||
if type(self.pageno) ~= "number" then return end
|
if type(self.pageno) ~= "number" then return end
|
||||||
self.progress_bar.percentage = self.pageno / self.pages
|
self.progress_bar.percentage = self.pageno / self.pages
|
||||||
|
|
||||||
if self.show_time then
|
if self.show_time then
|
||||||
self.progress_text.text = os.date("%H:%M")
|
self.progress_text.text = os.date("%H:%M")
|
||||||
else
|
else
|
||||||
self.progress_text.text = string.format("%d / %d", self.pageno, self.pages)
|
self.progress_text.text = string.format("%d / %d", self.pageno, self.pages)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:updateFooterPos()
|
function ReaderFooter:updateFooterPos()
|
||||||
if type(self.position) ~= "number" then return end
|
if type(self.position) ~= "number" then return end
|
||||||
self.progress_bar.percentage = self.position / self.doc_height
|
self.progress_bar.percentage = self.position / self.doc_height
|
||||||
|
|
||||||
if self.show_time then
|
if self.show_time then
|
||||||
self.progress_text.text = os.date("%H:%M")
|
self.progress_text.text = os.date("%H:%M")
|
||||||
else
|
else
|
||||||
self.progress_text.text = string.format("%1.f", self.progress_bar.percentage*100).."%"
|
self.progress_text.text = string.format("%1.f", self.progress_bar.percentage*100).."%"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:onPageUpdate(pageno)
|
function ReaderFooter:onPageUpdate(pageno)
|
||||||
self.pageno = pageno
|
self.pageno = pageno
|
||||||
self.pages = self.view.document.info.number_of_pages
|
self.pages = self.view.document.info.number_of_pages
|
||||||
self:updateFooterPage()
|
self:updateFooterPage()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:onPosUpdate(pos)
|
function ReaderFooter:onPosUpdate(pos)
|
||||||
self.position = pos
|
self.position = pos
|
||||||
self.doc_height = self.view.document.info.doc_height
|
self.doc_height = self.view.document.info.doc_height
|
||||||
self:updateFooterPos()
|
self:updateFooterPos()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:onTapFooter(arg, ges)
|
function ReaderFooter:onTapFooter(arg, ges)
|
||||||
if self.view.flipping_visible then
|
if self.view.flipping_visible then
|
||||||
local pos = ges.pos
|
local pos = ges.pos
|
||||||
local dimen = self.progress_bar.dimen
|
local dimen = self.progress_bar.dimen
|
||||||
local percentage = (pos.x - dimen.x)/dimen.w
|
local percentage = (pos.x - dimen.x)/dimen.w
|
||||||
self.ui:handleEvent(Event:new("GotoPercentage", percentage))
|
self.ui:handleEvent(Event:new("GotoPercentage", percentage))
|
||||||
else
|
else
|
||||||
self.show_time = not self.show_time
|
self.show_time = not self.show_time
|
||||||
end
|
end
|
||||||
if self.pageno then
|
if self.pageno then
|
||||||
self:updateFooterPage()
|
self:updateFooterPage()
|
||||||
else
|
else
|
||||||
self:updateFooterPos()
|
self:updateFooterPos()
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.view.dialog, "partial")
|
UIManager:setDirty(self.view.dialog, "partial")
|
||||||
-- consume this tap when footer is visible
|
-- consume this tap when footer is visible
|
||||||
if self.view.footer_visible then
|
if self.view.footer_visible then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:onHoldFooter(arg, ges)
|
function ReaderFooter:onHoldFooter(arg, ges)
|
||||||
self.ui:handleEvent(Event:new("ShowGotoDialog"))
|
self.ui:handleEvent(Event:new("ShowGotoDialog"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderFooter:onSetStatusLine(status_line)
|
function ReaderFooter:onSetStatusLine(status_line)
|
||||||
self.view.footer_visible = status_line == 1 and true or false
|
self.view.footer_visible = status_line == 1 and true or false
|
||||||
self.ui.document:setStatusLineProp(status_line)
|
self.ui.document:setStatusLineProp(status_line)
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderFooter
|
return ReaderFooter
|
||||||
|
|||||||
@@ -7,86 +7,86 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderGoto = InputContainer:new{
|
local ReaderGoto = InputContainer:new{
|
||||||
goto_menu_title = _("Go To"),
|
goto_menu_title = _("Go To"),
|
||||||
goto_dialog_title = _("Go to Page or Location"),
|
goto_dialog_title = _("Go to Page or Location"),
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderGoto:init()
|
function ReaderGoto:init()
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderGoto:addToMainMenu(tab_item_table)
|
function ReaderGoto:addToMainMenu(tab_item_table)
|
||||||
-- insert goto command to main reader menu
|
-- insert goto command to main reader menu
|
||||||
table.insert(tab_item_table.navi, {
|
table.insert(tab_item_table.navi, {
|
||||||
text = self.goto_menu_title,
|
text = self.goto_menu_title,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:onShowGotoDialog()
|
self:onShowGotoDialog()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderGoto:onShowGotoDialog()
|
function ReaderGoto:onShowGotoDialog()
|
||||||
DEBUG("show goto dialog")
|
DEBUG("show goto dialog")
|
||||||
self.goto_dialog = InputDialog:new{
|
self.goto_dialog = InputDialog:new{
|
||||||
title = self.goto_dialog_title,
|
title = self.goto_dialog_title,
|
||||||
input_hint = "(1 - "..self.document:getPageCount()..")",
|
input_hint = "(1 - "..self.document:getPageCount()..")",
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Cancel"),
|
text = _("Cancel"),
|
||||||
enabled = true,
|
enabled = true,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:close()
|
self:close()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Page"),
|
text = _("Page"),
|
||||||
enabled = self.document.info.has_pages,
|
enabled = self.document.info.has_pages,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:gotoPage()
|
self:gotoPage()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Location"),
|
text = _("Location"),
|
||||||
enabled = not self.document.info.has_pages,
|
enabled = not self.document.info.has_pages,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:gotoLocation()
|
self:gotoLocation()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
input_type = "number",
|
input_type = "number",
|
||||||
enter_callback = self.document.info.has_pages
|
enter_callback = self.document.info.has_pages
|
||||||
and function() self:gotoPage() end
|
and function() self:gotoPage() end
|
||||||
or function() self:gotoLocation() end,
|
or function() self:gotoLocation() end,
|
||||||
width = Screen:getWidth() * 0.8,
|
width = Screen:getWidth() * 0.8,
|
||||||
height = Screen:getHeight() * 0.2,
|
height = Screen:getHeight() * 0.2,
|
||||||
}
|
}
|
||||||
self.goto_dialog:onShowKeyboard()
|
self.goto_dialog:onShowKeyboard()
|
||||||
UIManager:show(self.goto_dialog)
|
UIManager:show(self.goto_dialog)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderGoto:close()
|
function ReaderGoto:close()
|
||||||
self.goto_dialog:onClose()
|
self.goto_dialog:onClose()
|
||||||
UIManager:close(self.goto_dialog)
|
UIManager:close(self.goto_dialog)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderGoto:gotoPage()
|
function ReaderGoto:gotoPage()
|
||||||
local number = tonumber(self.goto_dialog:getInputText())
|
local number = tonumber(self.goto_dialog:getInputText())
|
||||||
if number then
|
if number then
|
||||||
self.ui:handleEvent(Event:new("GotoPage", number))
|
self.ui:handleEvent(Event:new("GotoPage", number))
|
||||||
end
|
end
|
||||||
self:close()
|
self:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderGoto:gotoLocation()
|
function ReaderGoto:gotoLocation()
|
||||||
local number = tonumber(self.goto_dialog:getInputText())
|
local number = tonumber(self.goto_dialog:getInputText())
|
||||||
if number then
|
if number then
|
||||||
self.ui:handleEvent(Event:new("GotoPage", number))
|
self.ui:handleEvent(Event:new("GotoPage", number))
|
||||||
end
|
end
|
||||||
self:close()
|
self:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderGoto
|
return ReaderGoto
|
||||||
|
|||||||
@@ -12,405 +12,405 @@ local _ = require("gettext")
|
|||||||
local ReaderHighlight = InputContainer:new{}
|
local ReaderHighlight = InputContainer:new{}
|
||||||
|
|
||||||
function ReaderHighlight:init()
|
function ReaderHighlight:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowToc = {
|
ShowToc = {
|
||||||
{ "." },
|
{ "." },
|
||||||
doc = _("highlight text") },
|
doc = _("highlight text") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:initGesListener()
|
function ReaderHighlight:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Tap = {
|
Tap = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()
|
h = Screen:getHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Hold = {
|
Hold = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold",
|
ges = "hold",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()
|
h = Screen:getHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HoldRelease = {
|
HoldRelease = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold_release",
|
ges = "hold_release",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()
|
h = Screen:getHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HoldPan = {
|
HoldPan = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold_pan",
|
ges = "hold_pan",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()
|
h = Screen:getHeight()
|
||||||
},
|
},
|
||||||
rate = 2.0,
|
rate = 2.0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:addToMainMenu(tab_item_table)
|
function ReaderHighlight:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.typeset, {
|
table.insert(tab_item_table.typeset, {
|
||||||
text_func = function()
|
text_func = function()
|
||||||
return _("Set highlight drawer ").."( "..self.view.highlight.saved_drawer.." )"
|
return _("Set highlight drawer ").."( "..self.view.highlight.saved_drawer.." )"
|
||||||
end,
|
end,
|
||||||
sub_item_table = self:genHighlightDrawerMenu(),
|
sub_item_table = self:genHighlightDrawerMenu(),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:genHighlightDrawerMenu()
|
function ReaderHighlight:genHighlightDrawerMenu()
|
||||||
return {
|
return {
|
||||||
{
|
{
|
||||||
text = _("Lighten"),
|
text = _("Lighten"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self.view.highlight.saved_drawer = "lighten"
|
self.view.highlight.saved_drawer = "lighten"
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Underscore"),
|
text = _("Underscore"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self.view.highlight.saved_drawer = "underscore"
|
self.view.highlight.saved_drawer = "underscore"
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Invert"),
|
text = _("Invert"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self.view.highlight.saved_drawer = "invert"
|
self.view.highlight.saved_drawer = "invert"
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onSetDimensions(dimen)
|
function ReaderHighlight:onSetDimensions(dimen)
|
||||||
-- update listening according to new screen dimen
|
-- update listening according to new screen dimen
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onTap(arg, ges)
|
function ReaderHighlight:onTap(arg, ges)
|
||||||
if self.hold_pos then
|
if self.hold_pos then
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
self.view.highlight.temp[self.hold_pos.page] = nil
|
self.view.highlight.temp[self.hold_pos.page] = nil
|
||||||
else
|
else
|
||||||
self.ui.document:clearSelection()
|
self.ui.document:clearSelection()
|
||||||
end
|
end
|
||||||
self.hold_pos = nil
|
self.hold_pos = nil
|
||||||
UIManager:setDirty(self.dialog, "partial")
|
UIManager:setDirty(self.dialog, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
return self:onTapPageSavedHighlight(ges)
|
return self:onTapPageSavedHighlight(ges)
|
||||||
else
|
else
|
||||||
return self:onTapXPointerSavedHighlight(ges)
|
return self:onTapXPointerSavedHighlight(ges)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inside_box(pos, box)
|
local function inside_box(pos, box)
|
||||||
if pos then
|
if pos then
|
||||||
local x, y = pos.x, pos.y
|
local x, y = pos.x, pos.y
|
||||||
if box.x <= x and box.y <= y
|
if box.x <= x and box.y <= y
|
||||||
and box.x + box.w >= x
|
and box.x + box.w >= x
|
||||||
and box.y + box.h >= y then
|
and box.y + box.h >= y then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onTapPageSavedHighlight(ges)
|
function ReaderHighlight:onTapPageSavedHighlight(ges)
|
||||||
local pages = self.view:getCurrentPageList()
|
local pages = self.view:getCurrentPageList()
|
||||||
local pos = self.view:screenToPageTransform(ges.pos)
|
local pos = self.view:screenToPageTransform(ges.pos)
|
||||||
for key, page in pairs(pages) do
|
for key, page in pairs(pages) do
|
||||||
local items = self.view.highlight.saved[page]
|
local items = self.view.highlight.saved[page]
|
||||||
if not items then items = {} end
|
if not items then items = {} end
|
||||||
for i = 1, #items do
|
for i = 1, #items do
|
||||||
local pos0, pos1 = items[i].pos0, items[i].pos1
|
local pos0, pos1 = items[i].pos0, items[i].pos1
|
||||||
local boxes = self.ui.document:getPageBoxesFromPositions(page, pos0, pos1)
|
local boxes = self.ui.document:getPageBoxesFromPositions(page, pos0, pos1)
|
||||||
if boxes then
|
if boxes then
|
||||||
for index, box in pairs(boxes) do
|
for index, box in pairs(boxes) do
|
||||||
if inside_box(pos, box) then
|
if inside_box(pos, box) then
|
||||||
DEBUG("Tap on hightlight")
|
DEBUG("Tap on hightlight")
|
||||||
return self:onShowHighlightDialog(page, i)
|
return self:onShowHighlightDialog(page, i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
||||||
local pos = self.view:screenToPageTransform(ges.pos)
|
local pos = self.view:screenToPageTransform(ges.pos)
|
||||||
for page, _ in pairs(self.view.highlight.saved) do
|
for page, _ in pairs(self.view.highlight.saved) do
|
||||||
local items = self.view.highlight.saved[page]
|
local items = self.view.highlight.saved[page]
|
||||||
if not items then items = {} end
|
if not items then items = {} end
|
||||||
for i = 1, #items do
|
for i = 1, #items do
|
||||||
local pos0, pos1 = items[i].pos0, items[i].pos1
|
local pos0, pos1 = items[i].pos0, items[i].pos1
|
||||||
local boxes = self.ui.document:getScreenBoxesFromPositions(pos0, pos1)
|
local boxes = self.ui.document:getScreenBoxesFromPositions(pos0, pos1)
|
||||||
if boxes then
|
if boxes then
|
||||||
for index, box in pairs(boxes) do
|
for index, box in pairs(boxes) do
|
||||||
if inside_box(pos, box) then
|
if inside_box(pos, box) then
|
||||||
DEBUG("Tap on hightlight")
|
DEBUG("Tap on hightlight")
|
||||||
return self:onShowHighlightDialog(page, i)
|
return self:onShowHighlightDialog(page, i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onShowHighlightDialog(page, index)
|
function ReaderHighlight:onShowHighlightDialog(page, index)
|
||||||
self.edit_highlight_dialog = ButtonDialog:new{
|
self.edit_highlight_dialog = ButtonDialog:new{
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Delete"),
|
text = _("Delete"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:deleteHighlight(page, index)
|
self:deleteHighlight(page, index)
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Edit"),
|
text = _("Edit"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:editHighlight()
|
self:editHighlight()
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
UIManager:show(self.edit_highlight_dialog)
|
UIManager:show(self.edit_highlight_dialog)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onHold(arg, ges)
|
function ReaderHighlight:onHold(arg, ges)
|
||||||
self.hold_pos = self.view:screenToPageTransform(ges.pos)
|
self.hold_pos = self.view:screenToPageTransform(ges.pos)
|
||||||
DEBUG("hold position in page", self.hold_pos)
|
DEBUG("hold position in page", self.hold_pos)
|
||||||
if not self.hold_pos then
|
if not self.hold_pos then
|
||||||
DEBUG("not inside page area")
|
DEBUG("not inside page area")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local ok, word = pcall(self.ui.document.getWordFromPosition, self.ui.document, self.hold_pos)
|
local ok, word = pcall(self.ui.document.getWordFromPosition, self.ui.document, self.hold_pos)
|
||||||
if ok and word then
|
if ok and word then
|
||||||
DEBUG("selected word:", word)
|
DEBUG("selected word:", word)
|
||||||
self.selected_word = word
|
self.selected_word = word
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
local boxes = {}
|
local boxes = {}
|
||||||
table.insert(boxes, self.selected_word.sbox)
|
table.insert(boxes, self.selected_word.sbox)
|
||||||
self.view.highlight.temp[self.hold_pos.page] = boxes
|
self.view.highlight.temp[self.hold_pos.page] = boxes
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.dialog, "partial")
|
UIManager:setDirty(self.dialog, "partial")
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onHoldPan(arg, ges)
|
function ReaderHighlight:onHoldPan(arg, ges)
|
||||||
if self.hold_pos == nil then
|
if self.hold_pos == nil then
|
||||||
DEBUG("no previous hold position")
|
DEBUG("no previous hold position")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
self.holdpan_pos = self.view:screenToPageTransform(ges.pos)
|
self.holdpan_pos = self.view:screenToPageTransform(ges.pos)
|
||||||
DEBUG("holdpan position in page", self.holdpan_pos)
|
DEBUG("holdpan position in page", self.holdpan_pos)
|
||||||
self.selected_text = self.ui.document:getTextFromPositions(self.hold_pos, self.holdpan_pos)
|
self.selected_text = self.ui.document:getTextFromPositions(self.hold_pos, self.holdpan_pos)
|
||||||
DEBUG("selected text:", self.selected_text)
|
DEBUG("selected text:", self.selected_text)
|
||||||
if self.selected_text then
|
if self.selected_text then
|
||||||
self.view.highlight.temp[self.hold_pos.page] = self.selected_text.sboxes
|
self.view.highlight.temp[self.hold_pos.page] = self.selected_text.sboxes
|
||||||
-- remove selected word if hold moves out of word box
|
-- remove selected word if hold moves out of word box
|
||||||
if not self.selected_text.sboxes or #self.selected_text.sboxes == 0 then
|
if not self.selected_text.sboxes or #self.selected_text.sboxes == 0 then
|
||||||
self.selected_word = nil
|
self.selected_word = nil
|
||||||
elseif self.selected_word and not self.selected_word.sbox:contains(self.selected_text.sboxes[1]) or
|
elseif self.selected_word and not self.selected_word.sbox:contains(self.selected_text.sboxes[1]) or
|
||||||
#self.selected_text.sboxes > 1 then
|
#self.selected_text.sboxes > 1 then
|
||||||
self.selected_word = nil
|
self.selected_word = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.dialog, "partial")
|
UIManager:setDirty(self.dialog, "partial")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:lookup(selected_word)
|
function ReaderHighlight:lookup(selected_word)
|
||||||
-- if we extracted text directly
|
-- if we extracted text directly
|
||||||
if selected_word.word then
|
if selected_word.word then
|
||||||
local word_box = self.view:pageToScreenTransform(self.hold_pos.page, selected_word.sbox)
|
local word_box = self.view:pageToScreenTransform(self.hold_pos.page, selected_word.sbox)
|
||||||
self.ui:handleEvent(Event:new("LookupWord", self, selected_word.word, word_box))
|
self.ui:handleEvent(Event:new("LookupWord", self, selected_word.word, word_box))
|
||||||
-- or we will do OCR
|
-- or we will do OCR
|
||||||
elseif selected_word.sbox and self.hold_pos then
|
elseif selected_word.sbox and self.hold_pos then
|
||||||
local word = self.ui.document:getOCRWord(self.hold_pos.page, selected_word)
|
local word = self.ui.document:getOCRWord(self.hold_pos.page, selected_word)
|
||||||
DEBUG("OCRed word:", word)
|
DEBUG("OCRed word:", word)
|
||||||
local word_box = self.view:pageToScreenTransform(self.hold_pos.page, selected_word.sbox)
|
local word_box = self.view:pageToScreenTransform(self.hold_pos.page, selected_word.sbox)
|
||||||
self.ui:handleEvent(Event:new("LookupWord", self, word, word_box))
|
self.ui:handleEvent(Event:new("LookupWord", self, word, word_box))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:translate(selected_text)
|
function ReaderHighlight:translate(selected_text)
|
||||||
if selected_text.text ~= "" then
|
if selected_text.text ~= "" then
|
||||||
self.ui:handleEvent(Event:new("TranslateText", self, selected_text.text))
|
self.ui:handleEvent(Event:new("TranslateText", self, selected_text.text))
|
||||||
-- or we will do OCR
|
-- or we will do OCR
|
||||||
else
|
else
|
||||||
local text = self.ui.document:getOCRText(self.hold_pos.page, selected_text)
|
local text = self.ui.document:getOCRText(self.hold_pos.page, selected_text)
|
||||||
DEBUG("OCRed text:", text)
|
DEBUG("OCRed text:", text)
|
||||||
self.ui:handleEvent(Event:new("TranslateText", self, text))
|
self.ui:handleEvent(Event:new("TranslateText", self, text))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onHoldRelease(arg, ges)
|
function ReaderHighlight:onHoldRelease(arg, ges)
|
||||||
if self.selected_word then
|
if self.selected_word then
|
||||||
self:lookup(self.selected_word)
|
self:lookup(self.selected_word)
|
||||||
self.selected_word = nil
|
self.selected_word = nil
|
||||||
elseif self.selected_text then
|
elseif self.selected_text then
|
||||||
DEBUG("show highlight dialog")
|
DEBUG("show highlight dialog")
|
||||||
self.highlight_dialog = ButtonDialog:new{
|
self.highlight_dialog = ButtonDialog:new{
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Highlight"),
|
text = _("Highlight"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:saveHighlight()
|
self:saveHighlight()
|
||||||
UIManager:close(self.highlight_dialog)
|
UIManager:close(self.highlight_dialog)
|
||||||
self:handleEvent(Event:new("Tap"))
|
self:handleEvent(Event:new("Tap"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Add Note"),
|
text = _("Add Note"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:addNote()
|
self:addNote()
|
||||||
UIManager:close(self.highlight_dialog)
|
UIManager:close(self.highlight_dialog)
|
||||||
self:handleEvent(Event:new("Tap"))
|
self:handleEvent(Event:new("Tap"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Translate"),
|
text = _("Translate"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:translate(self.selected_text)
|
self:translate(self.selected_text)
|
||||||
UIManager:close(self.highlight_dialog)
|
UIManager:close(self.highlight_dialog)
|
||||||
self:handleEvent(Event:new("Tap"))
|
self:handleEvent(Event:new("Tap"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Share"),
|
text = _("Share"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:shareHighlight()
|
self:shareHighlight()
|
||||||
UIManager:close(self.highlight_dialog)
|
UIManager:close(self.highlight_dialog)
|
||||||
self:handleEvent(Event:new("Tap"))
|
self:handleEvent(Event:new("Tap"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("More"),
|
text = _("More"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:moreAction()
|
self:moreAction()
|
||||||
UIManager:close(self.highlight_dialog)
|
UIManager:close(self.highlight_dialog)
|
||||||
self:handleEvent(Event:new("Tap"))
|
self:handleEvent(Event:new("Tap"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tap_close_callback = function() self:handleEvent(Event:new("Tap")) end,
|
tap_close_callback = function() self:handleEvent(Event:new("Tap")) end,
|
||||||
}
|
}
|
||||||
UIManager:show(self.highlight_dialog)
|
UIManager:show(self.highlight_dialog)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:saveHighlight()
|
function ReaderHighlight:saveHighlight()
|
||||||
DEBUG("save highlight")
|
DEBUG("save highlight")
|
||||||
local page = self.hold_pos.page
|
local page = self.hold_pos.page
|
||||||
if self.hold_pos and self.selected_text then
|
if self.hold_pos and self.selected_text then
|
||||||
if not self.view.highlight.saved[page] then
|
if not self.view.highlight.saved[page] then
|
||||||
self.view.highlight.saved[page] = {}
|
self.view.highlight.saved[page] = {}
|
||||||
end
|
end
|
||||||
local hl_item = {}
|
local hl_item = {}
|
||||||
hl_item["text"] = self.selected_text.text
|
hl_item["text"] = self.selected_text.text
|
||||||
hl_item["pos0"] = self.selected_text.pos0
|
hl_item["pos0"] = self.selected_text.pos0
|
||||||
hl_item["pos1"] = self.selected_text.pos1
|
hl_item["pos1"] = self.selected_text.pos1
|
||||||
hl_item["pboxes"] = self.selected_text.pboxes
|
hl_item["pboxes"] = self.selected_text.pboxes
|
||||||
hl_item["datetime"] = os.date("%Y-%m-%d %H:%M:%S")
|
hl_item["datetime"] = os.date("%Y-%m-%d %H:%M:%S")
|
||||||
hl_item["drawer"] = self.view.highlight.saved_drawer
|
hl_item["drawer"] = self.view.highlight.saved_drawer
|
||||||
table.insert(self.view.highlight.saved[page], hl_item)
|
table.insert(self.view.highlight.saved[page], hl_item)
|
||||||
if self.selected_text.text ~= "" then
|
if self.selected_text.text ~= "" then
|
||||||
self:exportToClippings(page, hl_item)
|
self:exportToClippings(page, hl_item)
|
||||||
end
|
end
|
||||||
if self.selected_text.pboxes then
|
if self.selected_text.pboxes then
|
||||||
self:exportToDocument(page, hl_item)
|
self:exportToDocument(page, hl_item)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--DEBUG("saved hightlights", self.view.highlight.saved[page])
|
--DEBUG("saved hightlights", self.view.highlight.saved[page])
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:exportToClippings(page, item)
|
function ReaderHighlight:exportToClippings(page, item)
|
||||||
DEBUG("export highlight to clippings", item)
|
DEBUG("export highlight to clippings", item)
|
||||||
local clippings = io.open("/mnt/us/documents/My Clippings.txt", "a+")
|
local clippings = io.open("/mnt/us/documents/My Clippings.txt", "a+")
|
||||||
if clippings and item.text then
|
if clippings and item.text then
|
||||||
local current_locale = os.setlocale()
|
local current_locale = os.setlocale()
|
||||||
os.setlocale("C")
|
os.setlocale("C")
|
||||||
clippings:write(self.document.file:gsub("(.*/)(.*)", "%2").."\n")
|
clippings:write(self.document.file:gsub("(.*/)(.*)", "%2").."\n")
|
||||||
clippings:write("- Koreader Highlight Page "..page.." ")
|
clippings:write("- Koreader Highlight Page "..page.." ")
|
||||||
clippings:write("| Added on "..os.date("%A, %b %d, %Y %I:%M:%S %p\n\n"))
|
clippings:write("| Added on "..os.date("%A, %b %d, %Y %I:%M:%S %p\n\n"))
|
||||||
clippings:write(item["text"].."\n")
|
clippings:write(item["text"].."\n")
|
||||||
clippings:write("==========\n")
|
clippings:write("==========\n")
|
||||||
clippings:close()
|
clippings:close()
|
||||||
os.setlocale(current_locale)
|
os.setlocale(current_locale)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:exportToDocument(page, item)
|
function ReaderHighlight:exportToDocument(page, item)
|
||||||
DEBUG("export highlight to document", item)
|
DEBUG("export highlight to document", item)
|
||||||
self.ui.document:saveHighlight(page, item)
|
self.ui.document:saveHighlight(page, item)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:addNote()
|
function ReaderHighlight:addNote()
|
||||||
DEBUG("add Note")
|
DEBUG("add Note")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:shareHighlight()
|
function ReaderHighlight:shareHighlight()
|
||||||
DEBUG("share highlight")
|
DEBUG("share highlight")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:moreAction()
|
function ReaderHighlight:moreAction()
|
||||||
DEBUG("more action")
|
DEBUG("more action")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:deleteHighlight(page, i)
|
function ReaderHighlight:deleteHighlight(page, i)
|
||||||
DEBUG("delete highlight")
|
DEBUG("delete highlight")
|
||||||
table.remove(self.view.highlight.saved[page], i)
|
table.remove(self.view.highlight.saved[page], i)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:editHighlight()
|
function ReaderHighlight:editHighlight()
|
||||||
DEBUG("edit highlight")
|
DEBUG("edit highlight")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onReadSettings(config)
|
function ReaderHighlight:onReadSettings(config)
|
||||||
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer") or self.view.highlight.saved_drawer
|
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer") or self.view.highlight.saved_drawer
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onSaveSettings()
|
function ReaderHighlight:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer)
|
self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderHighlight
|
return ReaderHighlight
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
local EventListener = require("ui/widget/eventlistener")
|
local EventListener = require("ui/widget/eventlistener")
|
||||||
|
|
||||||
local ReaderHinting = EventListener:new{
|
local ReaderHinting = EventListener:new{
|
||||||
hinting_states = {}
|
hinting_states = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderHinting:onHintPage()
|
function ReaderHinting:onHintPage()
|
||||||
if not self.view.hinting then return true end
|
if not self.view.hinting then return true end
|
||||||
for i=1, DHINTCOUNT do
|
for i=1, DHINTCOUNT do
|
||||||
if self.view.state.page + i <= self.ui.document.info.number_of_pages then
|
if self.view.state.page + i <= self.ui.document.info.number_of_pages then
|
||||||
self.ui.document:hintPage(
|
self.ui.document:hintPage(
|
||||||
self.view.state.page + i,
|
self.view.state.page + i,
|
||||||
self.zoom:getZoom(self.view.state.page + i),
|
self.zoom:getZoom(self.view.state.page + i),
|
||||||
self.view.state.rotation,
|
self.view.state.rotation,
|
||||||
self.view.state.gamma,
|
self.view.state.gamma,
|
||||||
self.view.render_mode)
|
self.view.render_mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHinting:onSetHinting(hinting)
|
function ReaderHinting:onSetHinting(hinting)
|
||||||
self.view.hinting = hinting
|
self.view.hinting = hinting
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHinting:onDisableHinting()
|
function ReaderHinting:onDisableHinting()
|
||||||
table.insert(self.hinting_states, self.view.hinting)
|
table.insert(self.hinting_states, self.view.hinting)
|
||||||
self.view.hinting = false
|
self.view.hinting = false
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHinting:onRestoreHinting()
|
function ReaderHinting:onRestoreHinting()
|
||||||
self.view.hinting = table.remove(self.hinting_states)
|
self.view.hinting = table.remove(self.hinting_states)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderHinting
|
return ReaderHinting
|
||||||
|
|||||||
@@ -4,52 +4,52 @@ local InfoMessage = require("ui/widget/infomessage")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderHyphenation = InputContainer:new{
|
local ReaderHyphenation = InputContainer:new{
|
||||||
hyph_menu_title = _("Hyphenation"),
|
hyph_menu_title = _("Hyphenation"),
|
||||||
hyph_table = nil,
|
hyph_table = nil,
|
||||||
cur_hyph_idx = nil,
|
cur_hyph_idx = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderHyphenation:_changeSel(k)
|
function ReaderHyphenation:_changeSel(k)
|
||||||
if self.cur_hyph_idx then
|
if self.cur_hyph_idx then
|
||||||
self.hyph_table[self.cur_hyph_idx].selected = false
|
self.hyph_table[self.cur_hyph_idx].selected = false
|
||||||
end
|
end
|
||||||
self.hyph_table[k].selected = true
|
self.hyph_table[k].selected = true
|
||||||
self.cur_hyph_idx = k
|
self.cur_hyph_idx = k
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHyphenation:init()
|
function ReaderHyphenation:init()
|
||||||
self.hyph_table = {}
|
self.hyph_table = {}
|
||||||
self.hyph_alg = cre.getSelectedHyphDict()
|
self.hyph_alg = cre.getSelectedHyphDict()
|
||||||
for k,v in ipairs(cre.getHyphDictList()) do
|
for k,v in ipairs(cre.getHyphDictList()) do
|
||||||
if v == self.hyph_alg then
|
if v == self.hyph_alg then
|
||||||
self.cur_hyph_idx = k
|
self.cur_hyph_idx = k
|
||||||
end
|
end
|
||||||
table.insert(self.hyph_table, {
|
table.insert(self.hyph_table, {
|
||||||
text = v,
|
text = v,
|
||||||
callback = function()
|
callback = function()
|
||||||
self.hyph_alg = v
|
self.hyph_alg = v
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Change Hyphenation to ")..v,
|
text = _("Change Hyphenation to ")..v,
|
||||||
})
|
})
|
||||||
self:_changeSel(k)
|
self:_changeSel(k)
|
||||||
cre.setHyphDictionary(v)
|
cre.setHyphDictionary(v)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHyphenation:onReadSettings(config)
|
function ReaderHyphenation:onReadSettings(config)
|
||||||
local hyph_alg = config:readSetting("hyph_alg")
|
local hyph_alg = config:readSetting("hyph_alg")
|
||||||
if hyph_alg then
|
if hyph_alg then
|
||||||
cre.setHyphDictionary(hyph_alg)
|
cre.setHyphDictionary(hyph_alg)
|
||||||
end
|
end
|
||||||
self.hyph_alg = cre.getSelectedHyphDict()
|
self.hyph_alg = cre.getSelectedHyphDict()
|
||||||
for k,v in ipairs(self.hyph_table) do
|
for k,v in ipairs(self.hyph_table) do
|
||||||
if v.text == self.hyph_alg then
|
if v.text == self.hyph_alg then
|
||||||
self:_changeSel(k)
|
self:_changeSel(k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHyphenation:onSaveSettings()
|
function ReaderHyphenation:onSaveSettings()
|
||||||
@@ -57,11 +57,11 @@ function ReaderHyphenation:onSaveSettings()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHyphenation:addToMainMenu(tab_item_table)
|
function ReaderHyphenation:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.typeset, {
|
table.insert(tab_item_table.typeset, {
|
||||||
text = self.hyph_menu_title,
|
text = self.hyph_menu_title,
|
||||||
sub_item_table = self.hyph_table,
|
sub_item_table = self.hyph_table,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderHyphenation
|
return ReaderHyphenation
|
||||||
|
|||||||
@@ -4,56 +4,56 @@ local Event = require("ui/event")
|
|||||||
local ReaderKoptListener = EventListener:new{}
|
local ReaderKoptListener = EventListener:new{}
|
||||||
|
|
||||||
function ReaderKoptListener:setZoomMode(zoom_mode)
|
function ReaderKoptListener:setZoomMode(zoom_mode)
|
||||||
if self.document.configurable.text_wrap == 1 then
|
if self.document.configurable.text_wrap == 1 then
|
||||||
-- in reflow mode only "page" zoom mode is valid so override any other zoom mode
|
-- in reflow mode only "page" zoom mode is valid so override any other zoom mode
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", "page", "koptlistener"))
|
self.ui:handleEvent(Event:new("SetZoomMode", "page", "koptlistener"))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", zoom_mode, "koptlistener"))
|
self.ui:handleEvent(Event:new("SetZoomMode", zoom_mode, "koptlistener"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onReadSettings(config)
|
function ReaderKoptListener:onReadSettings(config)
|
||||||
-- normal zoom mode is zoom mode used in non-reflow mode.
|
-- normal zoom mode is zoom mode used in non-reflow mode.
|
||||||
self.normal_zoom_mode = config:readSetting("normal_zoom_mode") or "page"
|
self.normal_zoom_mode = config:readSetting("normal_zoom_mode") or "page"
|
||||||
self:setZoomMode(self.normal_zoom_mode)
|
self:setZoomMode(self.normal_zoom_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onSaveSettings()
|
function ReaderKoptListener:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("normal_zoom_mode", self.normal_zoom_mode)
|
self.ui.doc_settings:saveSetting("normal_zoom_mode", self.normal_zoom_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onRestoreZoomMode()
|
function ReaderKoptListener:onRestoreZoomMode()
|
||||||
-- "RestoreZoomMode" event is sent when reflow mode on/off is toggled
|
-- "RestoreZoomMode" event is sent when reflow mode on/off is toggled
|
||||||
self:setZoomMode(self.normal_zoom_mode)
|
self:setZoomMode(self.normal_zoom_mode)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onSetZoomMode(zoom_mode, orig)
|
function ReaderKoptListener:onSetZoomMode(zoom_mode, orig)
|
||||||
if orig == "koptlistener" then return end
|
if orig == "koptlistener" then return end
|
||||||
-- capture zoom mode set outside of koptlistener which should always be normal zoom mode
|
-- capture zoom mode set outside of koptlistener which should always be normal zoom mode
|
||||||
self.normal_zoom_mode = zoom_mode
|
self.normal_zoom_mode = zoom_mode
|
||||||
self:setZoomMode(self.normal_zoom_mode)
|
self:setZoomMode(self.normal_zoom_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onFineTuningFontSize(delta)
|
function ReaderKoptListener:onFineTuningFontSize(delta)
|
||||||
self.document.configurable.font_size = self.document.configurable.font_size + delta
|
self.document.configurable.font_size = self.document.configurable.font_size + delta
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderKoptListener:onZoomUpdate(zoom)
|
function ReaderKoptListener:onZoomUpdate(zoom)
|
||||||
-- an exceptional case is reflow mode
|
-- an exceptional case is reflow mode
|
||||||
if self.document.configurable.text_wrap == 1 then
|
if self.document.configurable.text_wrap == 1 then
|
||||||
self.view.state.zoom = 1.0
|
self.view.state.zoom = 1.0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- misc koptoption handler
|
-- misc koptoption handler
|
||||||
function ReaderKoptListener:onDocLangUpdate(lang)
|
function ReaderKoptListener:onDocLangUpdate(lang)
|
||||||
if lang == "chi_sim" or lang == "chi_tra" or
|
if lang == "chi_sim" or lang == "chi_tra" or
|
||||||
lang == "jpn" or lang == "kor" then
|
lang == "jpn" or lang == "kor" then
|
||||||
self.document.configurable.word_spacing = DKOPTREADER_CONFIG_WORD_SAPCINGS[1]
|
self.document.configurable.word_spacing = DKOPTREADER_CONFIG_WORD_SAPCINGS[1]
|
||||||
else
|
else
|
||||||
self.document.configurable.word_spacing = DKOPTREADER_CONFIG_WORD_SAPCINGS[3]
|
self.document.configurable.word_spacing = DKOPTREADER_CONFIG_WORD_SAPCINGS[3]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderKoptListener
|
return ReaderKoptListener
|
||||||
|
|||||||
@@ -7,100 +7,100 @@ local Event = require("ui/event")
|
|||||||
local DEBUG = require("dbg")
|
local DEBUG = require("dbg")
|
||||||
|
|
||||||
local ReaderLink = InputContainer:new{
|
local ReaderLink = InputContainer:new{
|
||||||
link_states = {}
|
link_states = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderLink:init()
|
function ReaderLink:init()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:onReadSettings(config)
|
function ReaderLink:onReadSettings(config)
|
||||||
-- called when loading new document
|
-- called when loading new document
|
||||||
self.link_states = {}
|
self.link_states = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:initGesListener()
|
function ReaderLink:initGesListener()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Tap = {
|
Tap = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()
|
h = Screen:getHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Swipe = {
|
Swipe = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:onSetDimensions(dimen)
|
function ReaderLink:onSetDimensions(dimen)
|
||||||
-- update listening according to new screen dimen
|
-- update listening according to new screen dimen
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:onTap(arg, ges)
|
function ReaderLink:onTap(arg, ges)
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
local pos = self.view:screenToPageTransform(ges.pos)
|
local pos = self.view:screenToPageTransform(ges.pos)
|
||||||
if pos then
|
if pos then
|
||||||
local link = self.ui.document:getLinkFromPosition(pos.page, pos)
|
local link = self.ui.document:getLinkFromPosition(pos.page, pos)
|
||||||
if link then
|
if link then
|
||||||
return self:onGotoLink(link)
|
return self:onGotoLink(link)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local link = self.ui.document:getLinkFromPosition(ges.pos)
|
local link = self.ui.document:getLinkFromPosition(ges.pos)
|
||||||
if link ~= "" then
|
if link ~= "" then
|
||||||
return self:onGotoLink(link)
|
return self:onGotoLink(link)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:onGotoLink(link)
|
function ReaderLink:onGotoLink(link)
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
table.insert(self.link_states, self.view.state.page)
|
table.insert(self.link_states, self.view.state.page)
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", link.page + 1))
|
self.ui:handleEvent(Event:new("PageUpdate", link.page + 1))
|
||||||
else
|
else
|
||||||
table.insert(self.link_states, self.ui.document:getXPointer())
|
table.insert(self.link_states, self.ui.document:getXPointer())
|
||||||
self.document:gotoLink(link)
|
self.document:gotoLink(link)
|
||||||
self.ui:handleEvent(Event:new("UpdateXPointer"))
|
self.ui:handleEvent(Event:new("UpdateXPointer"))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderLink:onSwipe(arg, ges)
|
function ReaderLink:onSwipe(arg, ges)
|
||||||
if ges.direction == "east" then
|
if ges.direction == "east" then
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
local last_page = table.remove(self.link_states)
|
local last_page = table.remove(self.link_states)
|
||||||
if last_page then
|
if last_page then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", last_page))
|
self.ui:handleEvent(Event:new("PageUpdate", last_page))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local last_xp = table.remove(self.link_states)
|
local last_xp = table.remove(self.link_states)
|
||||||
if last_xp then
|
if last_xp then
|
||||||
self.ui.document:gotoXPointer(last_xp)
|
self.ui.document:gotoXPointer(last_xp)
|
||||||
self.ui:handleEvent(Event:new("UpdateXPointer"))
|
self.ui:handleEvent(Event:new("UpdateXPointer"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderLink
|
return ReaderLink
|
||||||
|
|||||||
@@ -13,146 +13,146 @@ local Language = require("ui/language")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderMenu = InputContainer:new{
|
local ReaderMenu = InputContainer:new{
|
||||||
tab_item_table = nil,
|
tab_item_table = nil,
|
||||||
registered_widgets = {},
|
registered_widgets = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderMenu:init()
|
function ReaderMenu:init()
|
||||||
self.tab_item_table = {
|
self.tab_item_table = {
|
||||||
main = {
|
main = {
|
||||||
icon = "resources/icons/appbar.pokeball.png",
|
icon = "resources/icons/appbar.pokeball.png",
|
||||||
},
|
},
|
||||||
navi = {
|
navi = {
|
||||||
icon = "resources/icons/appbar.page.corner.bookmark.png",
|
icon = "resources/icons/appbar.page.corner.bookmark.png",
|
||||||
},
|
},
|
||||||
typeset = {
|
typeset = {
|
||||||
icon = "resources/icons/appbar.page.text.png",
|
icon = "resources/icons/appbar.page.text.png",
|
||||||
},
|
},
|
||||||
home = {
|
home = {
|
||||||
icon = "resources/icons/appbar.home.png",
|
icon = "resources/icons/appbar.home.png",
|
||||||
callback = function()
|
callback = function()
|
||||||
self.ui:handleEvent(Event:new("RestoreScreenMode",
|
self.ui:handleEvent(Event:new("RestoreScreenMode",
|
||||||
G_reader_settings:readSetting("screen_mode") or "portrait"))
|
G_reader_settings:readSetting("screen_mode") or "portrait"))
|
||||||
UIManager:close(self.menu_container)
|
UIManager:close(self.menu_container)
|
||||||
self.ui:onClose()
|
self.ui:onClose()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
self.registered_widgets = {}
|
self.registered_widgets = {}
|
||||||
|
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowMenu = { { "Menu" }, doc = _("show menu") },
|
ShowMenu = { { "Menu" }, doc = _("show menu") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:initGesListener()
|
function ReaderMenu:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapShowMenu = {
|
TapShowMenu = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_MENU.x,
|
x = Screen:getWidth()*DTAP_ZONE_MENU.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_MENU.y,
|
y = Screen:getHeight()*DTAP_ZONE_MENU.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_MENU.w,
|
w = Screen:getWidth()*DTAP_ZONE_MENU.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_MENU.h
|
h = Screen:getHeight()*DTAP_ZONE_MENU.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:setUpdateItemTable()
|
function ReaderMenu:setUpdateItemTable()
|
||||||
for _, widget in pairs(self.registered_widgets) do
|
for _, widget in pairs(self.registered_widgets) do
|
||||||
widget:addToMainMenu(self.tab_item_table)
|
widget:addToMainMenu(self.tab_item_table)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.tab_item_table.main, {
|
table.insert(self.tab_item_table.main, {
|
||||||
text = _("Help"),
|
text = _("Help"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Please report bugs to https://github.com/koreader/ koreader/issues, Click at the bottom of the page for more options"),
|
text = _("Please report bugs to https://github.com/koreader/ koreader/issues, Click at the bottom of the page for more options"),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
table.insert(self.tab_item_table.main, {
|
table.insert(self.tab_item_table.main, {
|
||||||
text = _("Version"),
|
text = _("Version"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = io.open("git-rev", "r"):read(),
|
text = io.open("git-rev", "r"):read(),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
table.insert(self.tab_item_table.main, Language:getLangMenuTable())
|
table.insert(self.tab_item_table.main, Language:getLangMenuTable())
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:onShowReaderMenu()
|
function ReaderMenu:onShowReaderMenu()
|
||||||
if #self.tab_item_table.main == 0 then
|
if #self.tab_item_table.main == 0 then
|
||||||
self:setUpdateItemTable()
|
self:setUpdateItemTable()
|
||||||
end
|
end
|
||||||
|
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
ignore = "height",
|
ignore = "height",
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
|
|
||||||
local main_menu = nil
|
local main_menu = nil
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
main_menu = TouchMenu:new{
|
main_menu = TouchMenu:new{
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
tab_item_table = {
|
tab_item_table = {
|
||||||
self.tab_item_table.navi,
|
self.tab_item_table.navi,
|
||||||
self.tab_item_table.typeset,
|
self.tab_item_table.typeset,
|
||||||
self.tab_item_table.main,
|
self.tab_item_table.main,
|
||||||
self.tab_item_table.home,
|
self.tab_item_table.home,
|
||||||
},
|
},
|
||||||
show_parent = menu_container,
|
show_parent = menu_container,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
main_menu = Menu:new{
|
main_menu = Menu:new{
|
||||||
title = _("Document menu"),
|
title = _("Document menu"),
|
||||||
item_table = {},
|
item_table = {},
|
||||||
width = Screen:getWidth() - 100,
|
width = Screen:getWidth() - 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _,item_table in pairs(self.tab_item_table) do
|
for _,item_table in pairs(self.tab_item_table) do
|
||||||
for k,v in ipairs(item_table) do
|
for k,v in ipairs(item_table) do
|
||||||
table.insert(main_menu.item_table, v)
|
table.insert(main_menu.item_table, v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main_menu.close_callback = function ()
|
main_menu.close_callback = function ()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
menu_container[1] = main_menu
|
menu_container[1] = main_menu
|
||||||
-- maintain a reference to menu_container
|
-- maintain a reference to menu_container
|
||||||
self.menu_container = menu_container
|
self.menu_container = menu_container
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:onTapShowMenu()
|
function ReaderMenu:onTapShowMenu()
|
||||||
self.ui:handleEvent(Event:new("ShowConfigMenu"))
|
self.ui:handleEvent(Event:new("ShowConfigMenu"))
|
||||||
self.ui:handleEvent(Event:new("ShowReaderMenu"))
|
self.ui:handleEvent(Event:new("ShowReaderMenu"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:onSetDimensions(dimen)
|
function ReaderMenu:onSetDimensions(dimen)
|
||||||
-- update listening according to new screen dimen
|
-- update listening according to new screen dimen
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:onSaveSettings()
|
function ReaderMenu:onSaveSettings()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderMenu:registerToMainMenu(widget)
|
function ReaderMenu:registerToMainMenu(widget)
|
||||||
table.insert(self.registered_widgets, widget)
|
table.insert(self.registered_widgets, widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderMenu
|
return ReaderMenu
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,48 +4,48 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderPanning = InputContainer:new{
|
local ReaderPanning = InputContainer:new{
|
||||||
-- defaults
|
-- defaults
|
||||||
panning_steps = {
|
panning_steps = {
|
||||||
normal = 50,
|
normal = 50,
|
||||||
alt = 25,
|
alt = 25,
|
||||||
shift = 10,
|
shift = 10,
|
||||||
altshift = 5
|
altshift = 5
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderPanning:init()
|
function ReaderPanning:init()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
else
|
else
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
-- these will all generate the same event, just with different arguments
|
-- these will all generate the same event, just with different arguments
|
||||||
MoveUp = {
|
MoveUp = {
|
||||||
{ "Up" }, doc = _("move visible area up"),
|
{ "Up" }, doc = _("move visible area up"),
|
||||||
event = "Panning", args = {0, -1} },
|
event = "Panning", args = {0, -1} },
|
||||||
MoveDown = {
|
MoveDown = {
|
||||||
{ "Down" }, doc = _("move visible area down"),
|
{ "Down" }, doc = _("move visible area down"),
|
||||||
event = "Panning", args = {0, 1} },
|
event = "Panning", args = {0, 1} },
|
||||||
MoveLeft = {
|
MoveLeft = {
|
||||||
{ "Left" }, doc = _("move visible area left"),
|
{ "Left" }, doc = _("move visible area left"),
|
||||||
event = "Panning", args = {-1, 0} },
|
event = "Panning", args = {-1, 0} },
|
||||||
MoveRight = {
|
MoveRight = {
|
||||||
{ "Right" }, doc = _("move visible area right"),
|
{ "Right" }, doc = _("move visible area right"),
|
||||||
event = "Panning", args = {1, 0} },
|
event = "Panning", args = {1, 0} },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderPanning:onSetDimensions(dimensions)
|
function ReaderPanning:onSetDimensions(dimensions)
|
||||||
self.dimen = dimensions
|
self.dimen = dimensions
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderPanning:onPanning(args, key)
|
function ReaderPanning:onPanning(args, key)
|
||||||
local dx, dy = unpack(args)
|
local dx, dy = unpack(args)
|
||||||
DEBUG("key =", key)
|
DEBUG("key =", key)
|
||||||
-- for now, bounds checking/calculation is done in the view
|
-- for now, bounds checking/calculation is done in the view
|
||||||
self.view:PanningUpdate(
|
self.view:PanningUpdate(
|
||||||
dx * self.panning_steps.normal * self.dimen.w / 100,
|
dx * self.panning_steps.normal * self.dimen.w / 100,
|
||||||
dy * self.panning_steps.normal * self.dimen.h / 100)
|
dy * self.panning_steps.normal * self.dimen.h / 100)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderPanning
|
return ReaderPanning
|
||||||
|
|||||||
@@ -11,363 +11,363 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderRolling = InputContainer:new{
|
local ReaderRolling = InputContainer:new{
|
||||||
old_doc_height = nil,
|
old_doc_height = nil,
|
||||||
old_page = nil,
|
old_page = nil,
|
||||||
current_pos = 0,
|
current_pos = 0,
|
||||||
-- only used for page view mode
|
-- only used for page view mode
|
||||||
current_page= nil,
|
current_page= nil,
|
||||||
doc_height = nil,
|
doc_height = nil,
|
||||||
panning_steps = ReaderPanning.panning_steps,
|
panning_steps = ReaderPanning.panning_steps,
|
||||||
show_overlap_enable = true,
|
show_overlap_enable = true,
|
||||||
overlap = 20,
|
overlap = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderRolling:init()
|
function ReaderRolling:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
GotoNextView = {
|
GotoNextView = {
|
||||||
{ Input.group.PgFwd },
|
{ Input.group.PgFwd },
|
||||||
doc = _("go to next view"),
|
doc = _("go to next view"),
|
||||||
event = "GotoViewRel", args = 1
|
event = "GotoViewRel", args = 1
|
||||||
},
|
},
|
||||||
GotoPrevView = {
|
GotoPrevView = {
|
||||||
{ Input.group.PgBack },
|
{ Input.group.PgBack },
|
||||||
doc = _("go to previous view"),
|
doc = _("go to previous view"),
|
||||||
event = "GotoViewRel", args = -1
|
event = "GotoViewRel", args = -1
|
||||||
},
|
},
|
||||||
MoveUp = {
|
MoveUp = {
|
||||||
{ "Up" },
|
{ "Up" },
|
||||||
doc = _("move view up"),
|
doc = _("move view up"),
|
||||||
event = "Panning", args = {0, -1}
|
event = "Panning", args = {0, -1}
|
||||||
},
|
},
|
||||||
MoveDown = {
|
MoveDown = {
|
||||||
{ "Down" },
|
{ "Down" },
|
||||||
doc = _("move view down"),
|
doc = _("move view down"),
|
||||||
event = "Panning", args = {0, 1}
|
event = "Panning", args = {0, 1}
|
||||||
},
|
},
|
||||||
GotoFirst = {
|
GotoFirst = {
|
||||||
{"1"}, doc = _("go to start"), event = "GotoPercent", args = 0},
|
{"1"}, doc = _("go to start"), event = "GotoPercent", args = 0},
|
||||||
Goto11 = {
|
Goto11 = {
|
||||||
{"2"}, doc = _("go to 11%"), event = "GotoPercent", args = 11},
|
{"2"}, doc = _("go to 11%"), event = "GotoPercent", args = 11},
|
||||||
Goto22 = {
|
Goto22 = {
|
||||||
{"3"}, doc = _("go to 22%"), event = "GotoPercent", args = 22},
|
{"3"}, doc = _("go to 22%"), event = "GotoPercent", args = 22},
|
||||||
Goto33 = {
|
Goto33 = {
|
||||||
{"4"}, doc = _("go to 33%"), event = "GotoPercent", args = 33},
|
{"4"}, doc = _("go to 33%"), event = "GotoPercent", args = 33},
|
||||||
Goto44 = {
|
Goto44 = {
|
||||||
{"5"}, doc = _("go to 44%"), event = "GotoPercent", args = 44},
|
{"5"}, doc = _("go to 44%"), event = "GotoPercent", args = 44},
|
||||||
Goto55 = {
|
Goto55 = {
|
||||||
{"6"}, doc = _("go to 55%"), event = "GotoPercent", args = 55},
|
{"6"}, doc = _("go to 55%"), event = "GotoPercent", args = 55},
|
||||||
Goto66 = {
|
Goto66 = {
|
||||||
{"7"}, doc = _("go to 66%"), event = "GotoPercent", args = 66},
|
{"7"}, doc = _("go to 66%"), event = "GotoPercent", args = 66},
|
||||||
Goto77 = {
|
Goto77 = {
|
||||||
{"8"}, doc = _("go to 77%"), event = "GotoPercent", args = 77},
|
{"8"}, doc = _("go to 77%"), event = "GotoPercent", args = 77},
|
||||||
Goto88 = {
|
Goto88 = {
|
||||||
{"9"}, doc = _("go to 88%"), event = "GotoPercent", args = 88},
|
{"9"}, doc = _("go to 88%"), event = "GotoPercent", args = 88},
|
||||||
GotoLast = {
|
GotoLast = {
|
||||||
{"0"}, doc = _("go to end"), event = "GotoPercent", args = 100},
|
{"0"}, doc = _("go to end"), event = "GotoPercent", args = 100},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self.doc_height = self.ui.document.info.doc_height
|
self.doc_height = self.ui.document.info.doc_height
|
||||||
self.old_doc_height = self.doc_height
|
self.old_doc_height = self.doc_height
|
||||||
self.old_page = self.ui.document.info.number_of_pages
|
self.old_page = self.ui.document.info.number_of_pages
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This method will be called in onSetDimensions handler
|
-- This method will be called in onSetDimensions handler
|
||||||
function ReaderRolling:initGesListener()
|
function ReaderRolling:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapForward = {
|
TapForward = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_FORWARD.x,
|
x = Screen:getWidth()*DTAP_ZONE_FORWARD.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_FORWARD.y,
|
y = Screen:getHeight()*DTAP_ZONE_FORWARD.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_FORWARD.w,
|
w = Screen:getWidth()*DTAP_ZONE_FORWARD.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_FORWARD.h,
|
h = Screen:getHeight()*DTAP_ZONE_FORWARD.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TapBackward = {
|
TapBackward = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = Screen:getWidth()*DTAP_ZONE_BACKWARD.x,
|
x = Screen:getWidth()*DTAP_ZONE_BACKWARD.x,
|
||||||
y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y,
|
y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y,
|
||||||
w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w,
|
w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w,
|
||||||
h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h,
|
h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Swipe = {
|
Swipe = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Pan = {
|
Pan = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "pan",
|
ges = "pan",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
},
|
},
|
||||||
rate = 4.0,
|
rate = 4.0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onReadSettings(config)
|
function ReaderRolling:onReadSettings(config)
|
||||||
local soe = config:readSetting("show_overlap_enable")
|
local soe = config:readSetting("show_overlap_enable")
|
||||||
if not soe then
|
if not soe then
|
||||||
self.show_overlap_enable = soe
|
self.show_overlap_enable = soe
|
||||||
end
|
end
|
||||||
local last_xp = config:readSetting("last_xpointer")
|
local last_xp = config:readSetting("last_xpointer")
|
||||||
if last_xp then
|
if last_xp then
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self:gotoXPointer(last_xp)
|
self:gotoXPointer(last_xp)
|
||||||
-- we have to do a real jump in self.ui.document._document to
|
-- we have to do a real jump in self.ui.document._document to
|
||||||
-- update status information in CREngine.
|
-- update status information in CREngine.
|
||||||
self.ui.document:gotoXPointer(last_xp)
|
self.ui.document:gotoXPointer(last_xp)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
-- we read last_percent just for backward compatibility
|
-- we read last_percent just for backward compatibility
|
||||||
if not last_xp then
|
if not last_xp then
|
||||||
local last_per = config:readSetting("last_percent")
|
local last_per = config:readSetting("last_percent")
|
||||||
if last_per then
|
if last_per then
|
||||||
table.insert(self.ui.postInitCallback, function()
|
table.insert(self.ui.postInitCallback, function()
|
||||||
self:gotoPercent(last_per)
|
self:gotoPercent(last_per)
|
||||||
-- we have to do a real pos change in self.ui.document._document
|
-- we have to do a real pos change in self.ui.document._document
|
||||||
-- to update status information in CREngine.
|
-- to update status information in CREngine.
|
||||||
self.ui.document:gotoPos(self.current_pos)
|
self.ui.document:gotoPos(self.current_pos)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getCurrentPage()))
|
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getCurrentPage()))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onSaveSettings()
|
function ReaderRolling:onSaveSettings()
|
||||||
-- remove last_percent config since its deprecated
|
-- remove last_percent config since its deprecated
|
||||||
self.ui.doc_settings:saveSetting("last_percent", nil)
|
self.ui.doc_settings:saveSetting("last_percent", nil)
|
||||||
self.ui.doc_settings:saveSetting("last_xpointer", self.ui.document:getXPointer())
|
self.ui.doc_settings:saveSetting("last_xpointer", self.ui.document:getXPointer())
|
||||||
self.ui.doc_settings:saveSetting("percent_finished", self:getLastPercent())
|
self.ui.doc_settings:saveSetting("percent_finished", self:getLastPercent())
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:getLastPercent()
|
function ReaderRolling:getLastPercent()
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
return self.current_page / self.old_page
|
return self.current_page / self.old_page
|
||||||
else
|
else
|
||||||
-- FIXME: the calculated percent is not accurate in "scroll" mode.
|
-- FIXME: the calculated percent is not accurate in "scroll" mode.
|
||||||
return self.ui.document:getPosFromXPointer(
|
return self.ui.document:getPosFromXPointer(
|
||||||
self.ui.document:getXPointer()) / self.doc_height
|
self.ui.document:getXPointer()) / self.doc_height
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onTapForward()
|
function ReaderRolling:onTapForward()
|
||||||
self:onGotoViewRel(1)
|
self:onGotoViewRel(1)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onTapBackward()
|
function ReaderRolling:onTapBackward()
|
||||||
self:onGotoViewRel(-1)
|
self:onGotoViewRel(-1)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onSwipe(arg, ges)
|
function ReaderRolling:onSwipe(arg, ges)
|
||||||
if ges.direction == "west" or ges.direction == "north" then
|
if ges.direction == "west" or ges.direction == "north" then
|
||||||
self:onGotoViewRel(1)
|
self:onGotoViewRel(1)
|
||||||
elseif ges.direction == "east" or ges.direction == "south" then
|
elseif ges.direction == "east" or ges.direction == "south" then
|
||||||
self:onGotoViewRel(-1)
|
self:onGotoViewRel(-1)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onPan(arg, ges)
|
function ReaderRolling:onPan(arg, ges)
|
||||||
if self.view.view_mode == "scroll" then
|
if self.view.view_mode == "scroll" then
|
||||||
if ges.direction == "north" then
|
if ges.direction == "north" then
|
||||||
self:gotoPos(self.current_pos + ges.distance)
|
self:gotoPos(self.current_pos + ges.distance)
|
||||||
elseif ges.direction == "south" then
|
elseif ges.direction == "south" then
|
||||||
self:gotoPos(self.current_pos - ges.distance)
|
self:gotoPos(self.current_pos - ges.distance)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onPosUpdate(new_pos)
|
function ReaderRolling:onPosUpdate(new_pos)
|
||||||
self.current_pos = new_pos
|
self.current_pos = new_pos
|
||||||
self:updateBatteryState()
|
self:updateBatteryState()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onPageUpdate(new_page)
|
function ReaderRolling:onPageUpdate(new_page)
|
||||||
self.current_page = new_page
|
self.current_page = new_page
|
||||||
self:updateBatteryState()
|
self:updateBatteryState()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onResume()
|
function ReaderRolling:onResume()
|
||||||
self:updateBatteryState()
|
self:updateBatteryState()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onNotCharging()
|
function ReaderRolling:onNotCharging()
|
||||||
self:updateBatteryState()
|
self:updateBatteryState()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onGotoPercent(percent)
|
function ReaderRolling:onGotoPercent(percent)
|
||||||
DEBUG("goto document offset in percent:", percent)
|
DEBUG("goto document offset in percent:", percent)
|
||||||
self:gotoPercent(percent)
|
self:gotoPercent(percent)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onGotoViewRel(diff)
|
function ReaderRolling:onGotoViewRel(diff)
|
||||||
DEBUG("goto relative screen:", diff, ", in mode: ", self.view.view_mode)
|
DEBUG("goto relative screen:", diff, ", in mode: ", self.view.view_mode)
|
||||||
if self.view.view_mode == "scroll" then
|
if self.view.view_mode == "scroll" then
|
||||||
local pan_diff = diff * self.ui.dimen.h
|
local pan_diff = diff * self.ui.dimen.h
|
||||||
if self.show_overlap_enable then
|
if self.show_overlap_enable then
|
||||||
if pan_diff > self.overlap then
|
if pan_diff > self.overlap then
|
||||||
pan_diff = pan_diff - self.overlap
|
pan_diff = pan_diff - self.overlap
|
||||||
elseif pan_diff < -self.overlap then
|
elseif pan_diff < -self.overlap then
|
||||||
pan_diff = pan_diff + self.overlap
|
pan_diff = pan_diff + self.overlap
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:gotoPos(self.current_pos + pan_diff)
|
self:gotoPos(self.current_pos + pan_diff)
|
||||||
elseif self.view.view_mode == "page" then
|
elseif self.view.view_mode == "page" then
|
||||||
self:gotoPage(self.current_page + diff)
|
self:gotoPage(self.current_page + diff)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onPanning(args, key)
|
function ReaderRolling:onPanning(args, key)
|
||||||
--@TODO disable panning in page view_mode? 22.12 2012 (houqp)
|
--@TODO disable panning in page view_mode? 22.12 2012 (houqp)
|
||||||
local _, dy = unpack(args)
|
local _, dy = unpack(args)
|
||||||
DEBUG("key =", key)
|
DEBUG("key =", key)
|
||||||
self:gotoPos(self.current_pos + dy * self.panning_steps.normal)
|
self:gotoPos(self.current_pos + dy * self.panning_steps.normal)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onZoom()
|
function ReaderRolling:onZoom()
|
||||||
--@TODO re-read doc_height info after font or lineheight changes 05.06 2012 (houqp)
|
--@TODO re-read doc_height info after font or lineheight changes 05.06 2012 (houqp)
|
||||||
self:updatePos()
|
self:updatePos()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
remember to signal this event when the document has been zoomed,
|
remember to signal this event when the document has been zoomed,
|
||||||
font has been changed, or line height has been changed.
|
font has been changed, or line height has been changed.
|
||||||
--]]
|
--]]
|
||||||
function ReaderRolling:onUpdatePos()
|
function ReaderRolling:onUpdatePos()
|
||||||
UIManager:scheduleIn(0.1, function () self:updatePos() end)
|
UIManager:scheduleIn(0.1, function () self:updatePos() end)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:updatePos()
|
function ReaderRolling:updatePos()
|
||||||
-- reread document height
|
-- reread document height
|
||||||
self.ui.document:_readMetadata()
|
self.ui.document:_readMetadata()
|
||||||
-- update self.current_pos if the height of document has been changed.
|
-- update self.current_pos if the height of document has been changed.
|
||||||
local new_height = self.ui.document.info.doc_height
|
local new_height = self.ui.document.info.doc_height
|
||||||
local new_page = self.ui.document.info.number_of_pages
|
local new_page = self.ui.document.info.number_of_pages
|
||||||
if self.old_doc_height ~= new_height or self.old_page ~= new_page then
|
if self.old_doc_height ~= new_height or self.old_page ~= new_page then
|
||||||
self:gotoXPointer(self.ui.document:getXPointer())
|
self:gotoXPointer(self.ui.document:getXPointer())
|
||||||
self.old_doc_height = new_height
|
self.old_doc_height = new_height
|
||||||
self.old_page = new_page
|
self.old_page = new_page
|
||||||
self.ui:handleEvent(Event:new("UpdateToc"))
|
self.ui:handleEvent(Event:new("UpdateToc"))
|
||||||
end
|
end
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onUpdateXPointer()
|
function ReaderRolling:onUpdateXPointer()
|
||||||
local xp = self.ui.document:getXPointer()
|
local xp = self.ui.document:getXPointer()
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getPageFromXPointer(xp)))
|
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getPageFromXPointer(xp)))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("PosUpdate", self.ui.document:getPosFromXPointer(xp)))
|
self.ui:handleEvent(Event:new("PosUpdate", self.ui.document:getPosFromXPointer(xp)))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onChangeViewMode()
|
function ReaderRolling:onChangeViewMode()
|
||||||
self.ui.document:_readMetadata()
|
self.ui.document:_readMetadata()
|
||||||
self.old_doc_height = self.ui.document.info.doc_height
|
self.old_doc_height = self.ui.document.info.doc_height
|
||||||
self.old_page = self.ui.document.info.number_of_pages
|
self.old_page = self.ui.document.info.number_of_pages
|
||||||
self.ui:handleEvent(Event:new("UpdateToc"))
|
self.ui:handleEvent(Event:new("UpdateToc"))
|
||||||
self:gotoXPointer(self.ui.document:getXPointer())
|
self:gotoXPointer(self.ui.document:getXPointer())
|
||||||
if self.view.view_mode == "scroll" then
|
if self.view.view_mode == "scroll" then
|
||||||
self.current_pos = self.ui.document:getCurrentPos()
|
self.current_pos = self.ui.document:getCurrentPos()
|
||||||
else
|
else
|
||||||
self.current_page = self.ui.document:getCurrentPage()
|
self.current_page = self.ui.document:getCurrentPage()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onRedrawCurrentView()
|
function ReaderRolling:onRedrawCurrentView()
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", self.current_page))
|
self.ui:handleEvent(Event:new("PageUpdate", self.current_page))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("PosUpdate", self.current_pos))
|
self.ui:handleEvent(Event:new("PosUpdate", self.current_pos))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onSetDimensions()
|
function ReaderRolling:onSetDimensions()
|
||||||
-- update listening according to new screen dimen
|
-- update listening according to new screen dimen
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onChangeScreenMode(mode)
|
function ReaderRolling:onChangeScreenMode(mode)
|
||||||
self.ui:handleEvent(Event:new("SetScreenMode", mode))
|
self.ui:handleEvent(Event:new("SetScreenMode", mode))
|
||||||
self:onChangeViewMode()
|
self:onChangeViewMode()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
PosUpdate event is used to signal other widgets that pos has been changed.
|
PosUpdate event is used to signal other widgets that pos has been changed.
|
||||||
--]]
|
--]]
|
||||||
function ReaderRolling:gotoPos(new_pos)
|
function ReaderRolling:gotoPos(new_pos)
|
||||||
if new_pos == self.current_pos then return end
|
if new_pos == self.current_pos then return end
|
||||||
if new_pos < 0 then new_pos = 0 end
|
if new_pos < 0 then new_pos = 0 end
|
||||||
if new_pos > self.doc_height then new_pos = self.doc_height end
|
if new_pos > self.doc_height then new_pos = self.doc_height end
|
||||||
-- adjust dim_area according to new_pos
|
-- adjust dim_area according to new_pos
|
||||||
if self.view.view_mode ~= "page" and self.show_overlap_enable then
|
if self.view.view_mode ~= "page" and self.show_overlap_enable then
|
||||||
local panned_step = new_pos - self.current_pos
|
local panned_step = new_pos - self.current_pos
|
||||||
self.view.dim_area.x = 0
|
self.view.dim_area.x = 0
|
||||||
self.view.dim_area.h = self.ui.dimen.h - math.abs(panned_step)
|
self.view.dim_area.h = self.ui.dimen.h - math.abs(panned_step)
|
||||||
self.view.dim_area.w = self.ui.dimen.w
|
self.view.dim_area.w = self.ui.dimen.w
|
||||||
if panned_step < 0 then
|
if panned_step < 0 then
|
||||||
self.view.dim_area.y = self.ui.dimen.h - self.view.dim_area.h
|
self.view.dim_area.y = self.ui.dimen.h - self.view.dim_area.h
|
||||||
elseif panned_step > 0 then
|
elseif panned_step > 0 then
|
||||||
self.view.dim_area.y = 0
|
self.view.dim_area.y = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.ui:handleEvent(Event:new("PosUpdate", new_pos))
|
self.ui:handleEvent(Event:new("PosUpdate", new_pos))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:gotoPage(new_page)
|
function ReaderRolling:gotoPage(new_page)
|
||||||
self.ui.document:gotoPage(new_page)
|
self.ui.document:gotoPage(new_page)
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getCurrentPage()))
|
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getCurrentPage()))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:gotoXPointer(xpointer)
|
function ReaderRolling:gotoXPointer(xpointer)
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
self:gotoPage(self.ui.document:getPageFromXPointer(xpointer))
|
self:gotoPage(self.ui.document:getPageFromXPointer(xpointer))
|
||||||
else
|
else
|
||||||
self:gotoPos(self.ui.document:getPosFromXPointer(xpointer))
|
self:gotoPos(self.ui.document:getPosFromXPointer(xpointer))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:gotoPercent(new_percent)
|
function ReaderRolling:gotoPercent(new_percent)
|
||||||
self:gotoPos(new_percent * self.doc_height / 10000)
|
self:gotoPos(new_percent * self.doc_height / 10000)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onGotoPage(number)
|
function ReaderRolling:onGotoPage(number)
|
||||||
self:gotoPage(number)
|
self:gotoPage(number)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -375,20 +375,20 @@ currently we don't need to get page links on each page/pos update
|
|||||||
since we can check link on the fly when tapping on the screen
|
since we can check link on the fly when tapping on the screen
|
||||||
--]]
|
--]]
|
||||||
function ReaderRolling:updatePageLink()
|
function ReaderRolling:updatePageLink()
|
||||||
DEBUG("update page link")
|
DEBUG("update page link")
|
||||||
local links = self.ui.document:getPageLinks()
|
local links = self.ui.document:getPageLinks()
|
||||||
self.view.links = links
|
self.view.links = links
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:updateBatteryState()
|
function ReaderRolling:updateBatteryState()
|
||||||
DEBUG("update battery state")
|
DEBUG("update battery state")
|
||||||
if self.view.view_mode == "page" then
|
if self.view.view_mode == "page" then
|
||||||
local powerd = Device:getPowerDevice()
|
local powerd = Device:getPowerDevice()
|
||||||
local state = powerd:isCharging() and -1 or powerd:getCapacity()
|
local state = powerd:isCharging() and -1 or powerd:getCapacity()
|
||||||
if state then
|
if state then
|
||||||
self.ui.document:setBatteryState(state)
|
self.ui.document:setBatteryState(state)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderRolling
|
return ReaderRolling
|
||||||
|
|||||||
@@ -7,72 +7,72 @@ local GestureRange = require("ui/gesturerange")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderRotation = InputContainer:new{
|
local ReaderRotation = InputContainer:new{
|
||||||
ROTATE_ANGLE_THRESHOLD = 15,
|
ROTATE_ANGLE_THRESHOLD = 15,
|
||||||
current_rotation = 0
|
current_rotation = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderRotation:init()
|
function ReaderRotation:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
-- these will all generate the same event, just with different arguments
|
-- these will all generate the same event, just with different arguments
|
||||||
RotateLeft = {
|
RotateLeft = {
|
||||||
{"J"},
|
{"J"},
|
||||||
doc = _("rotate left by 90 degrees"),
|
doc = _("rotate left by 90 degrees"),
|
||||||
event = "Rotate", args = -90 },
|
event = "Rotate", args = -90 },
|
||||||
RotateRight = {
|
RotateRight = {
|
||||||
{"K"},
|
{"K"},
|
||||||
doc = _("rotate right by 90 degrees"),
|
doc = _("rotate right by 90 degrees"),
|
||||||
event = "Rotate", args = 90 },
|
event = "Rotate", args = 90 },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
RotateGes = {
|
RotateGes = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "rotate",
|
ges = "rotate",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TwoFingerPanRelease = {
|
TwoFingerPanRelease = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "two_finger_pan_release",
|
ges = "two_finger_pan_release",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: reset rotation on new document, maybe on new page?
|
-- TODO: reset rotation on new document, maybe on new page?
|
||||||
|
|
||||||
function ReaderRotation:onRotate(rotate_by)
|
function ReaderRotation:onRotate(rotate_by)
|
||||||
self.current_rotation = (self.current_rotation + rotate_by) % 360
|
self.current_rotation = (self.current_rotation + rotate_by) % 360
|
||||||
self.ui:handleEvent(Event:new("RotationUpdate", self.current_rotation))
|
self.ui:handleEvent(Event:new("RotationUpdate", self.current_rotation))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRotation:onRotateGes(arg, ges)
|
function ReaderRotation:onRotateGes(arg, ges)
|
||||||
self.rotate_angle = ges.angle
|
self.rotate_angle = ges.angle
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRotation:onTwoFingerPanRelease(arg, ges)
|
function ReaderRotation:onTwoFingerPanRelease(arg, ges)
|
||||||
if self.rotate_angle and self.rotate_angle > self.ROTATE_ANGLE_THRESHOLD then
|
if self.rotate_angle and self.rotate_angle > self.ROTATE_ANGLE_THRESHOLD then
|
||||||
if Screen:getScreenMode() == "portrait" then
|
if Screen:getScreenMode() == "portrait" then
|
||||||
self.ui:handleEvent(Event:new("SetScreenMode", "landscape"))
|
self.ui:handleEvent(Event:new("SetScreenMode", "landscape"))
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetScreenMode", "portrait"))
|
self.ui:handleEvent(Event:new("SetScreenMode", "portrait"))
|
||||||
end
|
end
|
||||||
self.rotate_angle = nil
|
self.rotate_angle = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderRotation
|
return ReaderRotation
|
||||||
|
|||||||
@@ -10,36 +10,36 @@ local DEBUG = require("dbg")
|
|||||||
local ReaderScreenshot = InputContainer:new{}
|
local ReaderScreenshot = InputContainer:new{}
|
||||||
|
|
||||||
function ReaderScreenshot:init()
|
function ReaderScreenshot:init()
|
||||||
local diagonal = math.sqrt(
|
local diagonal = math.sqrt(
|
||||||
math.pow(Screen:getWidth(), 2) +
|
math.pow(Screen:getWidth(), 2) +
|
||||||
math.pow(Screen:getHeight(), 2)
|
math.pow(Screen:getHeight(), 2)
|
||||||
)
|
)
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Screenshot = {
|
Screenshot = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "two_finger_tap",
|
ges = "two_finger_tap",
|
||||||
scale = {diagonal - Screen:scaleByDPI(100), diagonal},
|
scale = {diagonal - Screen:scaleByDPI(100), diagonal},
|
||||||
rate = 1.0,
|
rate = 1.0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderScreenshot:onScreenshot()
|
function ReaderScreenshot:onScreenshot()
|
||||||
if Device:getModel() ~= 'Kobo_phoenix' then
|
if Device:getModel() ~= 'Kobo_phoenix' then
|
||||||
os.execute("screenshot")
|
os.execute("screenshot")
|
||||||
else Screen.bb:invert()
|
else Screen.bb:invert()
|
||||||
local screenshot_name = os.date("screenshots/Screenshot_%Y-%B-%d_%Hh%M.pam")
|
local screenshot_name = os.date("screenshots/Screenshot_%Y-%B-%d_%Hh%M.pam")
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Writing screen to ")..screenshot_name,
|
text = _("Writing screen to ")..screenshot_name,
|
||||||
timeout = 2,
|
timeout = 2,
|
||||||
})
|
})
|
||||||
Screen.bb:writePAM(screenshot_name)
|
Screen.bb:writePAM(screenshot_name)
|
||||||
DEBUG(screenshot_name)
|
DEBUG(screenshot_name)
|
||||||
Screen.bb:invert()
|
Screen.bb:invert()
|
||||||
end
|
end
|
||||||
UIManager.full_refresh = true
|
UIManager.full_refresh = true
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderScreenshot
|
return ReaderScreenshot
|
||||||
|
|||||||
@@ -10,135 +10,135 @@ local Event = require("ui/event")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderToc = InputContainer:new{
|
local ReaderToc = InputContainer:new{
|
||||||
toc = nil,
|
toc = nil,
|
||||||
toc_menu_title = _("Table of contents"),
|
toc_menu_title = _("Table of contents"),
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderToc:init()
|
function ReaderToc:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ShowToc = {
|
ShowToc = {
|
||||||
{ "T" },
|
{ "T" },
|
||||||
doc = _("show Table of Content menu") },
|
doc = _("show Table of Content menu") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
ShowToc = {
|
ShowToc = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "two_finger_swipe",
|
ges = "two_finger_swipe",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
},
|
},
|
||||||
direction = "east"
|
direction = "east"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:cleanUpTocTitle(title)
|
function ReaderToc:cleanUpTocTitle(title)
|
||||||
return (title:gsub("\13", ""))
|
return (title:gsub("\13", ""))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:onSetDimensions(dimen)
|
function ReaderToc:onSetDimensions(dimen)
|
||||||
self.dimen = dimen
|
self.dimen = dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:onUpdateToc()
|
function ReaderToc:onUpdateToc()
|
||||||
self.toc = nil
|
self.toc = nil
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:fillToc()
|
function ReaderToc:fillToc()
|
||||||
self.toc = self.ui.document:getToc()
|
self.toc = self.ui.document:getToc()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- _getTocTitleByPage wrapper, so specific reader
|
-- _getTocTitleByPage wrapper, so specific reader
|
||||||
-- can tranform pageno according its need
|
-- can tranform pageno according its need
|
||||||
function ReaderToc:getTocTitleByPage(pn_or_xp)
|
function ReaderToc:getTocTitleByPage(pn_or_xp)
|
||||||
local page = pn_or_xp
|
local page = pn_or_xp
|
||||||
if type(pn_or_xp) == "string" then
|
if type(pn_or_xp) == "string" then
|
||||||
page = self.ui.document:getPageFromXPointer(pn_or_xp)
|
page = self.ui.document:getPageFromXPointer(pn_or_xp)
|
||||||
end
|
end
|
||||||
return self:_getTocTitleByPage(page)
|
return self:_getTocTitleByPage(page)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:_getTocTitleByPage(pageno)
|
function ReaderToc:_getTocTitleByPage(pageno)
|
||||||
if not self.toc then
|
if not self.toc then
|
||||||
-- build toc when needed.
|
-- build toc when needed.
|
||||||
self:fillToc()
|
self:fillToc()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- no table of content
|
-- no table of content
|
||||||
if #self.toc == 0 then
|
if #self.toc == 0 then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local pre_entry = self.toc[1]
|
local pre_entry = self.toc[1]
|
||||||
for _k,_v in ipairs(self.toc) do
|
for _k,_v in ipairs(self.toc) do
|
||||||
if _v.page > pageno then
|
if _v.page > pageno then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
pre_entry = _v
|
pre_entry = _v
|
||||||
end
|
end
|
||||||
return self:cleanUpTocTitle(pre_entry.title)
|
return self:cleanUpTocTitle(pre_entry.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:getTocTitleOfCurrentPage()
|
function ReaderToc:getTocTitleOfCurrentPage()
|
||||||
return self:getTocTitleByPage(self.pageno)
|
return self:getTocTitleByPage(self.pageno)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:onShowToc()
|
function ReaderToc:onShowToc()
|
||||||
if not self.toc then
|
if not self.toc then
|
||||||
self:fillToc()
|
self:fillToc()
|
||||||
end
|
end
|
||||||
-- build menu items
|
-- build menu items
|
||||||
if #self.toc > 0 and not self.toc[1].text then
|
if #self.toc > 0 and not self.toc[1].text then
|
||||||
for _,v in ipairs(self.toc) do
|
for _,v in ipairs(self.toc) do
|
||||||
v.text = (" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title)
|
v.text = (" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title)
|
||||||
v.mandatory = v.page
|
v.mandatory = v.page
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local menu_container = CenterContainer:new{
|
local menu_container = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
}
|
}
|
||||||
|
|
||||||
local toc_menu = Menu:new{
|
local toc_menu = Menu:new{
|
||||||
title = _("Table of Contents"),
|
title = _("Table of Contents"),
|
||||||
item_table = self.toc,
|
item_table = self.toc,
|
||||||
ui = self.ui,
|
ui = self.ui,
|
||||||
width = Screen:getWidth()-50,
|
width = Screen:getWidth()-50,
|
||||||
height = Screen:getHeight()-50,
|
height = Screen:getHeight()-50,
|
||||||
show_parent = menu_container,
|
show_parent = menu_container,
|
||||||
}
|
}
|
||||||
|
|
||||||
table.insert(menu_container, toc_menu)
|
table.insert(menu_container, toc_menu)
|
||||||
|
|
||||||
function toc_menu:onMenuChoice(item)
|
function toc_menu:onMenuChoice(item)
|
||||||
self.ui:handleEvent(Event:new("PageUpdate", item.page))
|
self.ui:handleEvent(Event:new("PageUpdate", item.page))
|
||||||
end
|
end
|
||||||
|
|
||||||
toc_menu.close_callback = function()
|
toc_menu.close_callback = function()
|
||||||
UIManager:close(menu_container)
|
UIManager:close(menu_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
UIManager:show(menu_container)
|
UIManager:show(menu_container)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderToc:addToMainMenu(tab_item_table)
|
function ReaderToc:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.navi, {
|
table.insert(tab_item_table.navi, {
|
||||||
text = self.toc_menu_title,
|
text = self.toc_menu_title,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:onShowToc()
|
self:onShowToc()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderToc
|
return ReaderToc
|
||||||
|
|||||||
@@ -6,121 +6,121 @@ local _ = require("gettext")
|
|||||||
-- lfs
|
-- lfs
|
||||||
|
|
||||||
local ReaderTypeset = InputContainer:new{
|
local ReaderTypeset = InputContainer:new{
|
||||||
css_menu_title = _("Set render style"),
|
css_menu_title = _("Set render style"),
|
||||||
css = nil,
|
css = nil,
|
||||||
internal_css = true,
|
internal_css = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderTypeset:init()
|
function ReaderTypeset:init()
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:onReadSettings(config)
|
function ReaderTypeset:onReadSettings(config)
|
||||||
self.css = config:readSetting("css")
|
self.css = config:readSetting("css")
|
||||||
if self.css and self.css ~= "" then
|
if self.css and self.css ~= "" then
|
||||||
self.ui.document:setStyleSheet(self.css)
|
self.ui.document:setStyleSheet(self.css)
|
||||||
else
|
else
|
||||||
self.ui.document:setStyleSheet(self.ui.document.default_css)
|
self.ui.document:setStyleSheet(self.ui.document.default_css)
|
||||||
self.css = self.ui.document.default_css
|
self.css = self.ui.document.default_css
|
||||||
end
|
end
|
||||||
|
|
||||||
-- default to enable embedded css
|
-- default to enable embedded css
|
||||||
self.embedded_css = config:readSetting("embedded_css") or true
|
self.embedded_css = config:readSetting("embedded_css") or true
|
||||||
self.ui.document:setEmbeddedStyleSheet(self.embedded_css and 1 or 0)
|
self.ui.document:setEmbeddedStyleSheet(self.embedded_css and 1 or 0)
|
||||||
|
|
||||||
-- set page margins
|
-- set page margins
|
||||||
self:onSetPageMargins(config:readSetting("copt_page_margins") or DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM)
|
self:onSetPageMargins(config:readSetting("copt_page_margins") or DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:onSaveSettings()
|
function ReaderTypeset:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("css", self.css)
|
self.ui.doc_settings:saveSetting("css", self.css)
|
||||||
self.ui.doc_settings:saveSetting("embedded_css", self.embedded_css)
|
self.ui.doc_settings:saveSetting("embedded_css", self.embedded_css)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:onToggleEmbeddedStyleSheet(toggle)
|
function ReaderTypeset:onToggleEmbeddedStyleSheet(toggle)
|
||||||
self:toggleEmbeddedStyleSheet(toggle)
|
self:toggleEmbeddedStyleSheet(toggle)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:genStyleSheetMenu()
|
function ReaderTypeset:genStyleSheetMenu()
|
||||||
local file_list = {
|
local file_list = {
|
||||||
{
|
{
|
||||||
text = _("clear all external styles"),
|
text = _("clear all external styles"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:setStyleSheet(nil)
|
self:setStyleSheet(nil)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Auto"),
|
text = _("Auto"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:setStyleSheet(self.ui.document.default_css)
|
self:setStyleSheet(self.ui.document.default_css)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for f in lfs.dir("./data") do
|
for f in lfs.dir("./data") do
|
||||||
if lfs.attributes("./data/"..f, "mode") == "file" and string.match(f, "%.css$") then
|
if lfs.attributes("./data/"..f, "mode") == "file" and string.match(f, "%.css$") then
|
||||||
table.insert(file_list, {
|
table.insert(file_list, {
|
||||||
text = f,
|
text = f,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:setStyleSheet("./data/"..f)
|
self:setStyleSheet("./data/"..f)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return file_list
|
return file_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:setStyleSheet(new_css)
|
function ReaderTypeset:setStyleSheet(new_css)
|
||||||
if new_css ~= self.css then
|
if new_css ~= self.css then
|
||||||
--DEBUG("setting css to ", new_css)
|
--DEBUG("setting css to ", new_css)
|
||||||
self.css = new_css
|
self.css = new_css
|
||||||
if new_css == nil then
|
if new_css == nil then
|
||||||
new_css = ""
|
new_css = ""
|
||||||
end
|
end
|
||||||
self.ui.document:setStyleSheet(new_css)
|
self.ui.document:setStyleSheet(new_css)
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:setEmbededStyleSheetOnly()
|
function ReaderTypeset:setEmbededStyleSheetOnly()
|
||||||
if self.css ~= nil then
|
if self.css ~= nil then
|
||||||
-- clear applied css
|
-- clear applied css
|
||||||
self.ui.document:setStyleSheet("")
|
self.ui.document:setStyleSheet("")
|
||||||
self.ui.document:setEmbeddedStyleSheet(1)
|
self.ui.document:setEmbeddedStyleSheet(1)
|
||||||
self.css = nil
|
self.css = nil
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:toggleEmbeddedStyleSheet(toggle)
|
function ReaderTypeset:toggleEmbeddedStyleSheet(toggle)
|
||||||
if not toggle then
|
if not toggle then
|
||||||
self.embedded_css = false
|
self.embedded_css = false
|
||||||
self:setStyleSheet(self.ui.document.default_css)
|
self:setStyleSheet(self.ui.document.default_css)
|
||||||
self.ui.document:setEmbeddedStyleSheet(0)
|
self.ui.document:setEmbeddedStyleSheet(0)
|
||||||
else
|
else
|
||||||
self.embedded_css = true
|
self.embedded_css = true
|
||||||
--self:setStyleSheet(self.ui.document.default_css)
|
--self:setStyleSheet(self.ui.document.default_css)
|
||||||
self.ui.document:setEmbeddedStyleSheet(1)
|
self.ui.document:setEmbeddedStyleSheet(1)
|
||||||
end
|
end
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:addToMainMenu(tab_item_table)
|
function ReaderTypeset:addToMainMenu(tab_item_table)
|
||||||
-- insert table to main reader menu
|
-- insert table to main reader menu
|
||||||
table.insert(tab_item_table.typeset, {
|
table.insert(tab_item_table.typeset, {
|
||||||
text = self.css_menu_title,
|
text = self.css_menu_title,
|
||||||
sub_item_table = self:genStyleSheetMenu(),
|
sub_item_table = self:genStyleSheetMenu(),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderTypeset:onSetPageMargins(margins)
|
function ReaderTypeset:onSetPageMargins(margins)
|
||||||
local left = Screen:scaleByDPI(margins[1])
|
local left = Screen:scaleByDPI(margins[1])
|
||||||
local top = Screen:scaleByDPI(margins[2])
|
local top = Screen:scaleByDPI(margins[2])
|
||||||
local right = Screen:scaleByDPI(margins[3])
|
local right = Screen:scaleByDPI(margins[3])
|
||||||
local bottom = Screen:scaleByDPI(margins[4])
|
local bottom = Screen:scaleByDPI(margins[4])
|
||||||
self.ui.document:setPageMargins(left, top, right, bottom)
|
self.ui.document:setPageMargins(left, top, right, bottom)
|
||||||
self.ui:handleEvent(Event:new("UpdatePos"))
|
self.ui:handleEvent(Event:new("UpdatePos"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderTypeset
|
return ReaderTypeset
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,315 +9,315 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ReaderZooming = InputContainer:new{
|
local ReaderZooming = InputContainer:new{
|
||||||
zoom = 1.0,
|
zoom = 1.0,
|
||||||
-- default to nil so we can trigger ZoomModeUpdate events on start up
|
-- default to nil so we can trigger ZoomModeUpdate events on start up
|
||||||
zoom_mode = nil,
|
zoom_mode = nil,
|
||||||
DEFAULT_ZOOM_MODE = "page",
|
DEFAULT_ZOOM_MODE = "page",
|
||||||
current_page = 1,
|
current_page = 1,
|
||||||
rotation = 0
|
rotation = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderZooming:init()
|
function ReaderZooming:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
ZoomIn = {
|
ZoomIn = {
|
||||||
{ "Shift", Input.group.PgFwd },
|
{ "Shift", Input.group.PgFwd },
|
||||||
doc = _("zoom in"),
|
doc = _("zoom in"),
|
||||||
event = "Zoom", args = "in"
|
event = "Zoom", args = "in"
|
||||||
},
|
},
|
||||||
ZoomOut = {
|
ZoomOut = {
|
||||||
{ "Shift", Input.group.PgBack },
|
{ "Shift", Input.group.PgBack },
|
||||||
doc = _("zoom out"),
|
doc = _("zoom out"),
|
||||||
event = "Zoom", args = "out"
|
event = "Zoom", args = "out"
|
||||||
},
|
},
|
||||||
ZoomToFitPage = {
|
ZoomToFitPage = {
|
||||||
{ "A" },
|
{ "A" },
|
||||||
doc = _("zoom to fit page"),
|
doc = _("zoom to fit page"),
|
||||||
event = "SetZoomMode", args = "page"
|
event = "SetZoomMode", args = "page"
|
||||||
},
|
},
|
||||||
ZoomToFitContent = {
|
ZoomToFitContent = {
|
||||||
{ "Shift", "A" },
|
{ "Shift", "A" },
|
||||||
doc = _("zoom to fit content"),
|
doc = _("zoom to fit content"),
|
||||||
event = "SetZoomMode", args = "content"
|
event = "SetZoomMode", args = "content"
|
||||||
},
|
},
|
||||||
ZoomToFitPageWidth = {
|
ZoomToFitPageWidth = {
|
||||||
{ "S" },
|
{ "S" },
|
||||||
doc = _("zoom to fit page width"),
|
doc = _("zoom to fit page width"),
|
||||||
event = "SetZoomMode", args = "pagewidth"
|
event = "SetZoomMode", args = "pagewidth"
|
||||||
},
|
},
|
||||||
ZoomToFitContentWidth = {
|
ZoomToFitContentWidth = {
|
||||||
{ "Shift", "S" },
|
{ "Shift", "S" },
|
||||||
doc = _("zoom to fit content width"),
|
doc = _("zoom to fit content width"),
|
||||||
event = "SetZoomMode", args = "contentwidth"
|
event = "SetZoomMode", args = "contentwidth"
|
||||||
},
|
},
|
||||||
ZoomToFitPageHeight = {
|
ZoomToFitPageHeight = {
|
||||||
{ "D" },
|
{ "D" },
|
||||||
doc = _("zoom to fit page height"),
|
doc = _("zoom to fit page height"),
|
||||||
event = "SetZoomMode", args = "pageheight"
|
event = "SetZoomMode", args = "pageheight"
|
||||||
},
|
},
|
||||||
ZoomToFitContentHeight = {
|
ZoomToFitContentHeight = {
|
||||||
{ "Shift", "D" },
|
{ "Shift", "D" },
|
||||||
doc = _("zoom to fit content height"),
|
doc = _("zoom to fit content height"),
|
||||||
event = "SetZoomMode", args = "contentheight"
|
event = "SetZoomMode", args = "contentheight"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Spread = {
|
Spread = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "spread",
|
ges = "spread",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Pinch = {
|
Pinch = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "pinch",
|
ges = "pinch",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ToggleFreeZoom = {
|
ToggleFreeZoom = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "double_tap",
|
ges = "double_tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onReadSettings(config)
|
function ReaderZooming:onReadSettings(config)
|
||||||
-- @TODO config file from old code base uses globalzoom_mode
|
-- @TODO config file from old code base uses globalzoom_mode
|
||||||
-- instead of zoom_mode, we need to handle this imcompatibility
|
-- instead of zoom_mode, we need to handle this imcompatibility
|
||||||
-- 04.12 2012 (houqp)
|
-- 04.12 2012 (houqp)
|
||||||
local zoom_mode = config:readSetting("zoom_mode")
|
local zoom_mode = config:readSetting("zoom_mode")
|
||||||
if not zoom_mode then
|
if not zoom_mode then
|
||||||
zoom_mode = self.DEFAULT_ZOOM_MODE
|
zoom_mode = self.DEFAULT_ZOOM_MODE
|
||||||
end
|
end
|
||||||
self:setZoomMode(zoom_mode)
|
self:setZoomMode(zoom_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onSaveSettings()
|
function ReaderZooming:onSaveSettings()
|
||||||
self.ui.doc_settings:saveSetting("zoom_mode", self.zoom_mode)
|
self.ui.doc_settings:saveSetting("zoom_mode", self.zoom_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onSpread(arg, ges)
|
function ReaderZooming:onSpread(arg, ges)
|
||||||
if ges.direction == "horizontal" then
|
if ges.direction == "horizontal" then
|
||||||
self:genSetZoomModeCallBack("contentwidth")()
|
self:genSetZoomModeCallBack("contentwidth")()
|
||||||
elseif ges.direction == "vertical" then
|
elseif ges.direction == "vertical" then
|
||||||
self:genSetZoomModeCallBack("contentheight")()
|
self:genSetZoomModeCallBack("contentheight")()
|
||||||
elseif ges.direction == "diagonal" then
|
elseif ges.direction == "diagonal" then
|
||||||
self:genSetZoomModeCallBack("content")()
|
self:genSetZoomModeCallBack("content")()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onPinch(arg, ges)
|
function ReaderZooming:onPinch(arg, ges)
|
||||||
if ges.direction == "diagonal" then
|
if ges.direction == "diagonal" then
|
||||||
self:genSetZoomModeCallBack("page")()
|
self:genSetZoomModeCallBack("page")()
|
||||||
elseif ges.direction == "horizontal" then
|
elseif ges.direction == "horizontal" then
|
||||||
self:genSetZoomModeCallBack("pagewidth")()
|
self:genSetZoomModeCallBack("pagewidth")()
|
||||||
elseif ges.direction == "vertical" then
|
elseif ges.direction == "vertical" then
|
||||||
self:genSetZoomModeCallBack("pageheight")()
|
self:genSetZoomModeCallBack("pageheight")()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onToggleFreeZoom(arg, ges)
|
function ReaderZooming:onToggleFreeZoom(arg, ges)
|
||||||
if self.zoom_mode ~= "free" then
|
if self.zoom_mode ~= "free" then
|
||||||
self.orig_zoom = self.zoom
|
self.orig_zoom = self.zoom
|
||||||
self.orig_zoom_mode = self.zoom_mode
|
self.orig_zoom_mode = self.zoom_mode
|
||||||
local xpos, ypos
|
local xpos, ypos
|
||||||
self.zoom, xpos, ypos = self:getRegionalZoomCenter(self.current_page, ges.pos)
|
self.zoom, xpos, ypos = self:getRegionalZoomCenter(self.current_page, ges.pos)
|
||||||
DEBUG("zoom center", self.zoom, xpos, ypos)
|
DEBUG("zoom center", self.zoom, xpos, ypos)
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", "free"))
|
self.ui:handleEvent(Event:new("SetZoomMode", "free"))
|
||||||
if xpos == nil or ypos == nil then
|
if xpos == nil or ypos == nil then
|
||||||
xpos = ges.pos.x * self.zoom / self.orig_zoom
|
xpos = ges.pos.x * self.zoom / self.orig_zoom
|
||||||
ypos = ges.pos.y * self.zoom / self.orig_zoom
|
ypos = ges.pos.y * self.zoom / self.orig_zoom
|
||||||
end
|
end
|
||||||
self.view:SetZoomCenter(xpos, ypos)
|
self.view:SetZoomCenter(xpos, ypos)
|
||||||
else
|
else
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode or "page"))
|
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode or "page"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onSetDimensions(dimensions)
|
function ReaderZooming:onSetDimensions(dimensions)
|
||||||
-- we were resized
|
-- we were resized
|
||||||
self.dimen = dimensions
|
self.dimen = dimensions
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onRestoreDimensions(dimensions)
|
function ReaderZooming:onRestoreDimensions(dimensions)
|
||||||
-- we were resized
|
-- we were resized
|
||||||
self.dimen = dimensions
|
self.dimen = dimensions
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onRotationUpdate(rotation)
|
function ReaderZooming:onRotationUpdate(rotation)
|
||||||
self.rotation = rotation
|
self.rotation = rotation
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onZoom(direction)
|
function ReaderZooming:onZoom(direction)
|
||||||
DEBUG("zoom", direction)
|
DEBUG("zoom", direction)
|
||||||
if direction == "in" then
|
if direction == "in" then
|
||||||
self.zoom = self.zoom * 1.333333
|
self.zoom = self.zoom * 1.333333
|
||||||
elseif direction == "out" then
|
elseif direction == "out" then
|
||||||
self.zoom = self.zoom * 0.75
|
self.zoom = self.zoom * 0.75
|
||||||
end
|
end
|
||||||
DEBUG("zoom is now at", self.zoom)
|
DEBUG("zoom is now at", self.zoom)
|
||||||
self:onSetZoomMode("free")
|
self:onSetZoomMode("free")
|
||||||
self.view:onZoomUpdate(self.zoom)
|
self.view:onZoomUpdate(self.zoom)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onSetZoomMode(new_mode)
|
function ReaderZooming:onSetZoomMode(new_mode)
|
||||||
self.view.zoom_mode = new_mode
|
self.view.zoom_mode = new_mode
|
||||||
if self.zoom_mode ~= new_mode then
|
if self.zoom_mode ~= new_mode then
|
||||||
DEBUG("setting zoom mode to", new_mode)
|
DEBUG("setting zoom mode to", new_mode)
|
||||||
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
|
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
|
||||||
self.zoom_mode = new_mode
|
self.zoom_mode = new_mode
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onPageUpdate(new_page_no)
|
function ReaderZooming:onPageUpdate(new_page_no)
|
||||||
self.current_page = new_page_no
|
self.current_page = new_page_no
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:onReZoom()
|
function ReaderZooming:onReZoom()
|
||||||
self:setZoom()
|
self:setZoom()
|
||||||
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:getZoom(pageno)
|
function ReaderZooming:getZoom(pageno)
|
||||||
-- check if we're in bbox mode and work on bbox if that's the case
|
-- check if we're in bbox mode and work on bbox if that's the case
|
||||||
local zoom = nil
|
local zoom = nil
|
||||||
local page_size = {}
|
local page_size = {}
|
||||||
if self.zoom_mode == "content"
|
if self.zoom_mode == "content"
|
||||||
or self.zoom_mode == "contentwidth"
|
or self.zoom_mode == "contentwidth"
|
||||||
or self.zoom_mode == "contentheight" then
|
or self.zoom_mode == "contentheight" then
|
||||||
local ubbox_dimen = self.ui.document:getUsedBBoxDimensions(pageno, 1)
|
local ubbox_dimen = self.ui.document:getUsedBBoxDimensions(pageno, 1)
|
||||||
--self.view:handleEvent(Event:new("BBoxUpdate", page_size))
|
--self.view:handleEvent(Event:new("BBoxUpdate", page_size))
|
||||||
self.view:onBBoxUpdate(ubbox_dimen)
|
self.view:onBBoxUpdate(ubbox_dimen)
|
||||||
page_size = ubbox_dimen
|
page_size = ubbox_dimen
|
||||||
else
|
else
|
||||||
-- otherwise, operate on full page
|
-- otherwise, operate on full page
|
||||||
self.view:onBBoxUpdate(nil)
|
self.view:onBBoxUpdate(nil)
|
||||||
page_size = self.ui.document:getNativePageDimensions(pageno)
|
page_size = self.ui.document:getNativePageDimensions(pageno)
|
||||||
--page_size = self.ui.document:getPageDimensions(pageno, 1, 0)
|
--page_size = self.ui.document:getPageDimensions(pageno, 1, 0)
|
||||||
end
|
end
|
||||||
-- calculate zoom value:
|
-- calculate zoom value:
|
||||||
local zoom_w = self.dimen.w / page_size.w
|
local zoom_w = self.dimen.w / page_size.w
|
||||||
local zoom_h = self.dimen.h / page_size.h
|
local zoom_h = self.dimen.h / page_size.h
|
||||||
if self.rotation % 180 ~= 0 then
|
if self.rotation % 180 ~= 0 then
|
||||||
-- rotated by 90 or 270 degrees
|
-- rotated by 90 or 270 degrees
|
||||||
zoom_w = self.dimen.w / page_size.h
|
zoom_w = self.dimen.w / page_size.h
|
||||||
zoom_h = self.dimen.h / page_size.w
|
zoom_h = self.dimen.h / page_size.w
|
||||||
end
|
end
|
||||||
if self.zoom_mode == "content" or self.zoom_mode == "page" then
|
if self.zoom_mode == "content" or self.zoom_mode == "page" then
|
||||||
if zoom_w < zoom_h then
|
if zoom_w < zoom_h then
|
||||||
zoom = zoom_w
|
zoom = zoom_w
|
||||||
else
|
else
|
||||||
zoom = zoom_h
|
zoom = zoom_h
|
||||||
end
|
end
|
||||||
elseif self.zoom_mode == "contentwidth" or self.zoom_mode == "pagewidth" then
|
elseif self.zoom_mode == "contentwidth" or self.zoom_mode == "pagewidth" then
|
||||||
zoom = zoom_w
|
zoom = zoom_w
|
||||||
elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then
|
elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then
|
||||||
zoom = zoom_h
|
zoom = zoom_h
|
||||||
elseif self.zoom_mode == "free" then
|
elseif self.zoom_mode == "free" then
|
||||||
zoom = self.zoom
|
zoom = self.zoom
|
||||||
end
|
end
|
||||||
return zoom
|
return zoom
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:getRegionalZoomCenter(pageno, pos)
|
function ReaderZooming:getRegionalZoomCenter(pageno, pos)
|
||||||
local p_pos = self.view:getSinglePagePosition(pos)
|
local p_pos = self.view:getSinglePagePosition(pos)
|
||||||
local page_size = self.ui.document:getNativePageDimensions(pageno)
|
local page_size = self.ui.document:getNativePageDimensions(pageno)
|
||||||
local pos_x = p_pos.x / page_size.w / p_pos.zoom
|
local pos_x = p_pos.x / page_size.w / p_pos.zoom
|
||||||
local pos_y = p_pos.y / page_size.h / p_pos.zoom
|
local pos_y = p_pos.y / page_size.h / p_pos.zoom
|
||||||
local regions = self.ui.document:getPageRegions(pageno)
|
local regions = self.ui.document:getPageRegions(pageno)
|
||||||
DEBUG("get page regions", regions)
|
DEBUG("get page regions", regions)
|
||||||
local margin = self.ui.document.configurable.page_margin * Screen:getDPI()
|
local margin = self.ui.document.configurable.page_margin * Screen:getDPI()
|
||||||
for i = 1, #regions do
|
for i = 1, #regions do
|
||||||
if regions[i].x0 <= pos_x and pos_x <= regions[i].x1
|
if regions[i].x0 <= pos_x and pos_x <= regions[i].x1
|
||||||
and regions[i].y0 <= pos_y and pos_y <= regions[i].y1 then
|
and regions[i].y0 <= pos_y and pos_y <= regions[i].y1 then
|
||||||
local zoom = 1/(regions[i].x1 - regions[i].x0)
|
local zoom = 1/(regions[i].x1 - regions[i].x0)
|
||||||
zoom = zoom/(1 + 3*margin/zoom/page_size.w)
|
zoom = zoom/(1 + 3*margin/zoom/page_size.w)
|
||||||
local xpos = (regions[i].x0 + regions[i].x1)/2 * zoom * page_size.w
|
local xpos = (regions[i].x0 + regions[i].x1)/2 * zoom * page_size.w
|
||||||
local ypos = p_pos.y / p_pos.zoom * zoom
|
local ypos = p_pos.y / p_pos.zoom * zoom
|
||||||
return zoom, xpos, ypos
|
return zoom, xpos, ypos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return 2
|
return 2
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:setZoom()
|
function ReaderZooming:setZoom()
|
||||||
if not self.dimen then
|
if not self.dimen then
|
||||||
self.dimen = self.ui.dimen
|
self.dimen = self.ui.dimen
|
||||||
end
|
end
|
||||||
self.zoom = self:getZoom(self.current_page)
|
self.zoom = self:getZoom(self.current_page)
|
||||||
self.ui:handleEvent(Event:new("ZoomUpdate", self.zoom))
|
self.ui:handleEvent(Event:new("ZoomUpdate", self.zoom))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:genSetZoomModeCallBack(mode)
|
function ReaderZooming:genSetZoomModeCallBack(mode)
|
||||||
return function()
|
return function()
|
||||||
self:setZoomMode(mode)
|
self:setZoomMode(mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:setZoomMode(mode)
|
function ReaderZooming:setZoomMode(mode)
|
||||||
self.ui:handleEvent(Event:new("SetZoomMode", mode))
|
self.ui:handleEvent(Event:new("SetZoomMode", mode))
|
||||||
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderZooming:addToMainMenu(tab_item_table)
|
function ReaderZooming:addToMainMenu(tab_item_table)
|
||||||
if self.ui.document.info.has_pages then
|
if self.ui.document.info.has_pages then
|
||||||
table.insert(tab_item_table.typeset, {
|
table.insert(tab_item_table.typeset, {
|
||||||
text = _("Switch zoom mode"),
|
text = _("Switch zoom mode"),
|
||||||
sub_item_table = {
|
sub_item_table = {
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit content width"),
|
text = _("Zoom to fit content width"),
|
||||||
callback = self:genSetZoomModeCallBack("contentwidth")
|
callback = self:genSetZoomModeCallBack("contentwidth")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit content height"),
|
text = _("Zoom to fit content height"),
|
||||||
callback = self:genSetZoomModeCallBack("contentheight")
|
callback = self:genSetZoomModeCallBack("contentheight")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit page width"),
|
text = _("Zoom to fit page width"),
|
||||||
callback = self:genSetZoomModeCallBack("pagewidth")
|
callback = self:genSetZoomModeCallBack("pagewidth")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit page height"),
|
text = _("Zoom to fit page height"),
|
||||||
callback = self:genSetZoomModeCallBack("pageheight")
|
callback = self:genSetZoomModeCallBack("pageheight")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit content"),
|
text = _("Zoom to fit content"),
|
||||||
callback = self:genSetZoomModeCallBack("content")
|
callback = self:genSetZoomModeCallBack("content")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Zoom to fit page"),
|
text = _("Zoom to fit page"),
|
||||||
callback = self:genSetZoomModeCallBack("page")
|
callback = self:genSetZoomModeCallBack("page")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderZooming
|
return ReaderZooming
|
||||||
|
|||||||
@@ -39,256 +39,256 @@ it works using data gathered from a document interface
|
|||||||
]]--
|
]]--
|
||||||
|
|
||||||
local ReaderUI = InputContainer:new{
|
local ReaderUI = InputContainer:new{
|
||||||
key_events = {
|
key_events = {
|
||||||
Close = { { "Home" },
|
Close = { { "Home" },
|
||||||
doc = _("close document"), event = "Close" },
|
doc = _("close document"), event = "Close" },
|
||||||
},
|
},
|
||||||
active_widgets = {},
|
active_widgets = {},
|
||||||
|
|
||||||
-- our own size
|
-- our own size
|
||||||
dimen = Geom:new{ w = 400, h = 600 },
|
dimen = Geom:new{ w = 400, h = 600 },
|
||||||
-- if we have a parent container, it must be referenced for now
|
-- if we have a parent container, it must be referenced for now
|
||||||
dialog = nil,
|
dialog = nil,
|
||||||
|
|
||||||
-- the document interface
|
-- the document interface
|
||||||
document = nil,
|
document = nil,
|
||||||
|
|
||||||
-- initial page or percent inside document on opening
|
-- initial page or percent inside document on opening
|
||||||
start_pos = nil,
|
start_pos = nil,
|
||||||
-- password for document unlock
|
-- password for document unlock
|
||||||
password = nil,
|
password = nil,
|
||||||
|
|
||||||
postInitCallback = nil,
|
postInitCallback = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderUI:init()
|
function ReaderUI:init()
|
||||||
self.postInitCallback = {}
|
self.postInitCallback = {}
|
||||||
-- if we are not the top level dialog ourselves, it must be given in the table
|
-- if we are not the top level dialog ourselves, it must be given in the table
|
||||||
if not self.dialog then
|
if not self.dialog then
|
||||||
self.dialog = self
|
self.dialog = self
|
||||||
end
|
end
|
||||||
|
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events.Back = {
|
self.key_events.Back = {
|
||||||
{ "Back" }, doc = _("close document"),
|
{ "Back" }, doc = _("close document"),
|
||||||
event = "Close" }
|
event = "Close" }
|
||||||
end
|
end
|
||||||
|
|
||||||
self.doc_settings = DocSettings:open(self.document.file)
|
self.doc_settings = DocSettings:open(self.document.file)
|
||||||
|
|
||||||
-- a view container (so it must be child #1!)
|
-- a view container (so it must be child #1!)
|
||||||
self[1] = ReaderView:new{
|
self[1] = ReaderView:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
dimen = self.dimen,
|
dimen = self.dimen,
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
}
|
}
|
||||||
-- reader menu controller
|
-- reader menu controller
|
||||||
-- hold reference to menu widget
|
-- hold reference to menu widget
|
||||||
self.menu = ReaderMenu:new{
|
self.menu = ReaderMenu:new{
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
-- link
|
-- link
|
||||||
table.insert(self, ReaderLink:new{
|
table.insert(self, ReaderLink:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
-- text highlight
|
-- text highlight
|
||||||
table.insert(self, ReaderHighlight:new{
|
table.insert(self, ReaderHighlight:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
-- menu widget should be registered after link widget and highlight widget
|
-- menu widget should be registered after link widget and highlight widget
|
||||||
-- so that taps on link and highlight areas won't popup reader menu
|
-- so that taps on link and highlight areas won't popup reader menu
|
||||||
table.insert(self, self.menu)
|
table.insert(self, self.menu)
|
||||||
-- rotation controller
|
-- rotation controller
|
||||||
table.insert(self, ReaderRotation:new{
|
table.insert(self, ReaderRotation:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- Table of content controller
|
-- Table of content controller
|
||||||
-- hold reference to bm widget
|
-- hold reference to bm widget
|
||||||
self.toc = ReaderToc:new{
|
self.toc = ReaderToc:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
table.insert(self, self.toc)
|
table.insert(self, self.toc)
|
||||||
-- bookmark controller
|
-- bookmark controller
|
||||||
table.insert(self, ReaderBookmark:new{
|
table.insert(self, ReaderBookmark:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- reader goto controller
|
-- reader goto controller
|
||||||
table.insert(self, ReaderGoto:new{
|
table.insert(self, ReaderGoto:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
-- dictionary
|
-- dictionary
|
||||||
table.insert(self, ReaderDictionary:new{
|
table.insert(self, ReaderDictionary:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
-- screenshot controller
|
-- screenshot controller
|
||||||
table.insert(self.active_widgets, ReaderScreenshot:new{
|
table.insert(self.active_widgets, ReaderScreenshot:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- frontlight controller
|
-- frontlight controller
|
||||||
if Device:hasFrontlight() then
|
if Device:hasFrontlight() then
|
||||||
table.insert(self, ReaderFrontLight:new{
|
table.insert(self, ReaderFrontLight:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
-- configuable controller
|
-- configuable controller
|
||||||
if self.document.info.configurable then
|
if self.document.info.configurable then
|
||||||
-- config panel controller
|
-- config panel controller
|
||||||
table.insert(self, ReaderConfig:new{
|
table.insert(self, ReaderConfig:new{
|
||||||
configurable = self.document.configurable,
|
configurable = self.document.configurable,
|
||||||
options = self.document.options,
|
options = self.document.options,
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
if not self.document.info.has_pages then
|
if not self.document.info.has_pages then
|
||||||
-- cre option controller
|
-- cre option controller
|
||||||
table.insert(self, ReaderCoptListener:new{
|
table.insert(self, ReaderCoptListener:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- for page specific controller
|
-- for page specific controller
|
||||||
if self.document.info.has_pages then
|
if self.document.info.has_pages then
|
||||||
-- cropping controller
|
-- cropping controller
|
||||||
table.insert(self, ReaderCropping:new{
|
table.insert(self, ReaderCropping:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
-- paging controller
|
-- paging controller
|
||||||
table.insert(self, ReaderPaging:new{
|
table.insert(self, ReaderPaging:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- zooming controller
|
-- zooming controller
|
||||||
local zoom = ReaderZooming:new{
|
local zoom = ReaderZooming:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
table.insert(self, zoom)
|
table.insert(self, zoom)
|
||||||
-- panning controller
|
-- panning controller
|
||||||
table.insert(self, ReaderPanning:new{
|
table.insert(self, ReaderPanning:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- hinting controller
|
-- hinting controller
|
||||||
table.insert(self, ReaderHinting:new{
|
table.insert(self, ReaderHinting:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
zoom = zoom,
|
zoom = zoom,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
-- make sure we load document first before calling any callback
|
-- make sure we load document first before calling any callback
|
||||||
table.insert(self.postInitCallback, function()
|
table.insert(self.postInitCallback, function()
|
||||||
self.document:loadDocument()
|
self.document:loadDocument()
|
||||||
end)
|
end)
|
||||||
-- typeset controller
|
-- typeset controller
|
||||||
table.insert(self, ReaderTypeset:new{
|
table.insert(self, ReaderTypeset:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
-- font menu
|
-- font menu
|
||||||
self.font = ReaderFont:new{
|
self.font = ReaderFont:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
table.insert(self, self.font) -- hold reference to font menu
|
table.insert(self, self.font) -- hold reference to font menu
|
||||||
-- hyphenation menu
|
-- hyphenation menu
|
||||||
self.hyphenation = ReaderHyphenation:new{
|
self.hyphenation = ReaderHyphenation:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
}
|
}
|
||||||
table.insert(self, self.hyphenation) -- hold reference to hyphenation menu
|
table.insert(self, self.hyphenation) -- hold reference to hyphenation menu
|
||||||
-- rolling controller
|
-- rolling controller
|
||||||
table.insert(self, ReaderRolling:new{
|
table.insert(self, ReaderRolling:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
-- configuable controller
|
-- configuable controller
|
||||||
if self.document.info.configurable then
|
if self.document.info.configurable then
|
||||||
if self.document.info.has_pages then
|
if self.document.info.has_pages then
|
||||||
-- kopt option controller
|
-- kopt option controller
|
||||||
table.insert(self, ReaderKoptListener:new{
|
table.insert(self, ReaderKoptListener:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
-- activity indicator
|
-- activity indicator
|
||||||
table.insert(self, ReaderActivityIndicator:new{
|
table.insert(self, ReaderActivityIndicator:new{
|
||||||
dialog = self.dialog,
|
dialog = self.dialog,
|
||||||
view = self[1],
|
view = self[1],
|
||||||
ui = self,
|
ui = self,
|
||||||
document = self.document,
|
document = self.document,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
--DEBUG(self.doc_settings)
|
--DEBUG(self.doc_settings)
|
||||||
-- we only read settings after all the widgets are initialized
|
-- we only read settings after all the widgets are initialized
|
||||||
self:handleEvent(Event:new("ReadSettings", self.doc_settings))
|
self:handleEvent(Event:new("ReadSettings", self.doc_settings))
|
||||||
|
|
||||||
for _,v in ipairs(self.postInitCallback) do
|
for _,v in ipairs(self.postInitCallback) do
|
||||||
v()
|
v()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderUI:onSetDimensions(dimen)
|
function ReaderUI:onSetDimensions(dimen)
|
||||||
self.dimen = dimen
|
self.dimen = dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderUI:saveSettings()
|
function ReaderUI:saveSettings()
|
||||||
self:handleEvent(Event:new("SaveSettings"))
|
self:handleEvent(Event:new("SaveSettings"))
|
||||||
self.doc_settings:flush()
|
self.doc_settings:flush()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderUI:onClose()
|
function ReaderUI:onClose()
|
||||||
DEBUG("closing reader")
|
DEBUG("closing reader")
|
||||||
self:saveSettings()
|
self:saveSettings()
|
||||||
if self.document ~= nil then
|
if self.document ~= nil then
|
||||||
self.document:close()
|
self.document:close()
|
||||||
self.document = nil
|
self.document = nil
|
||||||
self.start_pos = nil
|
self.start_pos = nil
|
||||||
end
|
end
|
||||||
UIManager:close(self.dialog)
|
UIManager:close(self.dialog)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReaderUI
|
return ReaderUI
|
||||||
|
|||||||
@@ -10,170 +10,170 @@ TODO: all these functions should probably be methods on Face objects
|
|||||||
local RenderText = {}
|
local RenderText = {}
|
||||||
|
|
||||||
local GlyphCache = Cache:new{
|
local GlyphCache = Cache:new{
|
||||||
max_memsize = 512*1024,
|
max_memsize = 512*1024,
|
||||||
current_memsize = 0,
|
current_memsize = 0,
|
||||||
cache = {},
|
cache = {},
|
||||||
-- this will hold the LRU order of the cache
|
-- this will hold the LRU order of the cache
|
||||||
cache_order = {}
|
cache_order = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- iterator over UTF8 encoded characters in a string
|
-- iterator over UTF8 encoded characters in a string
|
||||||
local function utf8Chars(input)
|
local function utf8Chars(input)
|
||||||
local function read_next_glyph(input, pos)
|
local function read_next_glyph(input, pos)
|
||||||
if string.len(input) < pos then return nil end
|
if string.len(input) < pos then return nil end
|
||||||
local value = string.byte(input, pos)
|
local value = string.byte(input, pos)
|
||||||
if bit.band(value, 0x80) == 0 then
|
if bit.band(value, 0x80) == 0 then
|
||||||
-- TODO: check valid ranges
|
-- TODO: check valid ranges
|
||||||
return pos+1, value, string.sub(input, pos, pos)
|
return pos+1, value, string.sub(input, pos, pos)
|
||||||
elseif bit.band(value, 0xC0) == 0x80 -- invalid, continuation
|
elseif bit.band(value, 0xC0) == 0x80 -- invalid, continuation
|
||||||
or bit.band(value, 0xF8) == 0xF8 -- 5-or-more byte sequence, illegal due to RFC3629
|
or bit.band(value, 0xF8) == 0xF8 -- 5-or-more byte sequence, illegal due to RFC3629
|
||||||
then
|
then
|
||||||
return pos+1, 0xFFFD, "\xFF\xFD"
|
return pos+1, 0xFFFD, "\xFF\xFD"
|
||||||
else
|
else
|
||||||
local glyph, bytes_left
|
local glyph, bytes_left
|
||||||
if bit.band(value, 0xE0) == 0xC0 then
|
if bit.band(value, 0xE0) == 0xC0 then
|
||||||
glyph = bit.band(value, 0x1F)
|
glyph = bit.band(value, 0x1F)
|
||||||
bytes_left = 1
|
bytes_left = 1
|
||||||
elseif bit.band(value, 0xF0) == 0xE0 then
|
elseif bit.band(value, 0xF0) == 0xE0 then
|
||||||
glyph = bit.band(value, 0x0F)
|
glyph = bit.band(value, 0x0F)
|
||||||
bytes_left = 2
|
bytes_left = 2
|
||||||
elseif bit.band(value, 0xF8) == 0xF0 then
|
elseif bit.band(value, 0xF8) == 0xF0 then
|
||||||
glyph = bit.band(value, 0x07)
|
glyph = bit.band(value, 0x07)
|
||||||
bytes_left = 3
|
bytes_left = 3
|
||||||
else
|
else
|
||||||
return pos+1, 0xFFFD, "\xFF\xFD"
|
return pos+1, 0xFFFD, "\xFF\xFD"
|
||||||
end
|
end
|
||||||
if string.len(input) < (pos + bytes_left - 1) then
|
if string.len(input) < (pos + bytes_left - 1) then
|
||||||
return pos+1, 0xFFFD, "\xFF\xFD"
|
return pos+1, 0xFFFD, "\xFF\xFD"
|
||||||
end
|
end
|
||||||
for i = pos+1, pos + bytes_left do
|
for i = pos+1, pos + bytes_left do
|
||||||
value = string.byte(input, i)
|
value = string.byte(input, i)
|
||||||
if bit.band(value, 0xC0) == 0x80 then
|
if bit.band(value, 0xC0) == 0x80 then
|
||||||
glyph = bit.bor(bit.lshift(glyph, 6), bit.band(value, 0x3F))
|
glyph = bit.bor(bit.lshift(glyph, 6), bit.band(value, 0x3F))
|
||||||
else
|
else
|
||||||
return i+1, 0xFFFD, "\xFF\xFD"
|
return i+1, 0xFFFD, "\xFF\xFD"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- TODO: check for valid ranges here!
|
-- TODO: check for valid ranges here!
|
||||||
return pos+bytes_left+1, glyph, string.sub(input, pos, pos+bytes_left)
|
return pos+bytes_left+1, glyph, string.sub(input, pos, pos+bytes_left)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return read_next_glyph, input, 1
|
return read_next_glyph, input, 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function RenderText:getGlyph(face, charcode, bold, bgcolor, fgcolor)
|
function RenderText:getGlyph(face, charcode, bold, bgcolor, fgcolor)
|
||||||
if bgcolor == nil then bgcolor = 0.0 end
|
if bgcolor == nil then bgcolor = 0.0 end
|
||||||
if fgcolor == nil then fgcolor = 1.0 end
|
if fgcolor == nil then fgcolor = 1.0 end
|
||||||
local hash = "glyph|"..face.hash.."|"..charcode.."|"..(bold and 1 or 0).."|"..bgcolor.."|"..fgcolor
|
local hash = "glyph|"..face.hash.."|"..charcode.."|"..(bold and 1 or 0).."|"..bgcolor.."|"..fgcolor
|
||||||
local glyph = GlyphCache:check(hash)
|
local glyph = GlyphCache:check(hash)
|
||||||
if glyph then
|
if glyph then
|
||||||
-- cache hit
|
-- cache hit
|
||||||
return glyph[1]
|
return glyph[1]
|
||||||
end
|
end
|
||||||
local rendered_glyph = face.ftface:renderGlyph(charcode, bgcolor, fgcolor, bold)
|
local rendered_glyph = face.ftface:renderGlyph(charcode, bgcolor, fgcolor, bold)
|
||||||
if face.ftface:checkGlyph(charcode) == 0 then
|
if face.ftface:checkGlyph(charcode) == 0 then
|
||||||
for index, font in pairs(Font.fallbacks) do
|
for index, font in pairs(Font.fallbacks) do
|
||||||
-- rescale face size by DPI since it will be scaled in getFace again
|
-- rescale face size by DPI since it will be scaled in getFace again
|
||||||
local fb_face = Font:getFace(font, Screen:rescaleByDPI(face.size))
|
local fb_face = Font:getFace(font, Screen:rescaleByDPI(face.size))
|
||||||
if fb_face.ftface:checkGlyph(charcode) ~= 0 then
|
if fb_face.ftface:checkGlyph(charcode) ~= 0 then
|
||||||
rendered_glyph = fb_face.ftface:renderGlyph(charcode, bgcolor, fgcolor, bold)
|
rendered_glyph = fb_face.ftface:renderGlyph(charcode, bgcolor, fgcolor, bold)
|
||||||
--DEBUG("fallback to font", font)
|
--DEBUG("fallback to font", font)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not rendered_glyph then
|
if not rendered_glyph then
|
||||||
DEBUG("error rendering glyph (charcode=", charcode, ") for face", face)
|
DEBUG("error rendering glyph (charcode=", charcode, ") for face", face)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
glyph = CacheItem:new{rendered_glyph}
|
glyph = CacheItem:new{rendered_glyph}
|
||||||
glyph.size = glyph[1].bb:getWidth() * glyph[1].bb:getHeight() / 2 + 32
|
glyph.size = glyph[1].bb:getWidth() * glyph[1].bb:getHeight() / 2 + 32
|
||||||
GlyphCache:insert(hash, glyph)
|
GlyphCache:insert(hash, glyph)
|
||||||
return rendered_glyph
|
return rendered_glyph
|
||||||
end
|
end
|
||||||
|
|
||||||
function RenderText:getSubTextByWidth(text, face, width, kerning, bold)
|
function RenderText:getSubTextByWidth(text, face, width, kerning, bold)
|
||||||
local pen_x = 0
|
local pen_x = 0
|
||||||
local prevcharcode = 0
|
local prevcharcode = 0
|
||||||
local char_list = {}
|
local char_list = {}
|
||||||
for _, charcode, uchar in utf8Chars(text) do
|
for _, charcode, uchar in utf8Chars(text) do
|
||||||
if pen_x < width then
|
if pen_x < width then
|
||||||
local glyph = self:getGlyph(face, charcode, bold)
|
local glyph = self:getGlyph(face, charcode, bold)
|
||||||
if kerning and prevcharcode then
|
if kerning and prevcharcode then
|
||||||
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
||||||
pen_x = pen_x + kern
|
pen_x = pen_x + kern
|
||||||
end
|
end
|
||||||
pen_x = pen_x + glyph.ax
|
pen_x = pen_x + glyph.ax
|
||||||
if pen_x <= width then
|
if pen_x <= width then
|
||||||
prevcharcode = charcode
|
prevcharcode = charcode
|
||||||
table.insert(char_list, uchar)
|
table.insert(char_list, uchar)
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(char_list)
|
return table.concat(char_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
function RenderText:sizeUtf8Text(x, width, face, text, kerning, bold)
|
function RenderText:sizeUtf8Text(x, width, face, text, kerning, bold)
|
||||||
if not text then
|
if not text then
|
||||||
DEBUG("sizeUtf8Text called without text");
|
DEBUG("sizeUtf8Text called without text");
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- may still need more adaptive pen placement when kerning,
|
-- may still need more adaptive pen placement when kerning,
|
||||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||||
local pen_x = 0
|
local pen_x = 0
|
||||||
local pen_y_top = 0
|
local pen_y_top = 0
|
||||||
local pen_y_bottom = 0
|
local pen_y_bottom = 0
|
||||||
local prevcharcode = 0
|
local prevcharcode = 0
|
||||||
for _, charcode, uchar in utf8Chars(text) do
|
for _, charcode, uchar in utf8Chars(text) do
|
||||||
if pen_x < (width - x) then
|
if pen_x < (width - x) then
|
||||||
local glyph = self:getGlyph(face, charcode, bold)
|
local glyph = self:getGlyph(face, charcode, bold)
|
||||||
if kerning and (prevcharcode ~= 0) then
|
if kerning and (prevcharcode ~= 0) then
|
||||||
pen_x = pen_x + (face.ftface):getKerning(prevcharcode, charcode)
|
pen_x = pen_x + (face.ftface):getKerning(prevcharcode, charcode)
|
||||||
end
|
end
|
||||||
pen_x = pen_x + glyph.ax
|
pen_x = pen_x + glyph.ax
|
||||||
pen_y_top = math.max(pen_y_top, glyph.t)
|
pen_y_top = math.max(pen_y_top, glyph.t)
|
||||||
pen_y_bottom = math.max(pen_y_bottom, glyph.bb:getHeight() - glyph.t)
|
pen_y_bottom = math.max(pen_y_bottom, glyph.bb:getHeight() - glyph.t)
|
||||||
--DEBUG("ax:"..glyph.ax.." t:"..glyph.t.." r:"..glyph.r.." h:"..glyph.bb:getHeight().." w:"..glyph.bb:getWidth().." yt:"..pen_y_top.." yb:"..pen_y_bottom)
|
--DEBUG("ax:"..glyph.ax.." t:"..glyph.t.." r:"..glyph.r.." h:"..glyph.bb:getHeight().." w:"..glyph.bb:getWidth().." yt:"..pen_y_top.." yb:"..pen_y_bottom)
|
||||||
prevcharcode = charcode
|
prevcharcode = charcode
|
||||||
end -- if pen_x < (width - x)
|
end -- if pen_x < (width - x)
|
||||||
end
|
end
|
||||||
return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom}
|
return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom}
|
||||||
end
|
end
|
||||||
|
|
||||||
function RenderText:renderUtf8Text(buffer, x, y, face, text, kerning, bold, bgcolor, fgcolor, width)
|
function RenderText:renderUtf8Text(buffer, x, y, face, text, kerning, bold, bgcolor, fgcolor, width)
|
||||||
if not text then
|
if not text then
|
||||||
DEBUG("renderUtf8Text called without text");
|
DEBUG("renderUtf8Text called without text");
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- may still need more adaptive pen placement when kerning,
|
-- may still need more adaptive pen placement when kerning,
|
||||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||||
local pen_x = 0
|
local pen_x = 0
|
||||||
local prevcharcode = 0
|
local prevcharcode = 0
|
||||||
local text_width = buffer:getWidth() - x
|
local text_width = buffer:getWidth() - x
|
||||||
if width and width < text_width then
|
if width and width < text_width then
|
||||||
text_width = width
|
text_width = width
|
||||||
end
|
end
|
||||||
for _, charcode, uchar in utf8Chars(text) do
|
for _, charcode, uchar in utf8Chars(text) do
|
||||||
if pen_x < text_width then
|
if pen_x < text_width then
|
||||||
local glyph = self:getGlyph(face, charcode, bold, bgcolor, fgcolor)
|
local glyph = self:getGlyph(face, charcode, bold, bgcolor, fgcolor)
|
||||||
if kerning and (prevcharcode ~= 0) then
|
if kerning and (prevcharcode ~= 0) then
|
||||||
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
|
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
|
||||||
end
|
end
|
||||||
buffer:addblitFrom(
|
buffer:addblitFrom(
|
||||||
glyph.bb,
|
glyph.bb,
|
||||||
x + pen_x + glyph.l, y - glyph.t,
|
x + pen_x + glyph.l, y - glyph.t,
|
||||||
0, 0,
|
0, 0,
|
||||||
glyph.bb:getWidth(), glyph.bb:getHeight(), 1)
|
glyph.bb:getWidth(), glyph.bb:getHeight(), 1)
|
||||||
pen_x = pen_x + glyph.ax
|
pen_x = pen_x + glyph.ax
|
||||||
prevcharcode = charcode
|
prevcharcode = charcode
|
||||||
end -- if pen_x < text_width
|
end -- if pen_x < text_width
|
||||||
end
|
end
|
||||||
|
|
||||||
return pen_x
|
return pen_x
|
||||||
end
|
end
|
||||||
|
|
||||||
return RenderText
|
return RenderText
|
||||||
|
|||||||
@@ -1,104 +1,104 @@
|
|||||||
local TimeVal = {
|
local TimeVal = {
|
||||||
sec = 0,
|
sec = 0,
|
||||||
usec = 0,
|
usec = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function TimeVal:new(o)
|
function TimeVal:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
if o.sec == nil then
|
if o.sec == nil then
|
||||||
o.sec = 0
|
o.sec = 0
|
||||||
end
|
end
|
||||||
if o.usec == nil then
|
if o.usec == nil then
|
||||||
o.usec = 0
|
o.usec = 0
|
||||||
elseif o.usec > 1000000 then
|
elseif o.usec > 1000000 then
|
||||||
o.sec = o.sec + maht.floor(o.usec/1000000)
|
o.sec = o.sec + maht.floor(o.usec/1000000)
|
||||||
o.usec = o.usec % 1000000
|
o.usec = o.usec % 1000000
|
||||||
end
|
end
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function TimeVal:__lt(time_b)
|
function TimeVal:__lt(time_b)
|
||||||
if self.sec < time_b.sec then
|
if self.sec < time_b.sec then
|
||||||
return true
|
return true
|
||||||
elseif self.sec > time_b.sec then
|
elseif self.sec > time_b.sec then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
-- self.sec == time_b.sec
|
-- self.sec == time_b.sec
|
||||||
if self.usec < time_b.usec then
|
if self.usec < time_b.usec then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TimeVal:__le(time_b)
|
function TimeVal:__le(time_b)
|
||||||
if self.sec < time_b.sec then
|
if self.sec < time_b.sec then
|
||||||
return true
|
return true
|
||||||
elseif self.sec > time_b.sec then
|
elseif self.sec > time_b.sec then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
-- self.sec == time_b.sec
|
-- self.sec == time_b.sec
|
||||||
if self.usec > time_b.usec then
|
if self.usec > time_b.usec then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TimeVal:__eq(time_b)
|
function TimeVal:__eq(time_b)
|
||||||
if self.sec == time_b.sec and self.usec == time_b.usec then
|
if self.sec == time_b.sec and self.usec == time_b.usec then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TimeVal:__sub(time_b)
|
function TimeVal:__sub(time_b)
|
||||||
local diff = TimeVal:new{}
|
local diff = TimeVal:new{}
|
||||||
|
|
||||||
diff.sec = self.sec - time_b.sec
|
diff.sec = self.sec - time_b.sec
|
||||||
diff.usec = self.usec - time_b.usec
|
diff.usec = self.usec - time_b.usec
|
||||||
|
|
||||||
if diff.sec < 0 and diff.usec > 0 then
|
if diff.sec < 0 and diff.usec > 0 then
|
||||||
diff.sec = diff.sec + 1
|
diff.sec = diff.sec + 1
|
||||||
diff.usec = diff.usec - 1000000
|
diff.usec = diff.usec - 1000000
|
||||||
elseif diff.sec > 0 and diff.usec < 0 then
|
elseif diff.sec > 0 and diff.usec < 0 then
|
||||||
diff.sec = diff.sec - 1
|
diff.sec = diff.sec - 1
|
||||||
diff.usec = diff.usec + 1000000
|
diff.usec = diff.usec + 1000000
|
||||||
end
|
end
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
end
|
end
|
||||||
|
|
||||||
function TimeVal:__add(time_b)
|
function TimeVal:__add(time_b)
|
||||||
local sum = TimeVal:new{}
|
local sum = TimeVal:new{}
|
||||||
|
|
||||||
sum.sec = self.sec + time_b.sec
|
sum.sec = self.sec + time_b.sec
|
||||||
sum.usec = self.usec + time_b.usec
|
sum.usec = self.usec + time_b.usec
|
||||||
if sum.usec > 1000000 then
|
if sum.usec > 1000000 then
|
||||||
sum.usec = sum.usec - 1000000
|
sum.usec = sum.usec - 1000000
|
||||||
sum.sec = sum.sec + 1
|
sum.sec = sum.sec + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if sum.sec < 0 and sum.usec > 0 then
|
if sum.sec < 0 and sum.usec > 0 then
|
||||||
sum.sec = sum.sec + 1
|
sum.sec = sum.sec + 1
|
||||||
sum.usec = sum.usec - 1000000
|
sum.usec = sum.usec - 1000000
|
||||||
elseif sum.sec > 0 and sum.usec < 0 then
|
elseif sum.sec > 0 and sum.usec < 0 then
|
||||||
sum.sec = sum.sec - 1
|
sum.sec = sum.sec - 1
|
||||||
sum.usec = sum.usec + 1000000
|
sum.usec = sum.usec + 1000000
|
||||||
end
|
end
|
||||||
|
|
||||||
return sum
|
return sum
|
||||||
end
|
end
|
||||||
|
|
||||||
function TimeVal:now()
|
function TimeVal:now()
|
||||||
local sec, usec = util.gettime()
|
local sec, usec = util.gettime()
|
||||||
return TimeVal:new{sec = sec, usec = usec}
|
return TimeVal:new{sec = sec, usec = usec}
|
||||||
end
|
end
|
||||||
|
|
||||||
return TimeVal
|
return TimeVal
|
||||||
|
|||||||
@@ -10,304 +10,304 @@ Screen:init()
|
|||||||
-- initialize the input handling
|
-- initialize the input handling
|
||||||
Input:init()
|
Input:init()
|
||||||
|
|
||||||
local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears)
|
local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears)
|
||||||
local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black
|
local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black
|
||||||
local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing)
|
local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing)
|
||||||
local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility
|
local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility
|
||||||
local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity
|
local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity
|
||||||
local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity
|
local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity
|
||||||
local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition
|
local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition
|
||||||
local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition
|
local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition
|
||||||
local WAVEFORM_MODE_AUTO = 0x101
|
local WAVEFORM_MODE_AUTO = 0x101
|
||||||
|
|
||||||
-- there is only one instance of this
|
-- there is only one instance of this
|
||||||
local UIManager = {
|
local UIManager = {
|
||||||
default_refresh_type = 0, -- 0 for partial refresh, 1 for full refresh
|
default_refresh_type = 0, -- 0 for partial refresh, 1 for full refresh
|
||||||
default_waveform_mode = WAVEFORM_MODE_GC16, -- high fidelity waveform
|
default_waveform_mode = WAVEFORM_MODE_GC16, -- high fidelity waveform
|
||||||
fast_waveform_mode = WAVEFORM_MODE_A2,
|
fast_waveform_mode = WAVEFORM_MODE_A2,
|
||||||
-- force to repaint all the widget is stack, will be reset to false
|
-- force to repaint all the widget is stack, will be reset to false
|
||||||
-- after each ui loop
|
-- after each ui loop
|
||||||
repaint_all = false,
|
repaint_all = false,
|
||||||
-- force to do full refresh, will be reset to false
|
-- force to do full refresh, will be reset to false
|
||||||
-- after each ui loop
|
-- after each ui loop
|
||||||
full_refresh = false,
|
full_refresh = false,
|
||||||
-- force to do patial refresh, will be reset to false
|
-- force to do patial refresh, will be reset to false
|
||||||
-- after each ui loop
|
-- after each ui loop
|
||||||
patial_refresh = false,
|
patial_refresh = false,
|
||||||
-- trigger a full refresh when counter reaches FULL_REFRESH_COUNT
|
-- trigger a full refresh when counter reaches FULL_REFRESH_COUNT
|
||||||
FULL_REFRESH_COUNT = DRCOUNTMAX,
|
FULL_REFRESH_COUNT = DRCOUNTMAX,
|
||||||
refresh_count = 0,
|
refresh_count = 0,
|
||||||
|
|
||||||
_running = true,
|
_running = true,
|
||||||
_window_stack = {},
|
_window_stack = {},
|
||||||
_execution_stack = {},
|
_execution_stack = {},
|
||||||
_dirty = {}
|
_dirty = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- register & show a widget
|
-- register & show a widget
|
||||||
function UIManager:show(widget, x, y)
|
function UIManager:show(widget, x, y)
|
||||||
-- put widget on top of stack
|
-- put widget on top of stack
|
||||||
table.insert(self._window_stack, {x = x or 0, y = y or 0, widget = widget})
|
table.insert(self._window_stack, {x = x or 0, y = y or 0, widget = widget})
|
||||||
-- and schedule it to be painted
|
-- and schedule it to be painted
|
||||||
self:setDirty(widget)
|
self:setDirty(widget)
|
||||||
-- tell the widget that it is shown now
|
-- tell the widget that it is shown now
|
||||||
widget:handleEvent(Event:new("Show"))
|
widget:handleEvent(Event:new("Show"))
|
||||||
-- check if this widget disables double tap gesture
|
-- check if this widget disables double tap gesture
|
||||||
if widget.disable_double_tap then
|
if widget.disable_double_tap then
|
||||||
Input.disable_double_tap = true
|
Input.disable_double_tap = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- unregister a widget
|
-- unregister a widget
|
||||||
function UIManager:close(widget)
|
function UIManager:close(widget)
|
||||||
Input.disable_double_tap = DGESDETECT_DISABLE_DOUBLE_TAP
|
Input.disable_double_tap = DGESDETECT_DISABLE_DOUBLE_TAP
|
||||||
local dirty = false
|
local dirty = false
|
||||||
for i = #self._window_stack, 1, -1 do
|
for i = #self._window_stack, 1, -1 do
|
||||||
if self._window_stack[i].widget == widget then
|
if self._window_stack[i].widget == widget then
|
||||||
table.remove(self._window_stack, i)
|
table.remove(self._window_stack, i)
|
||||||
dirty = true
|
dirty = true
|
||||||
elseif self._window_stack[i].widget.disable_double_tap then
|
elseif self._window_stack[i].widget.disable_double_tap then
|
||||||
Input.disable_double_tap = true
|
Input.disable_double_tap = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if dirty then
|
if dirty then
|
||||||
-- schedule remaining widgets to be painted
|
-- schedule remaining widgets to be painted
|
||||||
for i = 1, #self._window_stack do
|
for i = 1, #self._window_stack do
|
||||||
self:setDirty(self._window_stack[i].widget)
|
self:setDirty(self._window_stack[i].widget)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- schedule an execution task
|
-- schedule an execution task
|
||||||
function UIManager:schedule(time, action)
|
function UIManager:schedule(time, action)
|
||||||
table.insert(self._execution_stack, { time = time, action = action })
|
table.insert(self._execution_stack, { time = time, action = action })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- schedule task in a certain amount of seconds (fractions allowed) from now
|
-- schedule task in a certain amount of seconds (fractions allowed) from now
|
||||||
function UIManager:scheduleIn(seconds, action)
|
function UIManager:scheduleIn(seconds, action)
|
||||||
local when = { util.gettime() }
|
local when = { util.gettime() }
|
||||||
local s = math.floor(seconds)
|
local s = math.floor(seconds)
|
||||||
local usecs = (seconds - s) * 1000000
|
local usecs = (seconds - s) * 1000000
|
||||||
when[1] = when[1] + s
|
when[1] = when[1] + s
|
||||||
when[2] = when[2] + usecs
|
when[2] = when[2] + usecs
|
||||||
if when[2] > 1000000 then
|
if when[2] > 1000000 then
|
||||||
when[1] = when[1] + 1
|
when[1] = when[1] + 1
|
||||||
when[2] = when[2] - 1000000
|
when[2] = when[2] - 1000000
|
||||||
end
|
end
|
||||||
self:schedule(when, action)
|
self:schedule(when, action)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- register a widget to be repainted
|
-- register a widget to be repainted
|
||||||
function UIManager:setDirty(widget, refresh_type)
|
function UIManager:setDirty(widget, refresh_type)
|
||||||
-- "auto": request full refresh
|
-- "auto": request full refresh
|
||||||
-- "full": force full refresh
|
-- "full": force full refresh
|
||||||
-- "partial": partial refresh
|
-- "partial": partial refresh
|
||||||
if not refresh_type then
|
if not refresh_type then
|
||||||
refresh_type = "auto"
|
refresh_type = "auto"
|
||||||
end
|
end
|
||||||
self._dirty[widget] = refresh_type
|
self._dirty[widget] = refresh_type
|
||||||
end
|
end
|
||||||
|
|
||||||
-- signal to quit
|
-- signal to quit
|
||||||
function UIManager:quit()
|
function UIManager:quit()
|
||||||
self._running = false
|
self._running = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transmit an event to registered widgets
|
-- transmit an event to registered widgets
|
||||||
function UIManager:sendEvent(event)
|
function UIManager:sendEvent(event)
|
||||||
-- top level widget has first access to the event
|
-- top level widget has first access to the event
|
||||||
if self._window_stack[#self._window_stack].widget:handleEvent(event) then
|
if self._window_stack[#self._window_stack].widget:handleEvent(event) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if the event is not consumed, active widgets can access it
|
-- if the event is not consumed, active widgets can access it
|
||||||
for _, widget in ipairs(self._window_stack) do
|
for _, widget in ipairs(self._window_stack) do
|
||||||
if widget.widget.is_always_active then
|
if widget.widget.is_always_active then
|
||||||
if widget.widget:handleEvent(event) then return end
|
if widget.widget:handleEvent(event) then return end
|
||||||
end
|
end
|
||||||
if widget.widget.active_widgets then
|
if widget.widget.active_widgets then
|
||||||
for _, active_widget in ipairs(widget.widget.active_widgets) do
|
for _, active_widget in ipairs(widget.widget.active_widgets) do
|
||||||
if active_widget:handleEvent(event) then return end
|
if active_widget:handleEvent(event) then return end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UIManager:checkTasks()
|
function UIManager:checkTasks()
|
||||||
local now = { util.gettime() }
|
local now = { util.gettime() }
|
||||||
|
|
||||||
-- check if we have timed events in our queue and search next one
|
-- check if we have timed events in our queue and search next one
|
||||||
local wait_until = nil
|
local wait_until = nil
|
||||||
local all_tasks_checked
|
local all_tasks_checked
|
||||||
repeat
|
repeat
|
||||||
all_tasks_checked = true
|
all_tasks_checked = true
|
||||||
for i = #self._execution_stack, 1, -1 do
|
for i = #self._execution_stack, 1, -1 do
|
||||||
local task = self._execution_stack[i]
|
local task = self._execution_stack[i]
|
||||||
if not task.time
|
if not task.time
|
||||||
or task.time[1] < now[1]
|
or task.time[1] < now[1]
|
||||||
or task.time[1] == now[1] and task.time[2] < now[2] then
|
or task.time[1] == now[1] and task.time[2] < now[2] then
|
||||||
-- task is pending to be executed right now. do it.
|
-- task is pending to be executed right now. do it.
|
||||||
task.action()
|
task.action()
|
||||||
-- and remove from table
|
-- and remove from table
|
||||||
table.remove(self._execution_stack, i)
|
table.remove(self._execution_stack, i)
|
||||||
-- start loop again, since new tasks might be on the
|
-- start loop again, since new tasks might be on the
|
||||||
-- queue now
|
-- queue now
|
||||||
all_tasks_checked = false
|
all_tasks_checked = false
|
||||||
elseif not wait_until
|
elseif not wait_until
|
||||||
or wait_until[1] > task.time[1]
|
or wait_until[1] > task.time[1]
|
||||||
or wait_until[1] == task.time[1] and wait_until[2] > task.time[2] then
|
or wait_until[1] == task.time[1] and wait_until[2] > task.time[2] then
|
||||||
-- task is to be run in the future _and_ is scheduled
|
-- task is to be run in the future _and_ is scheduled
|
||||||
-- earlier than the tasks we looked at already
|
-- earlier than the tasks we looked at already
|
||||||
-- so adjust to the currently examined task instead.
|
-- so adjust to the currently examined task instead.
|
||||||
wait_until = task.time
|
wait_until = task.time
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
until all_tasks_checked
|
until all_tasks_checked
|
||||||
return wait_until
|
return wait_until
|
||||||
end
|
end
|
||||||
|
|
||||||
-- this is the main loop of the UI controller
|
-- this is the main loop of the UI controller
|
||||||
-- it is intended to manage input events and delegate
|
-- it is intended to manage input events and delegate
|
||||||
-- them to dialogs
|
-- them to dialogs
|
||||||
function UIManager:run()
|
function UIManager:run()
|
||||||
self._running = true
|
self._running = true
|
||||||
while self._running do
|
while self._running do
|
||||||
local now = { util.gettime() }
|
local now = { util.gettime() }
|
||||||
local wait_until = self:checkTasks()
|
local wait_until = self:checkTasks()
|
||||||
|
|
||||||
--DEBUG("---------------------------------------------------")
|
--DEBUG("---------------------------------------------------")
|
||||||
--DEBUG("exec stack", self._execution_stack)
|
--DEBUG("exec stack", self._execution_stack)
|
||||||
--DEBUG("window stack", self._window_stack)
|
--DEBUG("window stack", self._window_stack)
|
||||||
--DEBUG("dirty stack", self._dirty)
|
--DEBUG("dirty stack", self._dirty)
|
||||||
--DEBUG("---------------------------------------------------")
|
--DEBUG("---------------------------------------------------")
|
||||||
|
|
||||||
-- stop when we have no window to show
|
-- stop when we have no window to show
|
||||||
if #self._window_stack == 0 then
|
if #self._window_stack == 0 then
|
||||||
DEBUG("no dialog left to show, would loop endlessly")
|
DEBUG("no dialog left to show, would loop endlessly")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- repaint dirty widgets
|
-- repaint dirty widgets
|
||||||
local dirty = false
|
local dirty = false
|
||||||
local request_full_refresh = false
|
local request_full_refresh = false
|
||||||
local force_full_refresh = false
|
local force_full_refresh = false
|
||||||
local force_patial_refresh = false
|
local force_patial_refresh = false
|
||||||
local force_fast_refresh = false
|
local force_fast_refresh = false
|
||||||
for _, widget in ipairs(self._window_stack) do
|
for _, widget in ipairs(self._window_stack) do
|
||||||
if self.repaint_all or self._dirty[widget.widget] then
|
if self.repaint_all or self._dirty[widget.widget] then
|
||||||
widget.widget:paintTo(Screen.bb, widget.x, widget.y)
|
widget.widget:paintTo(Screen.bb, widget.x, widget.y)
|
||||||
if self._dirty[widget.widget] == "auto" then
|
if self._dirty[widget.widget] == "auto" then
|
||||||
request_full_refresh = true
|
request_full_refresh = true
|
||||||
end
|
end
|
||||||
if self._dirty[widget.widget] == "full" then
|
if self._dirty[widget.widget] == "full" then
|
||||||
force_full_refresh = true
|
force_full_refresh = true
|
||||||
end
|
end
|
||||||
if self._dirty[widget.widget] == "partial" then
|
if self._dirty[widget.widget] == "partial" then
|
||||||
force_patial_refresh = true
|
force_patial_refresh = true
|
||||||
end
|
end
|
||||||
if self._dirty[widget.widget] == "fast" then
|
if self._dirty[widget.widget] == "fast" then
|
||||||
force_fast_refresh = true
|
force_fast_refresh = true
|
||||||
end
|
end
|
||||||
-- and remove from list after painting
|
-- and remove from list after painting
|
||||||
self._dirty[widget.widget] = nil
|
self._dirty[widget.widget] = nil
|
||||||
-- trigger repaint
|
-- trigger repaint
|
||||||
dirty = true
|
dirty = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.full_refresh then
|
if self.full_refresh then
|
||||||
dirty = true
|
dirty = true
|
||||||
force_full_refresh = true
|
force_full_refresh = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.patial_refresh then
|
if self.patial_refresh then
|
||||||
dirty = true
|
dirty = true
|
||||||
force_patial_refresh = true
|
force_patial_refresh = true
|
||||||
end
|
end
|
||||||
|
|
||||||
self.repaint_all = false
|
self.repaint_all = false
|
||||||
self.full_refresh = false
|
self.full_refresh = false
|
||||||
self.patial_refresh = false
|
self.patial_refresh = false
|
||||||
|
|
||||||
local refresh_type = self.default_refresh_type
|
local refresh_type = self.default_refresh_type
|
||||||
local waveform_mode = self.default_waveform_mode
|
local waveform_mode = self.default_waveform_mode
|
||||||
if dirty then
|
if dirty then
|
||||||
if force_patial_refresh or force_fast_refresh then
|
if force_patial_refresh or force_fast_refresh then
|
||||||
refresh_type = 0
|
refresh_type = 0
|
||||||
elseif force_full_refresh or self.refresh_count == self.FULL_REFRESH_COUNT - 1 then
|
elseif force_full_refresh or self.refresh_count == self.FULL_REFRESH_COUNT - 1 then
|
||||||
refresh_type = 1
|
refresh_type = 1
|
||||||
end
|
end
|
||||||
if force_fast_refresh then
|
if force_fast_refresh then
|
||||||
waveform_mode = self.fast_waveform_mode
|
waveform_mode = self.fast_waveform_mode
|
||||||
end
|
end
|
||||||
if self.update_region_func then
|
if self.update_region_func then
|
||||||
local update_region = self.update_region_func()
|
local update_region = self.update_region_func()
|
||||||
-- in some rare cases update region has 1 pixel offset
|
-- in some rare cases update region has 1 pixel offset
|
||||||
Screen:refresh(refresh_type, waveform_mode,
|
Screen:refresh(refresh_type, waveform_mode,
|
||||||
update_region.x-1, update_region.y-1,
|
update_region.x-1, update_region.y-1,
|
||||||
update_region.w+2, update_region.h+2)
|
update_region.w+2, update_region.h+2)
|
||||||
else
|
else
|
||||||
Screen:refresh(refresh_type, waveform_mode)
|
Screen:refresh(refresh_type, waveform_mode)
|
||||||
end
|
end
|
||||||
if self.refresh_type == 1 then
|
if self.refresh_type == 1 then
|
||||||
self.refresh_count = 0
|
self.refresh_count = 0
|
||||||
elseif not force_patial_refresh and not force_full_refresh then
|
elseif not force_patial_refresh and not force_full_refresh then
|
||||||
self.refresh_count = (self.refresh_count + 1)%self.FULL_REFRESH_COUNT
|
self.refresh_count = (self.refresh_count + 1)%self.FULL_REFRESH_COUNT
|
||||||
end
|
end
|
||||||
self.update_region_func = nil
|
self.update_region_func = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
self:checkTasks()
|
self:checkTasks()
|
||||||
|
|
||||||
-- wait for next event
|
-- wait for next event
|
||||||
-- note that we will skip that if in the meantime we have tasks that are ready to run
|
-- note that we will skip that if in the meantime we have tasks that are ready to run
|
||||||
local input_event = nil
|
local input_event = nil
|
||||||
if not wait_until then
|
if not wait_until then
|
||||||
-- no pending task, wait endlessly
|
-- no pending task, wait endlessly
|
||||||
input_event = Input:waitEvent()
|
input_event = Input:waitEvent()
|
||||||
elseif wait_until[1] > now[1]
|
elseif wait_until[1] > now[1]
|
||||||
or wait_until[1] == now[1] and wait_until[2] > now[2] then
|
or wait_until[1] == now[1] and wait_until[2] > now[2] then
|
||||||
local wait_for = { s = wait_until[1] - now[1], us = wait_until[2] - now[2] }
|
local wait_for = { s = wait_until[1] - now[1], us = wait_until[2] - now[2] }
|
||||||
if wait_for.us < 0 then
|
if wait_for.us < 0 then
|
||||||
wait_for.s = wait_for.s - 1
|
wait_for.s = wait_for.s - 1
|
||||||
wait_for.us = 1000000 + wait_for.us
|
wait_for.us = 1000000 + wait_for.us
|
||||||
end
|
end
|
||||||
-- wait until next task is pending
|
-- wait until next task is pending
|
||||||
input_event = Input:waitEvent(wait_for.us, wait_for.s)
|
input_event = Input:waitEvent(wait_for.us, wait_for.s)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- delegate input_event to handler
|
-- delegate input_event to handler
|
||||||
if input_event then
|
if input_event then
|
||||||
--DEBUG("in ui.lua:", input_event)
|
--DEBUG("in ui.lua:", input_event)
|
||||||
if input_event == "IntoSS" then
|
if input_event == "IntoSS" then
|
||||||
Device:intoScreenSaver()
|
Device:intoScreenSaver()
|
||||||
elseif input_event == "OutOfSS" then
|
elseif input_event == "OutOfSS" then
|
||||||
Device:outofScreenSaver()
|
Device:outofScreenSaver()
|
||||||
elseif input_event == "Charging" then
|
elseif input_event == "Charging" then
|
||||||
Device:usbPlugIn()
|
Device:usbPlugIn()
|
||||||
elseif input_event == "NotCharging" then
|
elseif input_event == "NotCharging" then
|
||||||
Device:usbPlugOut()
|
Device:usbPlugOut()
|
||||||
self:sendEvent(Event:new("NotCharging"))
|
self:sendEvent(Event:new("NotCharging"))
|
||||||
elseif input_event == "Light" then
|
elseif input_event == "Light" then
|
||||||
Device:getPowerDevice():toggleFrontlight()
|
Device:getPowerDevice():toggleFrontlight()
|
||||||
elseif (input_event == "Power" and not Device.screen_saver_mode)
|
elseif (input_event == "Power" and not Device.screen_saver_mode)
|
||||||
or input_event == "Suspend" then
|
or input_event == "Suspend" then
|
||||||
local InfoMessage = require("ui/widget/infomessage")
|
local InfoMessage = require("ui/widget/infomessage")
|
||||||
self:show(InfoMessage:new{
|
self:show(InfoMessage:new{
|
||||||
text = _("Standby"),
|
text = _("Standby"),
|
||||||
timeout = 1,
|
timeout = 1,
|
||||||
})
|
})
|
||||||
Device:prepareSuspend()
|
Device:prepareSuspend()
|
||||||
self:scheduleIn(0.5, function() Device:Suspend() end)
|
self:scheduleIn(0.5, function() Device:Suspend() end)
|
||||||
elseif (input_event == "Power" and Device.screen_saver_mode)
|
elseif (input_event == "Power" and Device.screen_saver_mode)
|
||||||
or input_event == "Resume" then
|
or input_event == "Resume" then
|
||||||
Device:Resume()
|
Device:Resume()
|
||||||
self:sendEvent(Event:new("Resume"))
|
self:sendEvent(Event:new("Resume"))
|
||||||
else
|
else
|
||||||
self:sendEvent(input_event)
|
self:sendEvent(input_event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return UIManager
|
return UIManager
|
||||||
|
|||||||
@@ -11,212 +11,212 @@ local DEBUG = require("dbg")
|
|||||||
BBoxWidget shows a bbox for page cropping
|
BBoxWidget shows a bbox for page cropping
|
||||||
]]
|
]]
|
||||||
local BBoxWidget = InputContainer:new{
|
local BBoxWidget = InputContainer:new{
|
||||||
page_bbox = nil,
|
page_bbox = nil,
|
||||||
screen_bbox = nil,
|
screen_bbox = nil,
|
||||||
linesize = 2,
|
linesize = 2,
|
||||||
fine_factor = 10,
|
fine_factor = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
function BBoxWidget:init()
|
function BBoxWidget:init()
|
||||||
self.page_bbox = self.document:getPageBBox(self.view.state.page)
|
self.page_bbox = self.document:getPageBBox(self.view.state.page)
|
||||||
--DEBUG("used page bbox on page", self.view.state.page, self.page_bbox)
|
--DEBUG("used page bbox on page", self.view.state.page, self.page_bbox)
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapAdjust = {
|
TapAdjust = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.view.dimen,
|
range = self.view.dimen,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwipeAdjust = {
|
SwipeAdjust = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = self.view.dimen,
|
range = self.view.dimen,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HoldAdjust = {
|
HoldAdjust = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "hold",
|
ges = "hold",
|
||||||
range = self.view.dimen,
|
range = self.view.dimen,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ConfirmAdjust = {
|
ConfirmAdjust = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "double_tap",
|
ges = "double_tap",
|
||||||
range = self.view.dimen,
|
range = self.view.dimen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:getSize()
|
function BBoxWidget:getSize()
|
||||||
return self.view.dimen
|
return self.view.dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:paintTo(bb, x, y)
|
function BBoxWidget:paintTo(bb, x, y)
|
||||||
-- As getScreenBBox uses view states, screen_bbox initialization is postponed.
|
-- As getScreenBBox uses view states, screen_bbox initialization is postponed.
|
||||||
self.screen_bbox = self.screen_bbox or self:getScreenBBox(self.page_bbox)
|
self.screen_bbox = self.screen_bbox or self:getScreenBBox(self.page_bbox)
|
||||||
local bbox = self.screen_bbox
|
local bbox = self.screen_bbox
|
||||||
-- top edge
|
-- top edge
|
||||||
bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize)
|
bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize)
|
||||||
-- bottom edge
|
-- bottom edge
|
||||||
bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize)
|
bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize)
|
||||||
-- left edge
|
-- left edge
|
||||||
bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize)
|
bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize)
|
||||||
-- right edge
|
-- right edge
|
||||||
bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0)
|
bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transform page bbox to screen bbox
|
-- transform page bbox to screen bbox
|
||||||
function BBoxWidget:getScreenBBox(page_bbox)
|
function BBoxWidget:getScreenBBox(page_bbox)
|
||||||
local bbox = {}
|
local bbox = {}
|
||||||
local scale = self.view.state.zoom
|
local scale = self.view.state.zoom
|
||||||
local screen_offset = self.view.state.offset
|
local screen_offset = self.view.state.offset
|
||||||
--DEBUG("screen offset in page_to_screen", screen_offset)
|
--DEBUG("screen offset in page_to_screen", screen_offset)
|
||||||
bbox.x0 = Math.round(page_bbox.x0 * scale + screen_offset.x)
|
bbox.x0 = Math.round(page_bbox.x0 * scale + screen_offset.x)
|
||||||
bbox.y0 = Math.round(page_bbox.y0 * scale + screen_offset.y)
|
bbox.y0 = Math.round(page_bbox.y0 * scale + screen_offset.y)
|
||||||
bbox.x1 = Math.round(page_bbox.x1 * scale + screen_offset.x)
|
bbox.x1 = Math.round(page_bbox.x1 * scale + screen_offset.x)
|
||||||
bbox.y1 = Math.round(page_bbox.y1 * scale + screen_offset.y)
|
bbox.y1 = Math.round(page_bbox.y1 * scale + screen_offset.y)
|
||||||
return bbox
|
return bbox
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transform screen bbox to page bbox
|
-- transform screen bbox to page bbox
|
||||||
function BBoxWidget:getPageBBox(screen_bbox)
|
function BBoxWidget:getPageBBox(screen_bbox)
|
||||||
local bbox = {}
|
local bbox = {}
|
||||||
local scale = self.view.state.zoom
|
local scale = self.view.state.zoom
|
||||||
local screen_offset = self.view.state.offset
|
local screen_offset = self.view.state.offset
|
||||||
--DEBUG("screen offset in screen_to_page", screen_offset)
|
--DEBUG("screen offset in screen_to_page", screen_offset)
|
||||||
bbox.x0 = Math.round((screen_bbox.x0 - screen_offset.x) / scale)
|
bbox.x0 = Math.round((screen_bbox.x0 - screen_offset.x) / scale)
|
||||||
bbox.y0 = Math.round((screen_bbox.y0 - screen_offset.y) / scale)
|
bbox.y0 = Math.round((screen_bbox.y0 - screen_offset.y) / scale)
|
||||||
bbox.x1 = Math.round((screen_bbox.x1 - screen_offset.x) / scale)
|
bbox.x1 = Math.round((screen_bbox.x1 - screen_offset.x) / scale)
|
||||||
bbox.y1 = Math.round((screen_bbox.y1 - screen_offset.y) / scale)
|
bbox.y1 = Math.round((screen_bbox.y1 - screen_offset.y) / scale)
|
||||||
return bbox
|
return bbox
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:inPageArea(ges)
|
function BBoxWidget:inPageArea(ges)
|
||||||
local offset = self.view.state.offset
|
local offset = self.view.state.offset
|
||||||
local page_area = self.view.page_area
|
local page_area = self.view.page_area
|
||||||
local page_dimen = Geom:new{ x = offset.x, y = offset.y, h = page_area.h, w = page_area.w}
|
local page_dimen = Geom:new{ x = offset.x, y = offset.y, h = page_area.h, w = page_area.w}
|
||||||
return not ges.pos:notIntersectWith(page_dimen)
|
return not ges.pos:notIntersectWith(page_dimen)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:adjustScreenBBox(ges, relative)
|
function BBoxWidget:adjustScreenBBox(ges, relative)
|
||||||
--DEBUG("adjusting crop bbox with pos", ges.pos)
|
--DEBUG("adjusting crop bbox with pos", ges.pos)
|
||||||
if not self:inPageArea(ges) then return end
|
if not self:inPageArea(ges) then return end
|
||||||
local bbox = self.screen_bbox
|
local bbox = self.screen_bbox
|
||||||
local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0}
|
local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0}
|
||||||
local upper_right = Geom:new{ x = bbox.x1, y = bbox.y0}
|
local upper_right = Geom:new{ x = bbox.x1, y = bbox.y0}
|
||||||
local bottom_left = Geom:new{ x = bbox.x0, y = bbox.y1}
|
local bottom_left = Geom:new{ x = bbox.x0, y = bbox.y1}
|
||||||
local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1}
|
local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1}
|
||||||
local upper_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y0}
|
local upper_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y0}
|
||||||
local bottom_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y1}
|
local bottom_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y1}
|
||||||
local right_center = Geom:new{ x = bbox.x1, y = (bbox.y0 + bbox.y1) / 2}
|
local right_center = Geom:new{ x = bbox.x1, y = (bbox.y0 + bbox.y1) / 2}
|
||||||
local left_center = Geom:new{ x = bbox.x0, y = (bbox.y0 + bbox.y1) / 2}
|
local left_center = Geom:new{ x = bbox.x0, y = (bbox.y0 + bbox.y1) / 2}
|
||||||
local anchors = {
|
local anchors = {
|
||||||
upper_left, upper_center, upper_right,
|
upper_left, upper_center, upper_right,
|
||||||
left_center, right_center,
|
left_center, right_center,
|
||||||
bottom_left, bottom_center, bottom_right,
|
bottom_left, bottom_center, bottom_right,
|
||||||
}
|
}
|
||||||
local _, nearest = Math.tmin(anchors, function(a,b)
|
local _, nearest = Math.tmin(anchors, function(a,b)
|
||||||
return a:distance(ges.pos) > b:distance(ges.pos)
|
return a:distance(ges.pos) > b:distance(ges.pos)
|
||||||
end)
|
end)
|
||||||
--DEBUG("nearest anchor", nearest)
|
--DEBUG("nearest anchor", nearest)
|
||||||
if nearest == upper_left then
|
if nearest == upper_left then
|
||||||
upper_left.x = ges.pos.x
|
upper_left.x = ges.pos.x
|
||||||
upper_left.y = ges.pos.y
|
upper_left.y = ges.pos.y
|
||||||
elseif nearest == bottom_right then
|
elseif nearest == bottom_right then
|
||||||
bottom_right.x = ges.pos.x
|
bottom_right.x = ges.pos.x
|
||||||
bottom_right.y = ges.pos.y
|
bottom_right.y = ges.pos.y
|
||||||
elseif nearest == upper_right then
|
elseif nearest == upper_right then
|
||||||
bottom_right.x = ges.pos.x
|
bottom_right.x = ges.pos.x
|
||||||
upper_left.y = ges.pos.y
|
upper_left.y = ges.pos.y
|
||||||
elseif nearest == bottom_left then
|
elseif nearest == bottom_left then
|
||||||
upper_left.x = ges.pos.x
|
upper_left.x = ges.pos.x
|
||||||
bottom_right.y = ges.pos.y
|
bottom_right.y = ges.pos.y
|
||||||
elseif nearest == upper_center then
|
elseif nearest == upper_center then
|
||||||
if relative then
|
if relative then
|
||||||
local delta = 0
|
local delta = 0
|
||||||
if ges.direction == "north" then
|
if ges.direction == "north" then
|
||||||
delta = -ges.distance / self.fine_factor
|
delta = -ges.distance / self.fine_factor
|
||||||
elseif ges.direction == "south" then
|
elseif ges.direction == "south" then
|
||||||
delta = ges.distance / self.fine_factor
|
delta = ges.distance / self.fine_factor
|
||||||
end
|
end
|
||||||
upper_left.y = upper_left.y + delta
|
upper_left.y = upper_left.y + delta
|
||||||
else
|
else
|
||||||
upper_left.y = ges.pos.y
|
upper_left.y = ges.pos.y
|
||||||
end
|
end
|
||||||
elseif nearest == right_center then
|
elseif nearest == right_center then
|
||||||
if relative then
|
if relative then
|
||||||
local delta = 0
|
local delta = 0
|
||||||
if ges.direction == "west" then
|
if ges.direction == "west" then
|
||||||
delta = -ges.distance / self.fine_factor
|
delta = -ges.distance / self.fine_factor
|
||||||
elseif ges.direction == "east" then
|
elseif ges.direction == "east" then
|
||||||
delta = ges.distance / self.fine_factor
|
delta = ges.distance / self.fine_factor
|
||||||
end
|
end
|
||||||
bottom_right.x = bottom_right.x + delta
|
bottom_right.x = bottom_right.x + delta
|
||||||
else
|
else
|
||||||
bottom_right.x = ges.pos.x
|
bottom_right.x = ges.pos.x
|
||||||
end
|
end
|
||||||
elseif nearest == bottom_center then
|
elseif nearest == bottom_center then
|
||||||
if relative then
|
if relative then
|
||||||
local delta = 0
|
local delta = 0
|
||||||
if ges.direction == "north" then
|
if ges.direction == "north" then
|
||||||
delta = -ges.distance / self.fine_factor
|
delta = -ges.distance / self.fine_factor
|
||||||
elseif ges.direction == "south" then
|
elseif ges.direction == "south" then
|
||||||
delta = ges.distance / self.fine_factor
|
delta = ges.distance / self.fine_factor
|
||||||
end
|
end
|
||||||
bottom_right.y = bottom_right.y + delta
|
bottom_right.y = bottom_right.y + delta
|
||||||
else
|
else
|
||||||
bottom_right.y = ges.pos.y
|
bottom_right.y = ges.pos.y
|
||||||
end
|
end
|
||||||
elseif nearest == left_center then
|
elseif nearest == left_center then
|
||||||
if relative then
|
if relative then
|
||||||
local delta = 0
|
local delta = 0
|
||||||
if ges.direction == "west" then
|
if ges.direction == "west" then
|
||||||
delta = -ges.distance / self.fine_factor
|
delta = -ges.distance / self.fine_factor
|
||||||
elseif ges.direction == "east" then
|
elseif ges.direction == "east" then
|
||||||
delta = ges.distance / self.fine_factor
|
delta = ges.distance / self.fine_factor
|
||||||
end
|
end
|
||||||
upper_left.x = upper_left.x + delta
|
upper_left.x = upper_left.x + delta
|
||||||
else
|
else
|
||||||
upper_left.x = ges.pos.x
|
upper_left.x = ges.pos.x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.screen_bbox = {
|
self.screen_bbox = {
|
||||||
x0 = Math.round(upper_left.x),
|
x0 = Math.round(upper_left.x),
|
||||||
y0 = Math.round(upper_left.y),
|
y0 = Math.round(upper_left.y),
|
||||||
x1 = Math.round(bottom_right.x),
|
x1 = Math.round(bottom_right.x),
|
||||||
y1 = Math.round(bottom_right.y)
|
y1 = Math.round(bottom_right.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:getModifiedPageBBox()
|
function BBoxWidget:getModifiedPageBBox()
|
||||||
return self:getPageBBox(self.screen_bbox)
|
return self:getPageBBox(self.screen_bbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:onTapAdjust(arg, ges)
|
function BBoxWidget:onTapAdjust(arg, ges)
|
||||||
self:adjustScreenBBox(ges)
|
self:adjustScreenBBox(ges)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:onSwipeAdjust(arg, ges)
|
function BBoxWidget:onSwipeAdjust(arg, ges)
|
||||||
self:adjustScreenBBox(ges, true)
|
self:adjustScreenBBox(ges, true)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:onHoldAdjust(arg, ges)
|
function BBoxWidget:onHoldAdjust(arg, ges)
|
||||||
self:adjustScreenBBox(ges)
|
self:adjustScreenBBox(ges)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function BBoxWidget:onConfirmAdjust(arg, ges)
|
function BBoxWidget:onConfirmAdjust(arg, ges)
|
||||||
if self:inPageArea(ges) then
|
if self:inPageArea(ges) then
|
||||||
self.ui:handleEvent(Event:new("ConfirmPageCrop"))
|
self.ui:handleEvent(Event:new("ConfirmPageCrop"))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return BBoxWidget
|
return BBoxWidget
|
||||||
|
|||||||
@@ -13,135 +13,135 @@ local _ = require("gettext")
|
|||||||
a button widget that shows text or a icon and handles callback when tapped
|
a button widget that shows text or a icon and handles callback when tapped
|
||||||
--]]
|
--]]
|
||||||
local Button = InputContainer:new{
|
local Button = InputContainer:new{
|
||||||
text = nil, -- mandatory
|
text = nil, -- mandatory
|
||||||
icon = nil,
|
icon = nil,
|
||||||
preselect = false,
|
preselect = false,
|
||||||
callback = nil,
|
callback = nil,
|
||||||
enabled = true,
|
enabled = true,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
bordersize = 3,
|
bordersize = 3,
|
||||||
background = 0,
|
background = 0,
|
||||||
radius = 15,
|
radius = 15,
|
||||||
padding = 2,
|
padding = 2,
|
||||||
width = nil,
|
width = nil,
|
||||||
text_font_face = "cfont",
|
text_font_face = "cfont",
|
||||||
text_font_size = 20,
|
text_font_size = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Button:init()
|
function Button:init()
|
||||||
if self.text then
|
if self.text then
|
||||||
self.label_widget = TextWidget:new{
|
self.label_widget = TextWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
bgcolor = 0.0,
|
bgcolor = 0.0,
|
||||||
fgcolor = self.enabled and 1.0 or 0.5,
|
fgcolor = self.enabled and 1.0 or 0.5,
|
||||||
bold = true,
|
bold = true,
|
||||||
face = Font:getFace(self.text_font_face, self.text_font_size)
|
face = Font:getFace(self.text_font_face, self.text_font_size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self.label_widget = ImageWidget:new{
|
self.label_widget = ImageWidget:new{
|
||||||
file = self.icon,
|
file = self.icon,
|
||||||
dim = self.enabled,
|
dim = self.enabled,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local widget_size = self.label_widget:getSize()
|
local widget_size = self.label_widget:getSize()
|
||||||
if self.width == nil then
|
if self.width == nil then
|
||||||
self.width = widget_size.w
|
self.width = widget_size.w
|
||||||
end
|
end
|
||||||
-- set FrameContainer content
|
-- set FrameContainer content
|
||||||
self[1] = FrameContainer:new{
|
self[1] = FrameContainer:new{
|
||||||
margin = self.margin,
|
margin = self.margin,
|
||||||
bordersize = self.bordersize,
|
bordersize = self.bordersize,
|
||||||
background = self.background,
|
background = self.background,
|
||||||
radius = self.radius,
|
radius = self.radius,
|
||||||
padding = self.padding,
|
padding = self.padding,
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = self.width,
|
w = self.width,
|
||||||
h = widget_size.h
|
h = widget_size.h
|
||||||
},
|
},
|
||||||
self.label_widget,
|
self.label_widget,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.preselect then
|
if self.preselect then
|
||||||
self[1].color = 15
|
self[1].color = 15
|
||||||
else
|
else
|
||||||
self[1].color = 5
|
self[1].color = 5
|
||||||
end
|
end
|
||||||
self.dimen = self[1]:getSize()
|
self.dimen = self[1]:getSize()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Tap Button"),
|
doc = _("Tap Button"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:onFocus()
|
function Button:onFocus()
|
||||||
self[1].color = 15
|
self[1].color = 15
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:onUnfocus()
|
function Button:onUnfocus()
|
||||||
self[1].color = 5
|
self[1].color = 5
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:enable()
|
function Button:enable()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
if self.text then
|
if self.text then
|
||||||
self.label_widget.fgcolor = self.enabled and 1.0 or 0.5
|
self.label_widget.fgcolor = self.enabled and 1.0 or 0.5
|
||||||
else
|
else
|
||||||
self.label_widget.dim = not self.enabled
|
self.label_widget.dim = not self.enabled
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:disable()
|
function Button:disable()
|
||||||
self.enabled = false
|
self.enabled = false
|
||||||
if self.text then
|
if self.text then
|
||||||
self.label_widget.fgcolor = self.enabled and 1.0 or 0.5
|
self.label_widget.fgcolor = self.enabled and 1.0 or 0.5
|
||||||
else
|
else
|
||||||
self.label_widget.dim = not self.enabled
|
self.label_widget.dim = not self.enabled
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:enableDisable(enable)
|
function Button:enableDisable(enable)
|
||||||
if enable then
|
if enable then
|
||||||
self:enable()
|
self:enable()
|
||||||
else
|
else
|
||||||
self:disable()
|
self:disable()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:hide()
|
function Button:hide()
|
||||||
if self.icon then
|
if self.icon then
|
||||||
self.label_widget.hide = true
|
self.label_widget.hide = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:show()
|
function Button:show()
|
||||||
if self.icon then
|
if self.icon then
|
||||||
self.label_widget.hide = false
|
self.label_widget.hide = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:showHide(show)
|
function Button:showHide(show)
|
||||||
if show then
|
if show then
|
||||||
self:show()
|
self:show()
|
||||||
else
|
else
|
||||||
self:hide()
|
self:hide()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Button:onTapSelect()
|
function Button:onTapSelect()
|
||||||
if self.enabled then
|
if self.enabled then
|
||||||
self.callback()
|
self.callback()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return Button
|
return Button
|
||||||
|
|||||||
@@ -11,49 +11,49 @@ local UIManager = require("ui/uimanager")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ButtonDialog = InputContainer:new{
|
local ButtonDialog = InputContainer:new{
|
||||||
buttons = nil,
|
buttons = nil,
|
||||||
tap_close_callback = nil,
|
tap_close_callback = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ButtonDialog:init()
|
function ButtonDialog:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
AnyKeyPressed = { { Input.group.Any },
|
AnyKeyPressed = { { Input.group.Any },
|
||||||
seqtext = "any key", doc = _("close dialog") }
|
seqtext = "any key", doc = _("close dialog") }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self.ges_events.TapClose = {
|
self.ges_events.TapClose = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self[1] = CenterContainer:new{
|
self[1] = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
ButtonTable:new{
|
ButtonTable:new{
|
||||||
width = Screen:getWidth()*0.9,
|
width = Screen:getWidth()*0.9,
|
||||||
buttons = self.buttons,
|
buttons = self.buttons,
|
||||||
},
|
},
|
||||||
background = 0,
|
background = 0,
|
||||||
bordersize = 2,
|
bordersize = 2,
|
||||||
radius = 7,
|
radius = 7,
|
||||||
padding = 2,
|
padding = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ButtonDialog:onTapClose()
|
function ButtonDialog:onTapClose()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
if self.tap_close_callback then
|
if self.tap_close_callback then
|
||||||
self.tap_close_callback()
|
self.tap_close_callback()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ButtonDialog
|
return ButtonDialog
|
||||||
|
|||||||
@@ -7,72 +7,72 @@ local Screen = require("ui/screen")
|
|||||||
local Geom = require("ui/geometry")
|
local Geom = require("ui/geometry")
|
||||||
|
|
||||||
local ButtonTable = VerticalGroup:new{
|
local ButtonTable = VerticalGroup:new{
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{text="OK", enabled=true, callback=nil},
|
{text="OK", enabled=true, callback=nil},
|
||||||
{text="Cancel", enabled=false, callback=nil},
|
{text="Cancel", enabled=false, callback=nil},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sep_width = Screen:scaleByDPI(1),
|
sep_width = Screen:scaleByDPI(1),
|
||||||
padding = Screen:scaleByDPI(2),
|
padding = Screen:scaleByDPI(2),
|
||||||
|
|
||||||
zero_sep = false,
|
zero_sep = false,
|
||||||
button_font_face = "cfont",
|
button_font_face = "cfont",
|
||||||
button_font_size = 20,
|
button_font_size = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ButtonTable:init()
|
function ButtonTable:init()
|
||||||
--local vertical_group = VerticalGroup:new{}
|
--local vertical_group = VerticalGroup:new{}
|
||||||
if self.zero_sep then
|
if self.zero_sep then
|
||||||
self:addHorizontalSep()
|
self:addHorizontalSep()
|
||||||
end
|
end
|
||||||
for i = 1, #self.buttons do
|
for i = 1, #self.buttons do
|
||||||
local horizontal_group = HorizontalGroup:new{}
|
local horizontal_group = HorizontalGroup:new{}
|
||||||
local line = self.buttons[i]
|
local line = self.buttons[i]
|
||||||
local sizer_space = self.sep_width * (#line - 1) + 2
|
local sizer_space = self.sep_width * (#line - 1) + 2
|
||||||
for j = 1, #line do
|
for j = 1, #line do
|
||||||
local button = Button:new{
|
local button = Button:new{
|
||||||
text = line[j].text,
|
text = line[j].text,
|
||||||
enabled = line[j].enabled,
|
enabled = line[j].enabled,
|
||||||
callback = line[j].callback,
|
callback = line[j].callback,
|
||||||
width = (self.width - sizer_space)/#line,
|
width = (self.width - sizer_space)/#line,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
text_font_face = self.button_font_face,
|
text_font_face = self.button_font_face,
|
||||||
text_font_size = self.button_font_size,
|
text_font_size = self.button_font_size,
|
||||||
}
|
}
|
||||||
local button_dim = button:getSize()
|
local button_dim = button:getSize()
|
||||||
local vertical_sep = LineWidget:new{
|
local vertical_sep = LineWidget:new{
|
||||||
background = 8,
|
background = 8,
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = self.sep_width,
|
w = self.sep_width,
|
||||||
h = button_dim.h,
|
h = button_dim.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table.insert(horizontal_group, button)
|
table.insert(horizontal_group, button)
|
||||||
if j < #line then
|
if j < #line then
|
||||||
table.insert(horizontal_group, vertical_sep)
|
table.insert(horizontal_group, vertical_sep)
|
||||||
end
|
end
|
||||||
end -- end for each button
|
end -- end for each button
|
||||||
table.insert(self, horizontal_group)
|
table.insert(self, horizontal_group)
|
||||||
if i < #self.buttons then
|
if i < #self.buttons then
|
||||||
self:addHorizontalSep()
|
self:addHorizontalSep()
|
||||||
end
|
end
|
||||||
end -- end for each button line
|
end -- end for each button line
|
||||||
end
|
end
|
||||||
|
|
||||||
function ButtonTable:addHorizontalSep()
|
function ButtonTable:addHorizontalSep()
|
||||||
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
|
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
|
||||||
table.insert(self, LineWidget:new{
|
table.insert(self, LineWidget:new{
|
||||||
background = 8,
|
background = 8,
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = self.width,
|
w = self.width,
|
||||||
h = self.sep_width,
|
h = self.sep_width,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
|
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
|
||||||
end
|
end
|
||||||
|
|
||||||
return ButtonTable
|
return ButtonTable
|
||||||
|
|||||||
@@ -11,35 +11,35 @@ local Font = require("ui/font")
|
|||||||
a button widget that shows an "×" and handles closing window when tapped
|
a button widget that shows an "×" and handles closing window when tapped
|
||||||
--]]
|
--]]
|
||||||
local CloseButton = InputContainer:new{
|
local CloseButton = InputContainer:new{
|
||||||
align = "right",
|
align = "right",
|
||||||
window = nil,
|
window = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function CloseButton:init()
|
function CloseButton:init()
|
||||||
local text_widget = TextWidget:new{
|
local text_widget = TextWidget:new{
|
||||||
text = "×",
|
text = "×",
|
||||||
face = Font:getFace("cfont", 32),
|
face = Font:getFace("cfont", 32),
|
||||||
}
|
}
|
||||||
self[1] = FrameContainer:new{
|
self[1] = FrameContainer:new{
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
text_widget
|
text_widget
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dimen = text_widget:getSize():copy()
|
self.dimen = text_widget:getSize():copy()
|
||||||
|
|
||||||
self.ges_events.Close = {
|
self.ges_events.Close = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = "Tap on close button",
|
doc = "Tap on close button",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function CloseButton:onClose()
|
function CloseButton:onClose()
|
||||||
self.window:onClose()
|
self.window:onClose()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return CloseButton
|
return CloseButton
|
||||||
|
|||||||
@@ -26,363 +26,363 @@ local _ = require("gettext")
|
|||||||
|
|
||||||
local MenuBarItem = InputContainer:new{}
|
local MenuBarItem = InputContainer:new{}
|
||||||
function MenuBarItem:init()
|
function MenuBarItem:init()
|
||||||
self.dimen = self[1]:getSize()
|
self.dimen = self[1]:getSize()
|
||||||
-- we need this table per-instance, so we declare it here
|
-- we need this table per-instance, so we declare it here
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Select Menu Item"),
|
doc = _("Select Menu Item"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self.active_key_events = {
|
self.active_key_events = {
|
||||||
Select = { {"Press"}, doc = _("chose selected item") },
|
Select = { {"Press"}, doc = _("chose selected item") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MenuBarItem:onTapSelect()
|
function MenuBarItem:onTapSelect()
|
||||||
UIManager:scheduleIn(0.0, function() self:invert(true) end)
|
UIManager:scheduleIn(0.0, function() self:invert(true) end)
|
||||||
UIManager:scheduleIn(0.1, function()
|
UIManager:scheduleIn(0.1, function()
|
||||||
UIManager:sendEvent(Event:new("ShowConfigPanel", self.index))
|
UIManager:sendEvent(Event:new("ShowConfigPanel", self.index))
|
||||||
end)
|
end)
|
||||||
UIManager:scheduleIn(0.5, function() self:invert(false) end)
|
UIManager:scheduleIn(0.5, function() self:invert(false) end)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function MenuBarItem:invert(invert)
|
function MenuBarItem:invert(invert)
|
||||||
self[1].invert = invert
|
self[1].invert = invert
|
||||||
UIManager.update_region_func = function()
|
UIManager.update_region_func = function()
|
||||||
DEBUG("update icon region", self[1].dimen)
|
DEBUG("update icon region", self[1].dimen)
|
||||||
return self[1].dimen
|
return self[1].dimen
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.config, "full")
|
UIManager:setDirty(self.config, "full")
|
||||||
end
|
end
|
||||||
|
|
||||||
local OptionTextItem = InputContainer:new{}
|
local OptionTextItem = InputContainer:new{}
|
||||||
function OptionTextItem:init()
|
function OptionTextItem:init()
|
||||||
local text_widget = self[1]
|
local text_widget = self[1]
|
||||||
|
|
||||||
self[1] = UnderlineContainer:new{
|
self[1] = UnderlineContainer:new{
|
||||||
text_widget,
|
text_widget,
|
||||||
padding = self.padding,
|
padding = self.padding,
|
||||||
color = self.color,
|
color = self.color,
|
||||||
}
|
}
|
||||||
self.dimen = self[1]:getSize()
|
self.dimen = self[1]:getSize()
|
||||||
-- we need this table per-instance, so we declare it here
|
-- we need this table per-instance, so we declare it here
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Select Option Item"),
|
doc = _("Select Option Item"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self.active_key_events = {
|
self.active_key_events = {
|
||||||
Select = { {"Press"}, doc = _("chose selected item") },
|
Select = { {"Press"}, doc = _("chose selected item") },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function OptionTextItem:onTapSelect()
|
function OptionTextItem:onTapSelect()
|
||||||
for _, item in pairs(self.items) do
|
for _, item in pairs(self.items) do
|
||||||
item[1].color = 0
|
item[1].color = 0
|
||||||
end
|
end
|
||||||
self[1].color = 15
|
self[1].color = 15
|
||||||
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.current_item)
|
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.current_item)
|
||||||
UIManager:setDirty(self.config, "partial")
|
UIManager:setDirty(self.config, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local OptionIconItem = InputContainer:new{}
|
local OptionIconItem = InputContainer:new{}
|
||||||
function OptionIconItem:init()
|
function OptionIconItem:init()
|
||||||
self.dimen = self.icon:getSize()
|
self.dimen = self.icon:getSize()
|
||||||
self[1] = UnderlineContainer:new{
|
self[1] = UnderlineContainer:new{
|
||||||
self.icon,
|
self.icon,
|
||||||
padding = self.padding,
|
padding = self.padding,
|
||||||
color = self.color,
|
color = self.color,
|
||||||
}
|
}
|
||||||
-- we need this table per-instance, so we declare it here
|
-- we need this table per-instance, so we declare it here
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Select Option Item"),
|
doc = _("Select Option Item"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function OptionIconItem:onTapSelect()
|
function OptionIconItem:onTapSelect()
|
||||||
for _, item in pairs(self.items) do
|
for _, item in pairs(self.items) do
|
||||||
--item[1][1].invert = false
|
--item[1][1].invert = false
|
||||||
item[1].color = 0
|
item[1].color = 0
|
||||||
end
|
end
|
||||||
--self[1][1].invert = true
|
--self[1][1].invert = true
|
||||||
self[1].color = 15
|
self[1].color = 15
|
||||||
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.current_item)
|
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.current_item)
|
||||||
UIManager:setDirty(self.config, "partial")
|
UIManager:setDirty(self.config, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local ConfigOption = CenterContainer:new{}
|
local ConfigOption = CenterContainer:new{}
|
||||||
function ConfigOption:init()
|
function ConfigOption:init()
|
||||||
local default_name_font_size = 20
|
local default_name_font_size = 20
|
||||||
local default_item_font_size = 16
|
local default_item_font_size = 16
|
||||||
local default_items_spacing = 30
|
local default_items_spacing = 30
|
||||||
local default_option_height = 50
|
local default_option_height = 50
|
||||||
local default_option_padding = 15
|
local default_option_padding = 15
|
||||||
local vertical_group = VerticalGroup:new{}
|
local vertical_group = VerticalGroup:new{}
|
||||||
table.insert(vertical_group, VerticalSpan:new{
|
table.insert(vertical_group, VerticalSpan:new{
|
||||||
width = Screen:scaleByDPI(default_option_padding),
|
width = Screen:scaleByDPI(default_option_padding),
|
||||||
})
|
})
|
||||||
for c = 1, #self.options do
|
for c = 1, #self.options do
|
||||||
if self.options[c].show ~= false then
|
if self.options[c].show ~= false then
|
||||||
local name_align = self.options[c].name_align_right and self.options[c].name_align_right or 0.33
|
local name_align = self.options[c].name_align_right and self.options[c].name_align_right or 0.33
|
||||||
local item_align = self.options[c].item_align_center and self.options[c].item_align_center or 0.66
|
local item_align = self.options[c].item_align_center and self.options[c].item_align_center or 0.66
|
||||||
local name_font_face = self.options[c].name_font_face and self.options[c].name_font_face or "cfont"
|
local name_font_face = self.options[c].name_font_face and self.options[c].name_font_face or "cfont"
|
||||||
local name_font_size = self.options[c].name_font_size and self.options[c].name_font_size or default_name_font_size
|
local name_font_size = self.options[c].name_font_size and self.options[c].name_font_size or default_name_font_size
|
||||||
local item_font_face = self.options[c].item_font_face and self.options[c].item_font_face or "cfont"
|
local item_font_face = self.options[c].item_font_face and self.options[c].item_font_face or "cfont"
|
||||||
local item_font_size = self.options[c].item_font_size and self.options[c].item_font_size or default_item_font_size
|
local item_font_size = self.options[c].item_font_size and self.options[c].item_font_size or default_item_font_size
|
||||||
local option_height = Screen:scaleByDPI(self.options[c].height and self.options[c].height or default_option_height)
|
local option_height = Screen:scaleByDPI(self.options[c].height and self.options[c].height or default_option_height)
|
||||||
local items_spacing = HorizontalSpan:new{
|
local items_spacing = HorizontalSpan:new{
|
||||||
width = Screen:scaleByDPI(self.options[c].spacing and self.options[c].spacing or default_items_spacing)
|
width = Screen:scaleByDPI(self.options[c].spacing and self.options[c].spacing or default_items_spacing)
|
||||||
}
|
}
|
||||||
local horizontal_group = HorizontalGroup:new{}
|
local horizontal_group = HorizontalGroup:new{}
|
||||||
if self.options[c].name_text then
|
if self.options[c].name_text then
|
||||||
local option_name_container = RightContainer:new{
|
local option_name_container = RightContainer:new{
|
||||||
dimen = Geom:new{ w = Screen:getWidth()*name_align, h = option_height},
|
dimen = Geom:new{ w = Screen:getWidth()*name_align, h = option_height},
|
||||||
}
|
}
|
||||||
local option_name = TextWidget:new{
|
local option_name = TextWidget:new{
|
||||||
text = self.options[c].name_text,
|
text = self.options[c].name_text,
|
||||||
face = Font:getFace(name_font_face, name_font_size),
|
face = Font:getFace(name_font_face, name_font_size),
|
||||||
}
|
}
|
||||||
table.insert(option_name_container, option_name)
|
table.insert(option_name_container, option_name)
|
||||||
table.insert(horizontal_group, option_name_container)
|
table.insert(horizontal_group, option_name_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.options[c].widget == "ProgressWidget" then
|
if self.options[c].widget == "ProgressWidget" then
|
||||||
local widget_container = CenterContainer:new{
|
local widget_container = CenterContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth()*self.options[c].widget_align_center, h = option_height}
|
dimen = Geom:new{w = Screen:getWidth()*self.options[c].widget_align_center, h = option_height}
|
||||||
}
|
}
|
||||||
local widget = ProgressWidget:new{
|
local widget = ProgressWidget:new{
|
||||||
width = self.options[c].width,
|
width = self.options[c].width,
|
||||||
height = self.options[c].height,
|
height = self.options[c].height,
|
||||||
percentage = self.options[c].percentage,
|
percentage = self.options[c].percentage,
|
||||||
}
|
}
|
||||||
table.insert(widget_container, widget)
|
table.insert(widget_container, widget)
|
||||||
table.insert(horizontal_group, widget_container)
|
table.insert(horizontal_group, widget_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
local option_items_container = CenterContainer:new{
|
local option_items_container = CenterContainer:new{
|
||||||
dimen = Geom:new{w = Screen:getWidth()*item_align, h = option_height}
|
dimen = Geom:new{w = Screen:getWidth()*item_align, h = option_height}
|
||||||
}
|
}
|
||||||
local option_items_group = HorizontalGroup:new{}
|
local option_items_group = HorizontalGroup:new{}
|
||||||
local option_items_fixed = false
|
local option_items_fixed = false
|
||||||
local option_items = {}
|
local option_items = {}
|
||||||
if type(self.options[c].item_font_size) == "table" then
|
if type(self.options[c].item_font_size) == "table" then
|
||||||
option_items_group.align = "bottom"
|
option_items_group.align = "bottom"
|
||||||
option_items_fixed = true
|
option_items_fixed = true
|
||||||
end
|
end
|
||||||
-- make current index according to configurable table
|
-- make current index according to configurable table
|
||||||
local current_item = nil
|
local current_item = nil
|
||||||
local function value_diff(val1, val2, name)
|
local function value_diff(val1, val2, name)
|
||||||
if type(val1) ~= type(val2) then
|
if type(val1) ~= type(val2) then
|
||||||
error("different data types in option", name)
|
error("different data types in option", name)
|
||||||
end
|
end
|
||||||
if type(val1) == "number" then
|
if type(val1) == "number" then
|
||||||
return math.abs(val1 - val2)
|
return math.abs(val1 - val2)
|
||||||
elseif type(val1) == "string" then
|
elseif type(val1) == "string" then
|
||||||
return val1 == val2 and 0 or 1
|
return val1 == val2 and 0 or 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.options[c].name then
|
if self.options[c].name then
|
||||||
if self.options[c].values then
|
if self.options[c].values then
|
||||||
-- check if current value is stored in configurable or calculated in runtime
|
-- check if current value is stored in configurable or calculated in runtime
|
||||||
local val = self.options[c].current_func and self.options[c].current_func()
|
local val = self.options[c].current_func and self.options[c].current_func()
|
||||||
or self.config.configurable[self.options[c].name]
|
or self.config.configurable[self.options[c].name]
|
||||||
local min_diff = nil
|
local min_diff = nil
|
||||||
if type(val) == "table" then
|
if type(val) == "table" then
|
||||||
min_diff = value_diff(val[1], self.options[c].values[1][1])
|
min_diff = value_diff(val[1], self.options[c].values[1][1])
|
||||||
else
|
else
|
||||||
min_diff = value_diff(val, self.options[c].values[1])
|
min_diff = value_diff(val, self.options[c].values[1])
|
||||||
end
|
end
|
||||||
|
|
||||||
local diff = nil
|
local diff = nil
|
||||||
for index, val_ in pairs(self.options[c].values) do
|
for index, val_ in pairs(self.options[c].values) do
|
||||||
local diff = nil
|
local diff = nil
|
||||||
if type(val) == "table" then
|
if type(val) == "table" then
|
||||||
diff = value_diff(val[1], val_[1])
|
diff = value_diff(val[1], val_[1])
|
||||||
else
|
else
|
||||||
diff = value_diff(val, val_)
|
diff = value_diff(val, val_)
|
||||||
end
|
end
|
||||||
if val == val_ then
|
if val == val_ then
|
||||||
current_item = index
|
current_item = index
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if diff <= min_diff then
|
if diff <= min_diff then
|
||||||
min_diff = diff
|
min_diff = diff
|
||||||
current_item = index
|
current_item = index
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif self.options[c].args then
|
elseif self.options[c].args then
|
||||||
-- check if current arg is stored in configurable or calculated in runtime
|
-- check if current arg is stored in configurable or calculated in runtime
|
||||||
local arg = self.options[c].current_func and self.options[c].current_func()
|
local arg = self.options[c].current_func and self.options[c].current_func()
|
||||||
or self.config.configurable[self.options[c].name]
|
or self.config.configurable[self.options[c].name]
|
||||||
for idx, arg_ in pairs(self.options[c].args) do
|
for idx, arg_ in pairs(self.options[c].args) do
|
||||||
if arg_ == arg then
|
if arg_ == arg then
|
||||||
current_item = idx
|
current_item = idx
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.options[c].item_text then
|
if self.options[c].item_text then
|
||||||
for d = 1, #self.options[c].item_text do
|
for d = 1, #self.options[c].item_text do
|
||||||
local option_item = nil
|
local option_item = nil
|
||||||
if option_items_fixed then
|
if option_items_fixed then
|
||||||
option_item = OptionTextItem:new{
|
option_item = OptionTextItem:new{
|
||||||
FixedTextWidget:new{
|
FixedTextWidget:new{
|
||||||
text = self.options[c].item_text[d],
|
text = self.options[c].item_text[d],
|
||||||
face = Font:getFace(item_font_face, item_font_size[d]),
|
face = Font:getFace(item_font_face, item_font_size[d]),
|
||||||
},
|
},
|
||||||
padding = 3,
|
padding = 3,
|
||||||
color = d == current_item and 15 or 0,
|
color = d == current_item and 15 or 0,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
option_item = OptionTextItem:new{
|
option_item = OptionTextItem:new{
|
||||||
TextWidget:new{
|
TextWidget:new{
|
||||||
text = self.options[c].item_text[d],
|
text = self.options[c].item_text[d],
|
||||||
face = Font:getFace(item_font_face, item_font_size),
|
face = Font:getFace(item_font_face, item_font_size),
|
||||||
},
|
},
|
||||||
padding = -3,
|
padding = -3,
|
||||||
color = d == current_item and 15 or 0,
|
color = d == current_item and 15 or 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
option_items[d] = option_item
|
option_items[d] = option_item
|
||||||
option_item.items = option_items
|
option_item.items = option_items
|
||||||
option_item.name = self.options[c].name
|
option_item.name = self.options[c].name
|
||||||
option_item.values = self.options[c].values
|
option_item.values = self.options[c].values
|
||||||
option_item.args = self.options[c].args
|
option_item.args = self.options[c].args
|
||||||
option_item.event = self.options[c].event
|
option_item.event = self.options[c].event
|
||||||
option_item.current_item = d
|
option_item.current_item = d
|
||||||
option_item.config = self.config
|
option_item.config = self.config
|
||||||
table.insert(option_items_group, option_item)
|
table.insert(option_items_group, option_item)
|
||||||
if d ~= #self.options[c].item_text then
|
if d ~= #self.options[c].item_text then
|
||||||
table.insert(option_items_group, items_spacing)
|
table.insert(option_items_group, items_spacing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.options[c].item_icons then
|
if self.options[c].item_icons then
|
||||||
for d = 1, #self.options[c].item_icons do
|
for d = 1, #self.options[c].item_icons do
|
||||||
local option_item = OptionIconItem:new{
|
local option_item = OptionIconItem:new{
|
||||||
icon = ImageWidget:new{
|
icon = ImageWidget:new{
|
||||||
file = self.options[c].item_icons[d]
|
file = self.options[c].item_icons[d]
|
||||||
},
|
},
|
||||||
padding = -2,
|
padding = -2,
|
||||||
color = d == current_item and 15 or 0,
|
color = d == current_item and 15 or 0,
|
||||||
}
|
}
|
||||||
option_items[d] = option_item
|
option_items[d] = option_item
|
||||||
option_item.items = option_items
|
option_item.items = option_items
|
||||||
option_item.name = self.options[c].name
|
option_item.name = self.options[c].name
|
||||||
option_item.values = self.options[c].values
|
option_item.values = self.options[c].values
|
||||||
option_item.args = self.options[c].args
|
option_item.args = self.options[c].args
|
||||||
option_item.event = self.options[c].event
|
option_item.event = self.options[c].event
|
||||||
option_item.current_item = d
|
option_item.current_item = d
|
||||||
option_item.config = self.config
|
option_item.config = self.config
|
||||||
table.insert(option_items_group, option_item)
|
table.insert(option_items_group, option_item)
|
||||||
if d ~= #self.options[c].item_icons then
|
if d ~= #self.options[c].item_icons then
|
||||||
table.insert(option_items_group, items_spacing)
|
table.insert(option_items_group, items_spacing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.options[c].toggle then
|
if self.options[c].toggle then
|
||||||
local switch = ToggleSwitch:new{
|
local switch = ToggleSwitch:new{
|
||||||
width = Screen:scaleByDPI(self.options[c].width or 216),
|
width = Screen:scaleByDPI(self.options[c].width or 216),
|
||||||
name = self.options[c].name,
|
name = self.options[c].name,
|
||||||
toggle = self.options[c].toggle,
|
toggle = self.options[c].toggle,
|
||||||
alternate = self.options[c].alternate,
|
alternate = self.options[c].alternate,
|
||||||
values = self.options[c].values,
|
values = self.options[c].values,
|
||||||
args = self.options[c].args,
|
args = self.options[c].args,
|
||||||
event = self.options[c].event,
|
event = self.options[c].event,
|
||||||
events = self.options[c].events,
|
events = self.options[c].events,
|
||||||
config = self.config,
|
config = self.config,
|
||||||
}
|
}
|
||||||
local position = current_item
|
local position = current_item
|
||||||
switch:setPosition(position)
|
switch:setPosition(position)
|
||||||
table.insert(option_items_group, switch)
|
table.insert(option_items_group, switch)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(option_items_container, option_items_group)
|
table.insert(option_items_container, option_items_group)
|
||||||
table.insert(horizontal_group, option_items_container)
|
table.insert(horizontal_group, option_items_container)
|
||||||
table.insert(vertical_group, horizontal_group)
|
table.insert(vertical_group, horizontal_group)
|
||||||
end -- if
|
end -- if
|
||||||
end -- for
|
end -- for
|
||||||
table.insert(vertical_group, VerticalSpan:new{ width = default_option_padding })
|
table.insert(vertical_group, VerticalSpan:new{ width = default_option_padding })
|
||||||
self[1] = vertical_group
|
self[1] = vertical_group
|
||||||
self.dimen = vertical_group:getSize()
|
self.dimen = vertical_group:getSize()
|
||||||
end
|
end
|
||||||
|
|
||||||
local ConfigPanel = FrameContainer:new{ background = 0, bordersize = 0, }
|
local ConfigPanel = FrameContainer:new{ background = 0, bordersize = 0, }
|
||||||
function ConfigPanel:init()
|
function ConfigPanel:init()
|
||||||
local config_options = self.config_dialog.config_options
|
local config_options = self.config_dialog.config_options
|
||||||
local default_option = config_options.default_options and config_options.default_options
|
local default_option = config_options.default_options and config_options.default_options
|
||||||
or config_options[1].options
|
or config_options[1].options
|
||||||
local panel = ConfigOption:new{
|
local panel = ConfigOption:new{
|
||||||
options = self.index and config_options[self.index].options or default_option,
|
options = self.index and config_options[self.index].options or default_option,
|
||||||
config = self.config_dialog,
|
config = self.config_dialog,
|
||||||
}
|
}
|
||||||
self.dimen = panel:getSize()
|
self.dimen = panel:getSize()
|
||||||
table.insert(self, panel)
|
table.insert(self, panel)
|
||||||
end
|
end
|
||||||
|
|
||||||
local MenuBar = FrameContainer:new{ background = 0, }
|
local MenuBar = FrameContainer:new{ background = 0, }
|
||||||
function MenuBar:init()
|
function MenuBar:init()
|
||||||
local config_options = self.config_dialog.config_options
|
local config_options = self.config_dialog.config_options
|
||||||
local menu_items = {}
|
local menu_items = {}
|
||||||
local icons_width = 0
|
local icons_width = 0
|
||||||
local icons_height = 0
|
local icons_height = 0
|
||||||
for c = 1, #config_options do
|
for c = 1, #config_options do
|
||||||
local menu_icon = ImageWidget:new{
|
local menu_icon = ImageWidget:new{
|
||||||
file = config_options[c].icon
|
file = config_options[c].icon
|
||||||
}
|
}
|
||||||
local icon_dimen = menu_icon:getSize()
|
local icon_dimen = menu_icon:getSize()
|
||||||
icons_width = icons_width + icon_dimen.w
|
icons_width = icons_width + icon_dimen.w
|
||||||
icons_height = icon_dimen.h > icons_height and icon_dimen.h or icons_height
|
icons_height = icon_dimen.h > icons_height and icon_dimen.h or icons_height
|
||||||
|
|
||||||
menu_items[c] = MenuBarItem:new{
|
menu_items[c] = MenuBarItem:new{
|
||||||
menu_icon,
|
menu_icon,
|
||||||
index = c,
|
index = c,
|
||||||
config = self.config_dialog,
|
config = self.config_dialog,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local spacing = HorizontalSpan:new{
|
local spacing = HorizontalSpan:new{
|
||||||
width = (Screen:getWidth() - icons_width) / (#menu_items+1)
|
width = (Screen:getWidth() - icons_width) / (#menu_items+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
local menu_bar = HorizontalGroup:new{}
|
local menu_bar = HorizontalGroup:new{}
|
||||||
|
|
||||||
for c = 1, #menu_items do
|
for c = 1, #menu_items do
|
||||||
table.insert(menu_bar, spacing)
|
table.insert(menu_bar, spacing)
|
||||||
table.insert(menu_bar, menu_items[c])
|
table.insert(menu_bar, menu_items[c])
|
||||||
end
|
end
|
||||||
table.insert(menu_bar, spacing)
|
table.insert(menu_bar, spacing)
|
||||||
|
|
||||||
self.dimen = Geom:new{ w = Screen:getWidth(), h = icons_height}
|
self.dimen = Geom:new{ w = Screen:getWidth(), h = icons_height}
|
||||||
table.insert(self, menu_bar)
|
table.insert(self, menu_bar)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -405,122 +405,122 @@ Widget that displays config menubar and config panel
|
|||||||
--]]
|
--]]
|
||||||
|
|
||||||
local ConfigDialog = InputContainer:new{
|
local ConfigDialog = InputContainer:new{
|
||||||
--is_borderless = false,
|
--is_borderless = false,
|
||||||
panel_index = 1,
|
panel_index = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfigDialog:init()
|
function ConfigDialog:init()
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
-- start to set up widget layout ---------
|
-- start to set up widget layout ---------
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
self.config_menubar = MenuBar:new{
|
self.config_menubar = MenuBar:new{
|
||||||
config_dialog = self,
|
config_dialog = self,
|
||||||
}
|
}
|
||||||
self:update()
|
self:update()
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
-- start to set up input event callback --
|
-- start to set up input event callback --
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events.TapCloseMenu = {
|
self.ges_events.TapCloseMenu = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
-- set up keyboard events
|
-- set up keyboard events
|
||||||
self.key_events.Close = { {"Back"}, doc = _("close config menu") }
|
self.key_events.Close = { {"Back"}, doc = _("close config menu") }
|
||||||
-- we won't catch presses to "Right"
|
-- we won't catch presses to "Right"
|
||||||
self.key_events.FocusRight = nil
|
self.key_events.FocusRight = nil
|
||||||
end
|
end
|
||||||
self.key_events.Select = { {"Press"}, doc = _("select current menu item") }
|
self.key_events.Select = { {"Press"}, doc = _("select current menu item") }
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:updateConfigPanel(index)
|
function ConfigDialog:updateConfigPanel(index)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:update()
|
function ConfigDialog:update()
|
||||||
self.config_panel = ConfigPanel:new{
|
self.config_panel = ConfigPanel:new{
|
||||||
index = self.panel_index,
|
index = self.panel_index,
|
||||||
config_dialog = self,
|
config_dialog = self,
|
||||||
}
|
}
|
||||||
self.dialog_frame = FrameContainer:new{
|
self.dialog_frame = FrameContainer:new{
|
||||||
background = 0,
|
background = 0,
|
||||||
VerticalGroup:new{
|
VerticalGroup:new{
|
||||||
self.config_panel,
|
self.config_panel,
|
||||||
self.config_menubar,
|
self.config_menubar,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self[1] = BottomContainer:new{
|
self[1] = BottomContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
self.dialog_frame,
|
self.dialog_frame,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onShowConfigPanel(index)
|
function ConfigDialog:onShowConfigPanel(index)
|
||||||
self.panel_index = index
|
self.panel_index = index
|
||||||
self:update()
|
self:update()
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onConfigChoice(option_name, option_value)
|
function ConfigDialog:onConfigChoice(option_name, option_value)
|
||||||
--DEBUG("config option value", option_name, option_value)
|
--DEBUG("config option value", option_name, option_value)
|
||||||
self.configurable[option_name] = option_value
|
self.configurable[option_name] = option_value
|
||||||
self.ui:handleEvent(Event:new("StartActivityIndicator"))
|
self.ui:handleEvent(Event:new("StartActivityIndicator"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onConfigEvent(option_event, option_arg)
|
function ConfigDialog:onConfigEvent(option_event, option_arg)
|
||||||
--DEBUG("config option event", option_event, option_arg)
|
--DEBUG("config option event", option_event, option_arg)
|
||||||
self.ui:handleEvent(Event:new(option_event, option_arg))
|
self.ui:handleEvent(Event:new(option_event, option_arg))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onConfigEvents(option_events, arg_index)
|
function ConfigDialog:onConfigEvents(option_events, arg_index)
|
||||||
--DEBUG("config option events", option_events, arg_index)
|
--DEBUG("config option events", option_events, arg_index)
|
||||||
for i=1, #option_events do
|
for i=1, #option_events do
|
||||||
option_events[i].args = option_events[i].args or {}
|
option_events[i].args = option_events[i].args or {}
|
||||||
self.ui:handleEvent(Event:new(option_events[i].event, option_events[i].args[arg_index]))
|
self.ui:handleEvent(Event:new(option_events[i].event, option_events[i].args[arg_index]))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onConfigChoose(values, name, event, args, events, position)
|
function ConfigDialog:onConfigChoose(values, name, event, args, events, position)
|
||||||
UIManager:scheduleIn(0.05, function()
|
UIManager:scheduleIn(0.05, function()
|
||||||
if values then
|
if values then
|
||||||
self:onConfigChoice(name, values[position])
|
self:onConfigChoice(name, values[position])
|
||||||
end
|
end
|
||||||
if event then
|
if event then
|
||||||
args = args or {}
|
args = args or {}
|
||||||
self:onConfigEvent(event, args[position])
|
self:onConfigEvent(event, args[position])
|
||||||
end
|
end
|
||||||
if events then
|
if events then
|
||||||
self:onConfigEvents(events, position)
|
self:onConfigEvents(events, position)
|
||||||
end
|
end
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:closeDialog()
|
function ConfigDialog:closeDialog()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
if self.close_callback then
|
if self.close_callback then
|
||||||
self.close_callback()
|
self.close_callback()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigDialog:onTapCloseMenu(arg, ges_ev)
|
function ConfigDialog:onTapCloseMenu(arg, ges_ev)
|
||||||
if ges_ev.pos:notIntersectWith(self.dialog_frame.dimen) then
|
if ges_ev.pos:notIntersectWith(self.dialog_frame.dimen) then
|
||||||
self:closeDialog()
|
self:closeDialog()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ConfigDialog
|
return ConfigDialog
|
||||||
|
|||||||
@@ -20,86 +20,86 @@ local _ = require("gettext")
|
|||||||
Widget that shows a message and OK/Cancel buttons
|
Widget that shows a message and OK/Cancel buttons
|
||||||
]]
|
]]
|
||||||
local ConfirmBox = FocusManager:new{
|
local ConfirmBox = FocusManager:new{
|
||||||
text = _("no text"),
|
text = _("no text"),
|
||||||
width = nil,
|
width = nil,
|
||||||
ok_text = _("OK"),
|
ok_text = _("OK"),
|
||||||
cancel_text = _("Cancel"),
|
cancel_text = _("Cancel"),
|
||||||
ok_callback = function() end,
|
ok_callback = function() end,
|
||||||
cancel_callback = function() end,
|
cancel_callback = function() end,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfirmBox:init()
|
function ConfirmBox:init()
|
||||||
-- calculate box width on the fly if not given
|
-- calculate box width on the fly if not given
|
||||||
if not self.width then
|
if not self.width then
|
||||||
self.width = Screen:getWidth() - 200
|
self.width = Screen:getWidth() - 200
|
||||||
end
|
end
|
||||||
-- build bottons
|
-- build bottons
|
||||||
self.key_events.Close = { {{"Home","Back"}}, doc = _("cancel") }
|
self.key_events.Close = { {{"Home","Back"}}, doc = _("cancel") }
|
||||||
self.key_events.Select = { {{"Enter","Press"}}, doc = _("chose selected option") }
|
self.key_events.Select = { {{"Enter","Press"}}, doc = _("chose selected option") }
|
||||||
|
|
||||||
local ok_button = Button:new{
|
local ok_button = Button:new{
|
||||||
text = self.ok_text,
|
text = self.ok_text,
|
||||||
callback = function()
|
callback = function()
|
||||||
self.ok_callback()
|
self.ok_callback()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
local cancel_button = Button:new{
|
local cancel_button = Button:new{
|
||||||
text = self.cancel_text,
|
text = self.cancel_text,
|
||||||
preselect = true,
|
preselect = true,
|
||||||
callback = function()
|
callback = function()
|
||||||
self.cancel_callback()
|
self.cancel_callback()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.layout = { { ok_button, cancel_button } }
|
self.layout = { { ok_button, cancel_button } }
|
||||||
self.selected.x = 2 -- Cancel is default
|
self.selected.x = 2 -- Cancel is default
|
||||||
|
|
||||||
self[1] = CenterContainer:new{
|
self[1] = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
margin = 2,
|
margin = 2,
|
||||||
background = 0,
|
background = 0,
|
||||||
padding = 10,
|
padding = 10,
|
||||||
HorizontalGroup:new{
|
HorizontalGroup:new{
|
||||||
ImageWidget:new{
|
ImageWidget:new{
|
||||||
file = "resources/info-i.png"
|
file = "resources/info-i.png"
|
||||||
},
|
},
|
||||||
HorizontalSpan:new{ width = 10 },
|
HorizontalSpan:new{ width = 10 },
|
||||||
VerticalGroup:new{
|
VerticalGroup:new{
|
||||||
align = "left",
|
align = "left",
|
||||||
TextBoxWidget:new{
|
TextBoxWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = Font:getFace("cfont", 30),
|
face = Font:getFace("cfont", 30),
|
||||||
width = self.width,
|
width = self.width,
|
||||||
},
|
},
|
||||||
VerticalSpan:new{ width = 10 },
|
VerticalSpan:new{ width = 10 },
|
||||||
HorizontalGroup:new{
|
HorizontalGroup:new{
|
||||||
ok_button,
|
ok_button,
|
||||||
HorizontalSpan:new{ width = 10 },
|
HorizontalSpan:new{ width = 10 },
|
||||||
cancel_button,
|
cancel_button,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfirmBox:onClose()
|
function ConfirmBox:onClose()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfirmBox:onSelect()
|
function ConfirmBox:onSelect()
|
||||||
DEBUG("selected:", self.selected.x)
|
DEBUG("selected:", self.selected.x)
|
||||||
if self.selected.x == 1 then
|
if self.selected.x == 1 then
|
||||||
self:ok_callback()
|
self:ok_callback()
|
||||||
else
|
else
|
||||||
self:cancel_callback()
|
self:cancel_callback()
|
||||||
end
|
end
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ConfirmBox
|
return ConfirmBox
|
||||||
|
|||||||
@@ -8,24 +8,24 @@ dimensions
|
|||||||
local BottomContainer = WidgetContainer:new()
|
local BottomContainer = WidgetContainer:new()
|
||||||
|
|
||||||
function BottomContainer:paintTo(bb, x, y)
|
function BottomContainer:paintTo(bb, x, y)
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
||||||
-- throw error? paint to scrap buffer and blit partially?
|
-- throw error? paint to scrap buffer and blit partially?
|
||||||
-- for now, we ignore this
|
-- for now, we ignore this
|
||||||
end
|
end
|
||||||
self[1]:paintTo(bb,
|
self[1]:paintTo(bb,
|
||||||
x + math.floor((self.dimen.w - contentSize.w)/2),
|
x + math.floor((self.dimen.w - contentSize.w)/2),
|
||||||
y + (self.dimen.h - contentSize.h))
|
y + (self.dimen.h - contentSize.h))
|
||||||
end
|
end
|
||||||
|
|
||||||
function BottomContainer:contentRange()
|
function BottomContainer:contentRange()
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
x = (self.dimen.x or 0) + math.floor((self.dimen.w - contentSize.w)/2),
|
x = (self.dimen.x or 0) + math.floor((self.dimen.w - contentSize.w)/2),
|
||||||
y = (self.dimen.y or 0) + self.dimen.h - contentSize.h,
|
y = (self.dimen.y or 0) + self.dimen.h - contentSize.h,
|
||||||
w = contentSize.w,
|
w = contentSize.w,
|
||||||
h = contentSize.h
|
h = contentSize.h
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return BottomContainer
|
return BottomContainer
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ CenterContainer centers its content (1 widget) within its own dimensions
|
|||||||
local CenterContainer = WidgetContainer:new()
|
local CenterContainer = WidgetContainer:new()
|
||||||
|
|
||||||
function CenterContainer:paintTo(bb, x, y)
|
function CenterContainer:paintTo(bb, x, y)
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
||||||
-- throw error? paint to scrap buffer and blit partially?
|
-- throw error? paint to scrap buffer and blit partially?
|
||||||
-- for now, we ignore this
|
-- for now, we ignore this
|
||||||
end
|
end
|
||||||
local x_pos = x
|
local x_pos = x
|
||||||
local y_pos = y
|
local y_pos = y
|
||||||
if self.ignore ~= "height" then
|
if self.ignore ~= "height" then
|
||||||
y_pos = y + math.floor((self.dimen.h - contentSize.h)/2)
|
y_pos = y + math.floor((self.dimen.h - contentSize.h)/2)
|
||||||
end
|
end
|
||||||
if self.ignore ~= "width" then
|
if self.ignore ~= "width" then
|
||||||
x_pos = x + math.floor((self.dimen.w - contentSize.w)/2)
|
x_pos = x + math.floor((self.dimen.w - contentSize.w)/2)
|
||||||
end
|
end
|
||||||
self[1]:paintTo(bb, x_pos, y_pos)
|
self[1]:paintTo(bb, x_pos, y_pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
return CenterContainer
|
return CenterContainer
|
||||||
|
|||||||
@@ -6,56 +6,56 @@ A FrameContainer is some graphics content (1 widget) that is surrounded by a
|
|||||||
frame
|
frame
|
||||||
--]]
|
--]]
|
||||||
local FrameContainer = WidgetContainer:new{
|
local FrameContainer = WidgetContainer:new{
|
||||||
background = nil,
|
background = nil,
|
||||||
color = 15,
|
color = 15,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
radius = 0,
|
radius = 0,
|
||||||
bordersize = 2,
|
bordersize = 2,
|
||||||
padding = 5,
|
padding = 5,
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
invert = false,
|
invert = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
function FrameContainer:getSize()
|
function FrameContainer:getSize()
|
||||||
local content_size = self[1]:getSize()
|
local content_size = self[1]:getSize()
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
w = content_size.w + ( self.margin + self.bordersize + self.padding ) * 2,
|
w = content_size.w + ( self.margin + self.bordersize + self.padding ) * 2,
|
||||||
h = content_size.h + ( self.margin + self.bordersize + self.padding ) * 2
|
h = content_size.h + ( self.margin + self.bordersize + self.padding ) * 2
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function FrameContainer:paintTo(bb, x, y)
|
function FrameContainer:paintTo(bb, x, y)
|
||||||
local my_size = self:getSize()
|
local my_size = self:getSize()
|
||||||
self.dimen = Geom:new{
|
self.dimen = Geom:new{
|
||||||
x = x, y = y,
|
x = x, y = y,
|
||||||
w = my_size.w,
|
w = my_size.w,
|
||||||
h = my_size.h
|
h = my_size.h
|
||||||
}
|
}
|
||||||
local container_width = self.width or my_size.w
|
local container_width = self.width or my_size.w
|
||||||
local container_height = self.height or my_size.h
|
local container_height = self.height or my_size.h
|
||||||
|
|
||||||
--@TODO get rid of margin here? 13.03 2013 (houqp)
|
--@TODO get rid of margin here? 13.03 2013 (houqp)
|
||||||
if self.background then
|
if self.background then
|
||||||
bb:paintRoundedRect(x, y, container_width, container_height,
|
bb:paintRoundedRect(x, y, container_width, container_height,
|
||||||
self.background, self.radius)
|
self.background, self.radius)
|
||||||
end
|
end
|
||||||
if self.bordersize > 0 then
|
if self.bordersize > 0 then
|
||||||
bb:paintBorder(x + self.margin, y + self.margin,
|
bb:paintBorder(x + self.margin, y + self.margin,
|
||||||
container_width - self.margin * 2,
|
container_width - self.margin * 2,
|
||||||
container_height - self.margin * 2,
|
container_height - self.margin * 2,
|
||||||
self.bordersize, self.color, self.radius)
|
self.bordersize, self.color, self.radius)
|
||||||
end
|
end
|
||||||
if self[1] then
|
if self[1] then
|
||||||
self[1]:paintTo(bb,
|
self[1]:paintTo(bb,
|
||||||
x + self.margin + self.bordersize + self.padding,
|
x + self.margin + self.bordersize + self.padding,
|
||||||
y + self.margin + self.bordersize + self.padding)
|
y + self.margin + self.bordersize + self.padding)
|
||||||
end
|
end
|
||||||
if self.invert then
|
if self.invert then
|
||||||
bb:invertRect(x + self.bordersize, y + self.bordersize,
|
bb:invertRect(x + self.bordersize, y + self.bordersize,
|
||||||
container_width - 2*self.bordersize,
|
container_width - 2*self.bordersize,
|
||||||
container_height - 2*self.bordersize)
|
container_height - 2*self.bordersize)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return FrameContainer
|
return FrameContainer
|
||||||
|
|||||||
@@ -8,60 +8,60 @@ an InputContainer is an WidgetContainer that handles input events
|
|||||||
|
|
||||||
an example for a key_event is this:
|
an example for a key_event is this:
|
||||||
|
|
||||||
PanBy20 = {
|
PanBy20 = {
|
||||||
{ "Shift", Input.group.Cursor },
|
{ "Shift", Input.group.Cursor },
|
||||||
seqtext = "Shift+Cursor",
|
seqtext = "Shift+Cursor",
|
||||||
doc = "pan by 20px",
|
doc = "pan by 20px",
|
||||||
event = "Pan", args = 20, is_inactive = true,
|
event = "Pan", args = 20, is_inactive = true,
|
||||||
},
|
},
|
||||||
PanNormal = {
|
PanNormal = {
|
||||||
{ Input.group.Cursor },
|
{ Input.group.Cursor },
|
||||||
seqtext = "Cursor",
|
seqtext = "Cursor",
|
||||||
doc = "pan by 10 px", event = "Pan", args = 10,
|
doc = "pan by 10 px", event = "Pan", args = 10,
|
||||||
},
|
},
|
||||||
Quit = { {"Home"} },
|
Quit = { {"Home"} },
|
||||||
|
|
||||||
it is suggested to reference configurable sequences from another table
|
it is suggested to reference configurable sequences from another table
|
||||||
and store that table as configuration setting
|
and store that table as configuration setting
|
||||||
--]]
|
--]]
|
||||||
local InputContainer = WidgetContainer:new{
|
local InputContainer = WidgetContainer:new{
|
||||||
vertical_align = "top",
|
vertical_align = "top",
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputContainer:_init()
|
function InputContainer:_init()
|
||||||
-- we need to do deep copy here
|
-- we need to do deep copy here
|
||||||
local new_key_events = {}
|
local new_key_events = {}
|
||||||
if self.key_events then
|
if self.key_events then
|
||||||
for k,v in pairs(self.key_events) do
|
for k,v in pairs(self.key_events) do
|
||||||
new_key_events[k] = v
|
new_key_events[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.key_events = new_key_events
|
self.key_events = new_key_events
|
||||||
|
|
||||||
local new_ges_events = {}
|
local new_ges_events = {}
|
||||||
if self.ges_events then
|
if self.ges_events then
|
||||||
for k,v in pairs(self.ges_events) do
|
for k,v in pairs(self.ges_events) do
|
||||||
new_ges_events[k] = v
|
new_ges_events[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.ges_events = new_ges_events
|
self.ges_events = new_ges_events
|
||||||
|
|
||||||
if not self.dimen then
|
if not self.dimen then
|
||||||
self.dimen = Geom:new{}
|
self.dimen = Geom:new{}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputContainer:paintTo(bb, x, y)
|
function InputContainer:paintTo(bb, x, y)
|
||||||
self.dimen.x = x
|
self.dimen.x = x
|
||||||
self.dimen.y = y
|
self.dimen.y = y
|
||||||
if self[1] then
|
if self[1] then
|
||||||
if self.vertical_align == "center" then
|
if self.vertical_align == "center" then
|
||||||
local content_size = self[1]:getSize()
|
local content_size = self[1]:getSize()
|
||||||
self[1]:paintTo(bb, x, y + math.floor((self.dimen.h - content_size.h)/2))
|
self[1]:paintTo(bb, x, y + math.floor((self.dimen.h - content_size.h)/2))
|
||||||
else
|
else
|
||||||
self[1]:paintTo(bb, x, y)
|
self[1]:paintTo(bb, x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -69,28 +69,28 @@ the following handler handles keypresses and checks if they lead to a command.
|
|||||||
if this is the case, we retransmit another event within ourselves
|
if this is the case, we retransmit another event within ourselves
|
||||||
--]]
|
--]]
|
||||||
function InputContainer:onKeyPress(key)
|
function InputContainer:onKeyPress(key)
|
||||||
for name, seq in pairs(self.key_events) do
|
for name, seq in pairs(self.key_events) do
|
||||||
if not seq.is_inactive then
|
if not seq.is_inactive then
|
||||||
for _, oneseq in ipairs(seq) do
|
for _, oneseq in ipairs(seq) do
|
||||||
if key:match(oneseq) then
|
if key:match(oneseq) then
|
||||||
local eventname = seq.event or name
|
local eventname = seq.event or name
|
||||||
return self:handleEvent(Event:new(eventname, seq.args, key))
|
return self:handleEvent(Event:new(eventname, seq.args, key))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputContainer:onGesture(ev)
|
function InputContainer:onGesture(ev)
|
||||||
for name, gsseq in pairs(self.ges_events) do
|
for name, gsseq in pairs(self.ges_events) do
|
||||||
for _, gs_range in ipairs(gsseq) do
|
for _, gs_range in ipairs(gsseq) do
|
||||||
--DEBUG("gs_range", gs_range)
|
--DEBUG("gs_range", gs_range)
|
||||||
if gs_range:match(ev) then
|
if gs_range:match(ev) then
|
||||||
local eventname = gsseq.event or name
|
local eventname = gsseq.event or name
|
||||||
return self:handleEvent(Event:new(eventname, gsseq.args, ev))
|
return self:handleEvent(Event:new(eventname, gsseq.args, ev))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return InputContainer
|
return InputContainer
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ LeftContainer aligns its content (1 widget) at the left of its own dimensions
|
|||||||
local LeftContainer = WidgetContainer:new()
|
local LeftContainer = WidgetContainer:new()
|
||||||
|
|
||||||
function LeftContainer:paintTo(bb, x, y)
|
function LeftContainer:paintTo(bb, x, y)
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
||||||
-- throw error? paint to scrap buffer and blit partially?
|
-- throw error? paint to scrap buffer and blit partially?
|
||||||
-- for now, we ignore this
|
-- for now, we ignore this
|
||||||
end
|
end
|
||||||
self[1]:paintTo(bb, x , y + math.floor((self.dimen.h - contentSize.h)/2))
|
self[1]:paintTo(bb, x , y + math.floor((self.dimen.h - contentSize.h)/2))
|
||||||
end
|
end
|
||||||
|
|
||||||
return LeftContainer
|
return LeftContainer
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ RightContainer aligns its content (1 widget) at the right of its own dimensions
|
|||||||
local RightContainer = WidgetContainer:new()
|
local RightContainer = WidgetContainer:new()
|
||||||
|
|
||||||
function RightContainer:paintTo(bb, x, y)
|
function RightContainer:paintTo(bb, x, y)
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
||||||
-- throw error? paint to scrap buffer and blit partially?
|
-- throw error? paint to scrap buffer and blit partially?
|
||||||
-- for now, we ignore this
|
-- for now, we ignore this
|
||||||
end
|
end
|
||||||
self[1]:paintTo(bb,
|
self[1]:paintTo(bb,
|
||||||
x + (self.dimen.w - contentSize.w),
|
x + (self.dimen.w - contentSize.w),
|
||||||
y + math.floor((self.dimen.h - contentSize.h)/2))
|
y + math.floor((self.dimen.h - contentSize.h)/2))
|
||||||
end
|
end
|
||||||
|
|
||||||
return RightContainer
|
return RightContainer
|
||||||
|
|||||||
@@ -7,36 +7,36 @@ a line under its child node
|
|||||||
--]]
|
--]]
|
||||||
|
|
||||||
local UnderlineContainer = WidgetContainer:new{
|
local UnderlineContainer = WidgetContainer:new{
|
||||||
linesize = 2,
|
linesize = 2,
|
||||||
padding = 1,
|
padding = 1,
|
||||||
color = 0,
|
color = 0,
|
||||||
vertical_align = "top",
|
vertical_align = "top",
|
||||||
}
|
}
|
||||||
|
|
||||||
function UnderlineContainer:getSize()
|
function UnderlineContainer:getSize()
|
||||||
return self:getContentSize()
|
return self:getContentSize()
|
||||||
end
|
end
|
||||||
|
|
||||||
function UnderlineContainer:getContentSize()
|
function UnderlineContainer:getContentSize()
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
w = contentSize.w,
|
w = contentSize.w,
|
||||||
h = contentSize.h + self.linesize + self.padding
|
h = contentSize.h + self.linesize + self.padding
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function UnderlineContainer:paintTo(bb, x, y)
|
function UnderlineContainer:paintTo(bb, x, y)
|
||||||
local container_size = self:getSize()
|
local container_size = self:getSize()
|
||||||
local content_size = self:getContentSize()
|
local content_size = self:getContentSize()
|
||||||
local p_y = y
|
local p_y = y
|
||||||
if self.vertical_align == "center" then
|
if self.vertical_align == "center" then
|
||||||
p_y = math.floor((container_size.h - content_size.h) / 2) + y
|
p_y = math.floor((container_size.h - content_size.h) / 2) + y
|
||||||
elseif self.vertical_align == "bottom" then
|
elseif self.vertical_align == "bottom" then
|
||||||
p_y = (container_size.h - content_size.h) + y
|
p_y = (container_size.h - content_size.h) + y
|
||||||
end
|
end
|
||||||
self[1]:paintTo(bb, x, p_y)
|
self[1]:paintTo(bb, x, p_y)
|
||||||
bb:paintRect(x, y + container_size.h - self.linesize,
|
bb:paintRect(x, y + container_size.h - self.linesize,
|
||||||
container_size.w, self.linesize, self.color)
|
container_size.w, self.linesize, self.color)
|
||||||
end
|
end
|
||||||
|
|
||||||
return UnderlineContainer
|
return UnderlineContainer
|
||||||
|
|||||||
@@ -7,83 +7,83 @@ WidgetContainer is a container for another Widget
|
|||||||
local WidgetContainer = Widget:new()
|
local WidgetContainer = Widget:new()
|
||||||
|
|
||||||
function WidgetContainer:init()
|
function WidgetContainer:init()
|
||||||
if not self.dimen then
|
if not self.dimen then
|
||||||
self.dimen = Geom:new{}
|
self.dimen = Geom:new{}
|
||||||
end
|
end
|
||||||
if not self.dimen.w then
|
if not self.dimen.w then
|
||||||
self.dimen.w = self[1].getSize().w
|
self.dimen.w = self[1].getSize().w
|
||||||
end
|
end
|
||||||
if not self.dimen.h then
|
if not self.dimen.h then
|
||||||
self.dimen.h = self[1].getSize().h
|
self.dimen.h = self[1].getSize().h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function WidgetContainer:getSize()
|
function WidgetContainer:getSize()
|
||||||
if self.dimen then
|
if self.dimen then
|
||||||
-- fixed size
|
-- fixed size
|
||||||
return self.dimen
|
return self.dimen
|
||||||
elseif self[1] then
|
elseif self[1] then
|
||||||
-- return size of first child widget
|
-- return size of first child widget
|
||||||
return self[1]:getSize()
|
return self[1]:getSize()
|
||||||
else
|
else
|
||||||
return Geom:new{ w = 0, h = 0 }
|
return Geom:new{ w = 0, h = 0 }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
delete all child widgets
|
delete all child widgets
|
||||||
--]]
|
--]]
|
||||||
function WidgetContainer:clear()
|
function WidgetContainer:clear()
|
||||||
while table.remove(self) do end
|
while table.remove(self) do end
|
||||||
end
|
end
|
||||||
|
|
||||||
function WidgetContainer:paintTo(bb, x, y)
|
function WidgetContainer:paintTo(bb, x, y)
|
||||||
-- default to pass request to first child widget
|
-- default to pass request to first child widget
|
||||||
if self[1] then
|
if self[1] then
|
||||||
x = x + (self.dimen.x or 0)
|
x = x + (self.dimen.x or 0)
|
||||||
y = y + (self.dimen.y or 0)
|
y = y + (self.dimen.y or 0)
|
||||||
if self.align == "top" then
|
if self.align == "top" then
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
self[1]:paintTo(bb,
|
self[1]:paintTo(bb,
|
||||||
x + math.floor((self.dimen.w - contentSize.w)/2), y)
|
x + math.floor((self.dimen.w - contentSize.w)/2), y)
|
||||||
elseif self.align == "bottom" then
|
elseif self.align == "bottom" then
|
||||||
local contentSize = self[1]:getSize()
|
local contentSize = self[1]:getSize()
|
||||||
self[1]:paintTo(bb,
|
self[1]:paintTo(bb,
|
||||||
x + math.floor((self.dimen.w - contentSize.w)/2),
|
x + math.floor((self.dimen.w - contentSize.w)/2),
|
||||||
y + (self.dimen.h - contentSize.h))
|
y + (self.dimen.h - contentSize.h))
|
||||||
else
|
else
|
||||||
return self[1]:paintTo(bb, x, y)
|
return self[1]:paintTo(bb, x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function WidgetContainer:propagateEvent(event)
|
function WidgetContainer:propagateEvent(event)
|
||||||
-- propagate to children
|
-- propagate to children
|
||||||
for _, widget in ipairs(self) do
|
for _, widget in ipairs(self) do
|
||||||
if widget:handleEvent(event) then
|
if widget:handleEvent(event) then
|
||||||
-- stop propagating when an event handler returns true
|
-- stop propagating when an event handler returns true
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Containers will pass events to children or react on them themselves
|
Containers will pass events to children or react on them themselves
|
||||||
--]]
|
--]]
|
||||||
function WidgetContainer:handleEvent(event)
|
function WidgetContainer:handleEvent(event)
|
||||||
if not self:propagateEvent(event) then
|
if not self:propagateEvent(event) then
|
||||||
-- call our own standard event handler
|
-- call our own standard event handler
|
||||||
return Widget.handleEvent(self, event)
|
return Widget.handleEvent(self, event)
|
||||||
else
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function WidgetContainer:free()
|
function WidgetContainer:free()
|
||||||
for _, widget in ipairs(self) do
|
for _, widget in ipairs(self) do
|
||||||
if widget.free then widget:free() end
|
if widget.free then widget:free() end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return WidgetContainer
|
return WidgetContainer
|
||||||
|
|||||||
@@ -24,280 +24,280 @@ local _ = require("gettext")
|
|||||||
Display quick lookup word definition
|
Display quick lookup word definition
|
||||||
]]
|
]]
|
||||||
local DictQuickLookup = InputContainer:new{
|
local DictQuickLookup = InputContainer:new{
|
||||||
results = nil,
|
results = nil,
|
||||||
lookupword = nil,
|
lookupword = nil,
|
||||||
dictionary = nil,
|
dictionary = nil,
|
||||||
definition = nil,
|
definition = nil,
|
||||||
dict_index = 1,
|
dict_index = 1,
|
||||||
title_face = Font:getFace("tfont", 22),
|
title_face = Font:getFace("tfont", 22),
|
||||||
word_face = Font:getFace("tfont", 22),
|
word_face = Font:getFace("tfont", 22),
|
||||||
content_face = Font:getFace("cfont", DDICT_FONT_SIZE),
|
content_face = Font:getFace("cfont", DDICT_FONT_SIZE),
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
|
|
||||||
title_padding = Screen:scaleByDPI(5),
|
title_padding = Screen:scaleByDPI(5),
|
||||||
title_margin = Screen:scaleByDPI(2),
|
title_margin = Screen:scaleByDPI(2),
|
||||||
word_padding = Screen:scaleByDPI(2),
|
word_padding = Screen:scaleByDPI(2),
|
||||||
word_margin = Screen:scaleByDPI(2),
|
word_margin = Screen:scaleByDPI(2),
|
||||||
definition_padding = Screen:scaleByDPI(2),
|
definition_padding = Screen:scaleByDPI(2),
|
||||||
definition_margin = Screen:scaleByDPI(2),
|
definition_margin = Screen:scaleByDPI(2),
|
||||||
button_padding = Screen:scaleByDPI(14),
|
button_padding = Screen:scaleByDPI(14),
|
||||||
}
|
}
|
||||||
|
|
||||||
function DictQuickLookup:init()
|
function DictQuickLookup:init()
|
||||||
self:changeToDefaultDict()
|
self:changeToDefaultDict()
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapCloseDict = {
|
TapCloseDict = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Swipe = {
|
Swipe = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
table.insert(self.dict_bar,
|
table.insert(self.dict_bar,
|
||||||
CloseButton:new{
|
CloseButton:new{
|
||||||
window = self,
|
window = self,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:update()
|
function DictQuickLookup:update()
|
||||||
-- dictionary title
|
-- dictionary title
|
||||||
self.dict_title = FrameContainer:new{
|
self.dict_title = FrameContainer:new{
|
||||||
padding = self.title_padding,
|
padding = self.title_padding,
|
||||||
margin = self.title_margin,
|
margin = self.title_margin,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
TextWidget:new{
|
TextWidget:new{
|
||||||
text = self.dictionary,
|
text = self.dictionary,
|
||||||
face = self.title_face,
|
face = self.title_face,
|
||||||
bold = true,
|
bold = true,
|
||||||
width = self.width - self.button_padding,
|
width = self.width - self.button_padding,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-- lookup word
|
-- lookup word
|
||||||
local lookup_word = FrameContainer:new{
|
local lookup_word = FrameContainer:new{
|
||||||
padding = self.word_padding,
|
padding = self.word_padding,
|
||||||
margin = self.word_margin,
|
margin = self.word_margin,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
TextBoxWidget:new{
|
TextBoxWidget:new{
|
||||||
text = self.lookupword,
|
text = self.lookupword,
|
||||||
face = self.word_face,
|
face = self.word_face,
|
||||||
bold = true,
|
bold = true,
|
||||||
width = self.width,
|
width = self.width,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
-- word definition
|
-- word definition
|
||||||
local definition = FrameContainer:new{
|
local definition = FrameContainer:new{
|
||||||
padding = self.definition_padding,
|
padding = self.definition_padding,
|
||||||
margin = self.definition_margin,
|
margin = self.definition_margin,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
ScrollTextWidget:new{
|
ScrollTextWidget:new{
|
||||||
text = self.definition,
|
text = self.definition,
|
||||||
face = self.content_face,
|
face = self.content_face,
|
||||||
width = self.width,
|
width = self.width,
|
||||||
height = self.height*0.7,
|
height = self.height*0.7,
|
||||||
dialog = self,
|
dialog = self,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
local button_table = ButtonTable:new{
|
local button_table = ButtonTable:new{
|
||||||
width = math.max(self.width, definition:getSize().w),
|
width = math.max(self.width, definition:getSize().w),
|
||||||
button_font_face = "cfont",
|
button_font_face = "cfont",
|
||||||
button_font_size = 20,
|
button_font_size = 20,
|
||||||
buttons = {
|
buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("<<"),
|
text = _("<<"),
|
||||||
enabled = self:isPrevDictAvaiable(),
|
enabled = self:isPrevDictAvaiable(),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:changeToPrevDict()
|
self:changeToPrevDict()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _(">>"),
|
text = _(">>"),
|
||||||
enabled = self:isNextDictAvaiable(),
|
enabled = self:isNextDictAvaiable(),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:changeToNextDict()
|
self:changeToNextDict()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Highlight"),
|
text = _("Highlight"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self.ui:handleEvent(Event:new("Highlight"))
|
self.ui:handleEvent(Event:new("Highlight"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Add Note"),
|
text = _("Add Note"),
|
||||||
enabled = false,
|
enabled = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
self.ui:handleEvent(Event:new("AddNote"))
|
self.ui:handleEvent(Event:new("AddNote"))
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zero_sep = true,
|
zero_sep = true,
|
||||||
}
|
}
|
||||||
local title_bar = LineWidget:new{
|
local title_bar = LineWidget:new{
|
||||||
--background = 8,
|
--background = 8,
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = button_table:getSize().w + self.button_padding,
|
w = button_table:getSize().w + self.button_padding,
|
||||||
h = Screen:scaleByDPI(2),
|
h = Screen:scaleByDPI(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dict_bar = OverlapGroup:new{
|
self.dict_bar = OverlapGroup:new{
|
||||||
dimen = {w = button_table:getSize().w, h = self.dict_title:getSize().h},
|
dimen = {w = button_table:getSize().w, h = self.dict_title:getSize().h},
|
||||||
self.dict_title,
|
self.dict_title,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dict_frame = FrameContainer:new{
|
self.dict_frame = FrameContainer:new{
|
||||||
radius = 8,
|
radius = 8,
|
||||||
bordersize = 3,
|
bordersize = 3,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
background = 0,
|
background = 0,
|
||||||
VerticalGroup:new{
|
VerticalGroup:new{
|
||||||
align = "left",
|
align = "left",
|
||||||
self.dict_bar,
|
self.dict_bar,
|
||||||
title_bar,
|
title_bar,
|
||||||
-- word
|
-- word
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = title_bar:getSize().w,
|
w = title_bar:getSize().w,
|
||||||
h = lookup_word:getSize().h,
|
h = lookup_word:getSize().h,
|
||||||
},
|
},
|
||||||
lookup_word,
|
lookup_word,
|
||||||
},
|
},
|
||||||
-- definition
|
-- definition
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = title_bar:getSize().w,
|
w = title_bar:getSize().w,
|
||||||
h = definition:getSize().h,
|
h = definition:getSize().h,
|
||||||
},
|
},
|
||||||
definition,
|
definition,
|
||||||
},
|
},
|
||||||
-- buttons
|
-- buttons
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = title_bar:getSize().w,
|
w = title_bar:getSize().w,
|
||||||
h = button_table:getSize().h,
|
h = button_table:getSize().h,
|
||||||
},
|
},
|
||||||
button_table,
|
button_table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self[1] = WidgetContainer:new{
|
self[1] = WidgetContainer:new{
|
||||||
align = self.align,
|
align = self.align,
|
||||||
dimen = self.region:copy(),
|
dimen = self.region:copy(),
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
padding = Screen:scaleByDPI(5),
|
padding = Screen:scaleByDPI(5),
|
||||||
self.dict_frame,
|
self.dict_frame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
UIManager.full_refresh = true
|
UIManager.full_refresh = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:isPrevDictAvaiable()
|
function DictQuickLookup:isPrevDictAvaiable()
|
||||||
return self.dict_index > 1
|
return self.dict_index > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:isNextDictAvaiable()
|
function DictQuickLookup:isNextDictAvaiable()
|
||||||
return self.dict_index < #self.results
|
return self.dict_index < #self.results
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:changeToPrevDict()
|
function DictQuickLookup:changeToPrevDict()
|
||||||
self:changeDictionary(self.dict_index - 1)
|
self:changeDictionary(self.dict_index - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:changeToNextDict()
|
function DictQuickLookup:changeToNextDict()
|
||||||
self:changeDictionary(self.dict_index + 1)
|
self:changeDictionary(self.dict_index + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:changeDictionary(index)
|
function DictQuickLookup:changeDictionary(index)
|
||||||
self.dict_index = index
|
self.dict_index = index
|
||||||
self.dictionary = self.results[index].dict
|
self.dictionary = self.results[index].dict
|
||||||
self.lookupword = self.results[index].word
|
self.lookupword = self.results[index].word
|
||||||
self.definition = self.results[index].definition
|
self.definition = self.results[index].definition
|
||||||
|
|
||||||
local orig_dimen = self.dict_frame and self.dict_frame.dimen or Geom:new{}
|
local orig_dimen = self.dict_frame and self.dict_frame.dimen or Geom:new{}
|
||||||
self:update()
|
self:update()
|
||||||
|
|
||||||
UIManager.update_region_func = function()
|
UIManager.update_region_func = function()
|
||||||
local update_region = self.dict_frame.dimen:combine(orig_dimen)
|
local update_region = self.dict_frame.dimen:combine(orig_dimen)
|
||||||
DEBUG("update region", update_region)
|
DEBUG("update region", update_region)
|
||||||
return update_region
|
return update_region
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:changeToDefaultDict()
|
function DictQuickLookup:changeToDefaultDict()
|
||||||
if self.dictionary then
|
if self.dictionary then
|
||||||
-- dictionaries that have definition of the first word(accurate word)
|
-- dictionaries that have definition of the first word(accurate word)
|
||||||
-- excluding Fuzzy queries.
|
-- excluding Fuzzy queries.
|
||||||
local n_accurate_dicts = nil
|
local n_accurate_dicts = nil
|
||||||
local default_word = self.results[1].word
|
local default_word = self.results[1].word
|
||||||
for i=1, #self.results do
|
for i=1, #self.results do
|
||||||
if self.results[i].word == default_word then
|
if self.results[i].word == default_word then
|
||||||
n_accurate_dicts = i
|
n_accurate_dicts = i
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- change to dictionary specified by self.dictionary
|
-- change to dictionary specified by self.dictionary
|
||||||
for i=1, n_accurate_dicts do
|
for i=1, n_accurate_dicts do
|
||||||
if self.results[i].dict == self.dictionary then
|
if self.results[i].dict == self.dictionary then
|
||||||
self:changeDictionary(i)
|
self:changeDictionary(i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
-- cannot find definition in default dictionary
|
-- cannot find definition in default dictionary
|
||||||
if i == n_accurate_dicts then
|
if i == n_accurate_dicts then
|
||||||
self:changeDictionary(1)
|
self:changeDictionary(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:changeDictionary(1)
|
self:changeDictionary(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:onAnyKeyPressed()
|
function DictQuickLookup:onAnyKeyPressed()
|
||||||
-- triggered by our defined key events
|
-- triggered by our defined key events
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:onTapCloseDict(arg, ges_ev)
|
function DictQuickLookup:onTapCloseDict(arg, ges_ev)
|
||||||
if ges_ev.pos:notIntersectWith(self.dict_frame.dimen) then
|
if ges_ev.pos:notIntersectWith(self.dict_frame.dimen) then
|
||||||
self:onClose()
|
self:onClose()
|
||||||
return true
|
return true
|
||||||
elseif not ges_ev.pos:notIntersectWith(self.dict_title.dimen) then
|
elseif not ges_ev.pos:notIntersectWith(self.dict_title.dimen) then
|
||||||
self.ui:handleEvent(Event:new("UpdateDefaultDict", self.dictionary))
|
self.ui:handleEvent(Event:new("UpdateDefaultDict", self.dictionary))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:onClose()
|
function DictQuickLookup:onClose()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
self.highlight:handleEvent(Event:new("Tap"))
|
self.highlight:handleEvent(Event:new("Tap"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return DictQuickLookup
|
return DictQuickLookup
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ will call a method "onEventName" for an event with name
|
|||||||
local EventListener = {}
|
local EventListener = {}
|
||||||
|
|
||||||
function EventListener:new(o)
|
function EventListener:new(o)
|
||||||
local o = o or {}
|
local o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
if o.init then o:init() end
|
if o.init then o:init() end
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function EventListener:handleEvent(event)
|
function EventListener:handleEvent(event)
|
||||||
if self[event.handler] then
|
if self[event.handler] then
|
||||||
return self[event.handler](self, unpack(event.args))
|
return self[event.handler](self, unpack(event.args))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return EventListener
|
return EventListener
|
||||||
|
|||||||
@@ -5,97 +5,97 @@ local DEBUG = require("dbg")
|
|||||||
-- lfs
|
-- lfs
|
||||||
|
|
||||||
local FileChooser = Menu:extend{
|
local FileChooser = Menu:extend{
|
||||||
height = Screen:getHeight(),
|
height = Screen:getHeight(),
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
no_title = true,
|
no_title = true,
|
||||||
path = lfs.currentdir(),
|
path = lfs.currentdir(),
|
||||||
parent = nil,
|
parent = nil,
|
||||||
show_hidden = nil,
|
show_hidden = nil,
|
||||||
show_filesize = DSHOWFILESIZE,
|
show_filesize = DSHOWFILESIZE,
|
||||||
filter = function(filename) return true end,
|
filter = function(filename) return true end,
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileChooser:init()
|
function FileChooser:init()
|
||||||
self.item_table = self:genItemTableFromPath(self.path)
|
self.item_table = self:genItemTableFromPath(self.path)
|
||||||
Menu.init(self) -- call parent's init()
|
Menu.init(self) -- call parent's init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:genItemTableFromPath(path)
|
function FileChooser:genItemTableFromPath(path)
|
||||||
local dirs = {}
|
local dirs = {}
|
||||||
local files = {}
|
local files = {}
|
||||||
|
|
||||||
for f in lfs.dir(self.path) do
|
for f in lfs.dir(self.path) do
|
||||||
if self.show_hidden or not string.match(f, "^%.[^.]") then
|
if self.show_hidden or not string.match(f, "^%.[^.]") then
|
||||||
local filename = self.path.."/"..f
|
local filename = self.path.."/"..f
|
||||||
local filemode = lfs.attributes(filename, "mode")
|
local filemode = lfs.attributes(filename, "mode")
|
||||||
if filemode == "directory" and f ~= "." and f~=".." then
|
if filemode == "directory" and f ~= "." and f~=".." then
|
||||||
if self.dir_filter(filename) then
|
if self.dir_filter(filename) then
|
||||||
table.insert(dirs, f)
|
table.insert(dirs, f)
|
||||||
end
|
end
|
||||||
elseif filemode == "file" then
|
elseif filemode == "file" then
|
||||||
if self.file_filter(filename) then
|
if self.file_filter(filename) then
|
||||||
table.insert(files, f)
|
table.insert(files, f)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(dirs)
|
table.sort(dirs)
|
||||||
if path ~= "/" then table.insert(dirs, 1, "..") end
|
if path ~= "/" then table.insert(dirs, 1, "..") end
|
||||||
table.sort(files)
|
table.sort(files)
|
||||||
|
|
||||||
local item_table = {}
|
local item_table = {}
|
||||||
for _, dir in ipairs(dirs) do
|
for _, dir in ipairs(dirs) do
|
||||||
table.insert(item_table, { text = dir.."/", path = self.path.."/"..dir })
|
table.insert(item_table, { text = dir.."/", path = self.path.."/"..dir })
|
||||||
end
|
end
|
||||||
for _, file in ipairs(files) do
|
for _, file in ipairs(files) do
|
||||||
local full_path = self.path.."/"..file
|
local full_path = self.path.."/"..file
|
||||||
if self.show_filesize then
|
if self.show_filesize then
|
||||||
local sstr = string.format("%4.1fM",lfs.attributes(full_path, "size")/1024/1024)
|
local sstr = string.format("%4.1fM",lfs.attributes(full_path, "size")/1024/1024)
|
||||||
table.insert(item_table, { text = file, mandatory = sstr, path = full_path })
|
table.insert(item_table, { text = file, mandatory = sstr, path = full_path })
|
||||||
else
|
else
|
||||||
table.insert(item_table, { text = file, path = full_path })
|
table.insert(item_table, { text = file, path = full_path })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return item_table
|
return item_table
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:changeToPath(path)
|
function FileChooser:changeToPath(path)
|
||||||
path = util.realpath(path)
|
path = util.realpath(path)
|
||||||
self.path = path
|
self.path = path
|
||||||
self:refreshPath()
|
self:refreshPath()
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:refreshPath()
|
function FileChooser:refreshPath()
|
||||||
self:swithItemTable(nil, self:genItemTableFromPath(self.path))
|
self:swithItemTable(nil, self:genItemTableFromPath(self.path))
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:toggleHiddenFiles()
|
function FileChooser:toggleHiddenFiles()
|
||||||
self.show_hidden = not self.show_hidden
|
self.show_hidden = not self.show_hidden
|
||||||
self:swithItemTable(nil, self:genItemTableFromPath(self.path))
|
self:swithItemTable(nil, self:genItemTableFromPath(self.path))
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:onMenuSelect(item)
|
function FileChooser:onMenuSelect(item)
|
||||||
if lfs.attributes(item.path, "mode") == "directory" then
|
if lfs.attributes(item.path, "mode") == "directory" then
|
||||||
self:changeToPath(item.path)
|
self:changeToPath(item.path)
|
||||||
else
|
else
|
||||||
self:onFileSelect(item.path)
|
self:onFileSelect(item.path)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:onMenuHold(item)
|
function FileChooser:onMenuHold(item)
|
||||||
self:onFileHold(item.path)
|
self:onFileHold(item.path)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:onFileSelect(file)
|
function FileChooser:onFileSelect(file)
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileChooser:onFileHold(file)
|
function FileChooser:onFileHold(file)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return FileChooser
|
return FileChooser
|
||||||
|
|||||||
@@ -9,21 +9,21 @@ FixedTextWidget
|
|||||||
local FixedTextWidget = TextWidget:new{}
|
local FixedTextWidget = TextWidget:new{}
|
||||||
|
|
||||||
function FixedTextWidget:getSize()
|
function FixedTextWidget:getSize()
|
||||||
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
|
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
|
||||||
if not tsize then
|
if not tsize then
|
||||||
return Geom:new{}
|
return Geom:new{}
|
||||||
end
|
end
|
||||||
self._length = tsize.x
|
self._length = tsize.x
|
||||||
self._height = self.face.size
|
self._height = self.face.size
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
w = self._length,
|
w = self._length,
|
||||||
h = self._height,
|
h = self._height,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function FixedTextWidget:paintTo(bb, x, y)
|
function FixedTextWidget:paintTo(bb, x, y)
|
||||||
RenderText:renderUtf8Text(bb, x, y+self._height, self.face, self.text, true, self.bold,
|
RenderText:renderUtf8Text(bb, x, y+self._height, self.face, self.text, true, self.bold,
|
||||||
self.bgcolor, self.fgcolor)
|
self.bgcolor, self.fgcolor)
|
||||||
end
|
end
|
||||||
|
|
||||||
return FixedTextWidget
|
return FixedTextWidget
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ Wrapper Widget that manages focus for a whole dialog
|
|||||||
supports a 2D model of active elements
|
supports a 2D model of active elements
|
||||||
|
|
||||||
e.g.:
|
e.g.:
|
||||||
layout = {
|
layout = {
|
||||||
{ textinput, textinput },
|
{ textinput, textinput },
|
||||||
{ okbutton, cancelbutton }
|
{ okbutton, cancelbutton }
|
||||||
}
|
}
|
||||||
|
|
||||||
this is a dialog with 2 rows. in the top row, there is the
|
this is a dialog with 2 rows. in the top row, there is the
|
||||||
single (!) widget <textinput>. when the focus is in this
|
single (!) widget <textinput>. when the focus is in this
|
||||||
@@ -26,76 +26,76 @@ but notice that this does _not_ do the layout for you,
|
|||||||
it rather defines an abstract layout.
|
it rather defines an abstract layout.
|
||||||
]]
|
]]
|
||||||
local FocusManager = InputContainer:new{
|
local FocusManager = InputContainer:new{
|
||||||
selected = nil, -- defaults to x=1, y=1
|
selected = nil, -- defaults to x=1, y=1
|
||||||
layout = nil, -- mandatory
|
layout = nil, -- mandatory
|
||||||
movement_allowed = { x = true, y = true }
|
movement_allowed = { x = true, y = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
function FocusManager:init()
|
function FocusManager:init()
|
||||||
self.selected = { x = 1, y = 1 }
|
self.selected = { x = 1, y = 1 }
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
-- these will all generate the same event, just with different arguments
|
-- these will all generate the same event, just with different arguments
|
||||||
FocusUp = { {"Up"}, doc = "move focus up", event = "FocusMove", args = {0, -1} },
|
FocusUp = { {"Up"}, doc = "move focus up", event = "FocusMove", args = {0, -1} },
|
||||||
FocusDown = { {"Down"}, doc = "move focus down", event = "FocusMove", args = {0, 1} },
|
FocusDown = { {"Down"}, doc = "move focus down", event = "FocusMove", args = {0, 1} },
|
||||||
FocusLeft = { {"Left"}, doc = "move focus left", event = "FocusMove", args = {-1, 0} },
|
FocusLeft = { {"Left"}, doc = "move focus left", event = "FocusMove", args = {-1, 0} },
|
||||||
FocusRight = { {"Right"}, doc = "move focus right", event = "FocusMove", args = {1, 0} },
|
FocusRight = { {"Right"}, doc = "move focus right", event = "FocusMove", args = {1, 0} },
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function FocusManager:onFocusMove(args)
|
function FocusManager:onFocusMove(args)
|
||||||
local dx, dy = unpack(args)
|
local dx, dy = unpack(args)
|
||||||
|
|
||||||
if (dx ~= 0 and not self.movement_allowed.x)
|
if (dx ~= 0 and not self.movement_allowed.x)
|
||||||
or (dy ~= 0 and not self.movement_allowed.y) then
|
or (dy ~= 0 and not self.movement_allowed.y) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.layout or not self.layout[self.selected.y] or not self.layout[self.selected.y][self.selected.x] then
|
if not self.layout or not self.layout[self.selected.y] or not self.layout[self.selected.y][self.selected.x] then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
local current_item = self.layout[self.selected.y][self.selected.x]
|
local current_item = self.layout[self.selected.y][self.selected.x]
|
||||||
while true do
|
while true do
|
||||||
if self.selected.x + dx > #self.layout[self.selected.y]
|
if self.selected.x + dx > #self.layout[self.selected.y]
|
||||||
or self.selected.x + dx < 1 then
|
or self.selected.x + dx < 1 then
|
||||||
break -- abort when we run into horizontal borders
|
break -- abort when we run into horizontal borders
|
||||||
end
|
end
|
||||||
|
|
||||||
-- move cyclic in vertical direction
|
-- move cyclic in vertical direction
|
||||||
if self.selected.y + dy > #self.layout then
|
if self.selected.y + dy > #self.layout then
|
||||||
if not self:onWrapLast() then
|
if not self:onWrapLast() then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
elseif self.selected.y + dy < 1 then
|
elseif self.selected.y + dy < 1 then
|
||||||
if not self:onWrapFirst() then
|
if not self:onWrapFirst() then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.selected.y = self.selected.y + dy
|
self.selected.y = self.selected.y + dy
|
||||||
end
|
end
|
||||||
self.selected.x = self.selected.x + dx
|
self.selected.x = self.selected.x + dx
|
||||||
|
|
||||||
if self.layout[self.selected.y][self.selected.x] ~= current_item
|
if self.layout[self.selected.y][self.selected.x] ~= current_item
|
||||||
or not self.layout[self.selected.y][self.selected.x].is_inactive then
|
or not self.layout[self.selected.y][self.selected.x].is_inactive then
|
||||||
-- we found a different object to focus
|
-- we found a different object to focus
|
||||||
current_item:handleEvent(Event:new("Unfocus"))
|
current_item:handleEvent(Event:new("Unfocus"))
|
||||||
self.layout[self.selected.y][self.selected.x]:handleEvent(Event:new("Focus"))
|
self.layout[self.selected.y][self.selected.x]:handleEvent(Event:new("Focus"))
|
||||||
-- trigger a repaint (we need to be the registered widget!)
|
-- trigger a repaint (we need to be the registered widget!)
|
||||||
UIManager:setDirty(self, "partial")
|
UIManager:setDirty(self, "partial")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FocusManager:onWrapFirst()
|
function FocusManager:onWrapFirst()
|
||||||
self.selected.y = #self.layout
|
self.selected.y = #self.layout
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function FocusManager:onWrapLast()
|
function FocusManager:onWrapLast()
|
||||||
self.selected.y = 1
|
self.selected.y = 1
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return FocusManager
|
return FocusManager
|
||||||
|
|||||||
@@ -4,58 +4,58 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|||||||
A Layout widget that puts objects besides each others
|
A Layout widget that puts objects besides each others
|
||||||
--]]
|
--]]
|
||||||
local HorizontalGroup = WidgetContainer:new{
|
local HorizontalGroup = WidgetContainer:new{
|
||||||
align = "center",
|
align = "center",
|
||||||
_size = nil,
|
_size = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function HorizontalGroup:getSize()
|
function HorizontalGroup:getSize()
|
||||||
if not self._size then
|
if not self._size then
|
||||||
self._size = { w = 0, h = 0 }
|
self._size = { w = 0, h = 0 }
|
||||||
self._offsets = { }
|
self._offsets = { }
|
||||||
for i, widget in ipairs(self) do
|
for i, widget in ipairs(self) do
|
||||||
local w_size = widget:getSize()
|
local w_size = widget:getSize()
|
||||||
self._offsets[i] = {
|
self._offsets[i] = {
|
||||||
x = self._size.w,
|
x = self._size.w,
|
||||||
y = w_size.h
|
y = w_size.h
|
||||||
}
|
}
|
||||||
self._size.w = self._size.w + w_size.w
|
self._size.w = self._size.w + w_size.w
|
||||||
if w_size.h > self._size.h then
|
if w_size.h > self._size.h then
|
||||||
self._size.h = w_size.h
|
self._size.h = w_size.h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self._size
|
return self._size
|
||||||
end
|
end
|
||||||
|
|
||||||
function HorizontalGroup:paintTo(bb, x, y)
|
function HorizontalGroup:paintTo(bb, x, y)
|
||||||
local size = self:getSize()
|
local size = self:getSize()
|
||||||
|
|
||||||
for i, widget in ipairs(self) do
|
for i, widget in ipairs(self) do
|
||||||
if self.align == "center" then
|
if self.align == "center" then
|
||||||
widget:paintTo(bb,
|
widget:paintTo(bb,
|
||||||
x + self._offsets[i].x,
|
x + self._offsets[i].x,
|
||||||
y + math.floor((size.h - self._offsets[i].y) / 2))
|
y + math.floor((size.h - self._offsets[i].y) / 2))
|
||||||
elseif self.align == "top" then
|
elseif self.align == "top" then
|
||||||
widget:paintTo(bb, x + self._offsets[i].x, y)
|
widget:paintTo(bb, x + self._offsets[i].x, y)
|
||||||
elseif self.align == "bottom" then
|
elseif self.align == "bottom" then
|
||||||
widget:paintTo(bb, x + self._offsets[i].x, y + size.h - self._offsets[i].y)
|
widget:paintTo(bb, x + self._offsets[i].x, y + size.h - self._offsets[i].y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function HorizontalGroup:clear()
|
function HorizontalGroup:clear()
|
||||||
self:free()
|
self:free()
|
||||||
WidgetContainer.clear(self)
|
WidgetContainer.clear(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function HorizontalGroup:resetLayout()
|
function HorizontalGroup:resetLayout()
|
||||||
self._size = nil
|
self._size = nil
|
||||||
self._offsets = {}
|
self._offsets = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function HorizontalGroup:free()
|
function HorizontalGroup:free()
|
||||||
self:resetLayout()
|
self:resetLayout()
|
||||||
WidgetContainer.free(self)
|
WidgetContainer.free(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return HorizontalGroup
|
return HorizontalGroup
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ local Widget = require("ui/widget/widget")
|
|||||||
Dummy Widget that reserves horizontal space
|
Dummy Widget that reserves horizontal space
|
||||||
--]]
|
--]]
|
||||||
local HorizontalSpan = Widget:new{
|
local HorizontalSpan = Widget:new{
|
||||||
width = 0,
|
width = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function HorizontalSpan:getSize()
|
function HorizontalSpan:getSize()
|
||||||
return {w = self.width, h = 0}
|
return {w = self.width, h = 0}
|
||||||
end
|
end
|
||||||
|
|
||||||
return HorizontalSpan
|
return HorizontalSpan
|
||||||
|
|||||||
@@ -7,51 +7,51 @@ local UIManager = require("ui/uimanager")
|
|||||||
Button with a big icon image! Designed for touch device
|
Button with a big icon image! Designed for touch device
|
||||||
--]]
|
--]]
|
||||||
local IconButton = InputContainer:new{
|
local IconButton = InputContainer:new{
|
||||||
icon_file = "resources/info-confirm.png",
|
icon_file = "resources/info-confirm.png",
|
||||||
dimen = nil,
|
dimen = nil,
|
||||||
-- show_parent is used for UIManager:setDirty, so we can trigger repaint
|
-- show_parent is used for UIManager:setDirty, so we can trigger repaint
|
||||||
show_parent = nil,
|
show_parent = nil,
|
||||||
callback = function() end,
|
callback = function() end,
|
||||||
}
|
}
|
||||||
|
|
||||||
function IconButton:init()
|
function IconButton:init()
|
||||||
self.image = ImageWidget:new{
|
self.image = ImageWidget:new{
|
||||||
file = self.icon_file
|
file = self.icon_file
|
||||||
}
|
}
|
||||||
|
|
||||||
self.show_parent = self.show_parent or self
|
self.show_parent = self.show_parent or self
|
||||||
self.dimen = self.image:getSize()
|
self.dimen = self.image:getSize()
|
||||||
|
|
||||||
self:initGesListener()
|
self:initGesListener()
|
||||||
|
|
||||||
self[1] = self.image
|
self[1] = self.image
|
||||||
end
|
end
|
||||||
|
|
||||||
function IconButton:initGesListener()
|
function IconButton:initGesListener()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapClickButton = {
|
TapClickButton = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function IconButton:onTapClickButton()
|
function IconButton:onTapClickButton()
|
||||||
self.image.invert = true
|
self.image.invert = true
|
||||||
UIManager:setDirty(self.show_parent, "partial")
|
UIManager:setDirty(self.show_parent, "partial")
|
||||||
-- make sure button reacts before doing callback
|
-- make sure button reacts before doing callback
|
||||||
UIManager:scheduleIn(0.1, function()
|
UIManager:scheduleIn(0.1, function()
|
||||||
self.callback()
|
self.callback()
|
||||||
self.image.invert = false
|
self.image.invert = false
|
||||||
UIManager:setDirty(self.show_parent, "partial")
|
UIManager:setDirty(self.show_parent, "partial")
|
||||||
end)
|
end)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function IconButton:onSetDimensions(new_dimen)
|
function IconButton:onSetDimensions(new_dimen)
|
||||||
self.dimen = new_dimen
|
self.dimen = new_dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
return IconButton
|
return IconButton
|
||||||
|
|||||||
@@ -6,51 +6,51 @@ local Geom = require("ui/geometry")
|
|||||||
ImageWidget shows an image from a file
|
ImageWidget shows an image from a file
|
||||||
--]]
|
--]]
|
||||||
local ImageWidget = Widget:new{
|
local ImageWidget = Widget:new{
|
||||||
file = nil,
|
file = nil,
|
||||||
invert = nil,
|
invert = nil,
|
||||||
dim = nil,
|
dim = nil,
|
||||||
hide = nil,
|
hide = nil,
|
||||||
_bb = nil
|
_bb = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
function ImageWidget:_render()
|
function ImageWidget:_render()
|
||||||
local itype = string.lower(string.match(self.file, ".+%.([^.]+)") or "")
|
local itype = string.lower(string.match(self.file, ".+%.([^.]+)") or "")
|
||||||
if itype == "jpeg" or itype == "jpg" then
|
if itype == "jpeg" or itype == "jpg" then
|
||||||
self._bb = Image:fromJPEG(self.file)
|
self._bb = Image:fromJPEG(self.file)
|
||||||
elseif itype == "png" then
|
elseif itype == "png" then
|
||||||
self._bb = Image:fromPNG(self.file)
|
self._bb = Image:fromPNG(self.file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ImageWidget:getSize()
|
function ImageWidget:getSize()
|
||||||
if not self._bb then
|
if not self._bb then
|
||||||
self:_render()
|
self:_render()
|
||||||
end
|
end
|
||||||
return Geom:new{ w = self._bb:getWidth(), h = self._bb:getHeight() }
|
return Geom:new{ w = self._bb:getWidth(), h = self._bb:getHeight() }
|
||||||
end
|
end
|
||||||
|
|
||||||
function ImageWidget:paintTo(bb, x, y)
|
function ImageWidget:paintTo(bb, x, y)
|
||||||
local size = self:getSize()
|
local size = self:getSize()
|
||||||
self.dimen = Geom:new{
|
self.dimen = Geom:new{
|
||||||
x = x, y = y,
|
x = x, y = y,
|
||||||
w = size.w,
|
w = size.w,
|
||||||
h = size.h
|
h = size.h
|
||||||
}
|
}
|
||||||
if self.hide then return end
|
if self.hide then return end
|
||||||
bb:blitFrom(self._bb, x, y, 0, 0, size.w, size.h)
|
bb:blitFrom(self._bb, x, y, 0, 0, size.w, size.h)
|
||||||
if self.invert then
|
if self.invert then
|
||||||
bb:invertRect(x, y, size.w, size.h)
|
bb:invertRect(x, y, size.w, size.h)
|
||||||
end
|
end
|
||||||
if self.dim then
|
if self.dim then
|
||||||
bb:dimRect(x, y, size.w, size.h)
|
bb:dimRect(x, y, size.w, size.h)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ImageWidget:free()
|
function ImageWidget:free()
|
||||||
if self._bb then
|
if self._bb then
|
||||||
self._bb:free()
|
self._bb:free()
|
||||||
self._bb = nil
|
self._bb = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return ImageWidget
|
return ImageWidget
|
||||||
|
|||||||
@@ -20,68 +20,68 @@ Widget that displays an informational message
|
|||||||
it vanishes on key press or after a given timeout
|
it vanishes on key press or after a given timeout
|
||||||
]]
|
]]
|
||||||
local InfoMessage = InputContainer:new{
|
local InfoMessage = InputContainer:new{
|
||||||
face = Font:getFace("infofont", 25),
|
face = Font:getFace("infofont", 25),
|
||||||
text = "",
|
text = "",
|
||||||
timeout = nil, -- in seconds
|
timeout = nil, -- in seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
function InfoMessage:init()
|
function InfoMessage:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
AnyKeyPressed = { { Input.group.Any },
|
AnyKeyPressed = { { Input.group.Any },
|
||||||
seqtext = "any key", doc = _("close dialog") }
|
seqtext = "any key", doc = _("close dialog") }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events.TapClose = {
|
self.ges_events.TapClose = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
-- we construct the actual content here because self.text is only available now
|
-- we construct the actual content here because self.text is only available now
|
||||||
self[1] = CenterContainer:new{
|
self[1] = CenterContainer:new{
|
||||||
dimen = Screen:getSize(),
|
dimen = Screen:getSize(),
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
margin = 2,
|
margin = 2,
|
||||||
background = 0,
|
background = 0,
|
||||||
HorizontalGroup:new{
|
HorizontalGroup:new{
|
||||||
align = "center",
|
align = "center",
|
||||||
ImageWidget:new{
|
ImageWidget:new{
|
||||||
file = "resources/info-i.png"
|
file = "resources/info-i.png"
|
||||||
},
|
},
|
||||||
HorizontalSpan:new{ width = 10 },
|
HorizontalSpan:new{ width = 10 },
|
||||||
TextBoxWidget:new{
|
TextBoxWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = self.face
|
face = self.face
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function InfoMessage:onShow()
|
function InfoMessage:onShow()
|
||||||
-- triggered by the UIManager after we got successfully shown (not yet painted)
|
-- triggered by the UIManager after we got successfully shown (not yet painted)
|
||||||
if self.timeout then
|
if self.timeout then
|
||||||
UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end)
|
UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function InfoMessage:onAnyKeyPressed()
|
function InfoMessage:onAnyKeyPressed()
|
||||||
-- triggered by our defined key events
|
-- triggered by our defined key events
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function InfoMessage:onTapClose()
|
function InfoMessage:onTapClose()
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return InfoMessage
|
return InfoMessage
|
||||||
|
|||||||
@@ -12,112 +12,112 @@ local UIManager = require("ui/uimanager")
|
|||||||
local Screen = require("ui/screen")
|
local Screen = require("ui/screen")
|
||||||
|
|
||||||
local InputDialog = InputContainer:new{
|
local InputDialog = InputContainer:new{
|
||||||
title = "",
|
title = "",
|
||||||
input = "",
|
input = "",
|
||||||
input_hint = "",
|
input_hint = "",
|
||||||
buttons = nil,
|
buttons = nil,
|
||||||
input_type = nil,
|
input_type = nil,
|
||||||
enter_callback = nil,
|
enter_callback = nil,
|
||||||
|
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
|
|
||||||
title_face = Font:getFace("tfont", 22),
|
title_face = Font:getFace("tfont", 22),
|
||||||
input_face = Font:getFace("cfont", 20),
|
input_face = Font:getFace("cfont", 20),
|
||||||
|
|
||||||
title_padding = Screen:scaleByDPI(5),
|
title_padding = Screen:scaleByDPI(5),
|
||||||
title_margin = Screen:scaleByDPI(2),
|
title_margin = Screen:scaleByDPI(2),
|
||||||
input_padding = Screen:scaleByDPI(10),
|
input_padding = Screen:scaleByDPI(10),
|
||||||
input_margin = Screen:scaleByDPI(10),
|
input_margin = Screen:scaleByDPI(10),
|
||||||
button_padding = Screen:scaleByDPI(14),
|
button_padding = Screen:scaleByDPI(14),
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputDialog:init()
|
function InputDialog:init()
|
||||||
self.title = FrameContainer:new{
|
self.title = FrameContainer:new{
|
||||||
padding = self.title_padding,
|
padding = self.title_padding,
|
||||||
margin = self.title_margin,
|
margin = self.title_margin,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
TextWidget:new{
|
TextWidget:new{
|
||||||
text = self.title,
|
text = self.title,
|
||||||
face = self.title_face,
|
face = self.title_face,
|
||||||
width = self.width,
|
width = self.width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.input = InputText:new{
|
self.input = InputText:new{
|
||||||
text = self.input,
|
text = self.input,
|
||||||
hint = self.input_hint,
|
hint = self.input_hint,
|
||||||
face = self.input_face,
|
face = self.input_face,
|
||||||
width = self.width * 0.9,
|
width = self.width * 0.9,
|
||||||
input_type = self.input_type,
|
input_type = self.input_type,
|
||||||
enter_callback = self.enter_callback,
|
enter_callback = self.enter_callback,
|
||||||
scroll = false,
|
scroll = false,
|
||||||
parent = self,
|
parent = self,
|
||||||
}
|
}
|
||||||
local button_table = ButtonTable:new{
|
local button_table = ButtonTable:new{
|
||||||
width = self.width,
|
width = self.width,
|
||||||
button_font_face = "cfont",
|
button_font_face = "cfont",
|
||||||
button_font_size = 20,
|
button_font_size = 20,
|
||||||
buttons = self.buttons,
|
buttons = self.buttons,
|
||||||
zero_sep = true,
|
zero_sep = true,
|
||||||
}
|
}
|
||||||
local title_bar = LineWidget:new{
|
local title_bar = LineWidget:new{
|
||||||
--background = 8,
|
--background = 8,
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = button_table:getSize().w + self.button_padding,
|
w = button_table:getSize().w + self.button_padding,
|
||||||
h = Screen:scaleByDPI(2),
|
h = Screen:scaleByDPI(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dialog_frame = FrameContainer:new{
|
self.dialog_frame = FrameContainer:new{
|
||||||
radius = 8,
|
radius = 8,
|
||||||
bordersize = 3,
|
bordersize = 3,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
background = 0,
|
background = 0,
|
||||||
VerticalGroup:new{
|
VerticalGroup:new{
|
||||||
align = "left",
|
align = "left",
|
||||||
self.title,
|
self.title,
|
||||||
title_bar,
|
title_bar,
|
||||||
-- input
|
-- input
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = title_bar:getSize().w,
|
w = title_bar:getSize().w,
|
||||||
h = self.input:getSize().h,
|
h = self.input:getSize().h,
|
||||||
},
|
},
|
||||||
self.input,
|
self.input,
|
||||||
},
|
},
|
||||||
-- buttons
|
-- buttons
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = title_bar:getSize().w,
|
w = title_bar:getSize().w,
|
||||||
h = button_table:getSize().h,
|
h = button_table:getSize().h,
|
||||||
},
|
},
|
||||||
button_table,
|
button_table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self[1] = CenterContainer:new{
|
self[1] = CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight() - self.input:getKeyboardDimen().h,
|
h = Screen:getHeight() - self.input:getKeyboardDimen().h,
|
||||||
},
|
},
|
||||||
self.dialog_frame,
|
self.dialog_frame,
|
||||||
}
|
}
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
UIManager.full_refresh = true
|
UIManager.full_refresh = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputDialog:onShowKeyboard()
|
function InputDialog:onShowKeyboard()
|
||||||
self.input:onShowKeyboard()
|
self.input:onShowKeyboard()
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputDialog:getInputText()
|
function InputDialog:getInputText()
|
||||||
return self.input:getText()
|
return self.input:getText()
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputDialog:onClose()
|
function InputDialog:onClose()
|
||||||
self.input:onCloseKeyboard()
|
self.input:onCloseKeyboard()
|
||||||
end
|
end
|
||||||
|
|
||||||
return InputDialog
|
return InputDialog
|
||||||
|
|||||||
@@ -8,149 +8,149 @@ local Screen = require("ui/screen")
|
|||||||
local UIManager = require("ui/uimanager")
|
local UIManager = require("ui/uimanager")
|
||||||
|
|
||||||
local InputText = InputContainer:new{
|
local InputText = InputContainer:new{
|
||||||
text = "",
|
text = "",
|
||||||
hint = "demo hint",
|
hint = "demo hint",
|
||||||
charlist = {}, -- table to store input string
|
charlist = {}, -- table to store input string
|
||||||
charpos = 1,
|
charpos = 1,
|
||||||
input_type = nil,
|
input_type = nil,
|
||||||
|
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
face = Font:getFace("cfont", 22),
|
face = Font:getFace("cfont", 22),
|
||||||
|
|
||||||
padding = 5,
|
padding = 5,
|
||||||
margin = 5,
|
margin = 5,
|
||||||
bordersize = 2,
|
bordersize = 2,
|
||||||
|
|
||||||
parent = nil, -- parent dialog that will be set dirty
|
parent = nil, -- parent dialog that will be set dirty
|
||||||
scroll = false,
|
scroll = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputText:init()
|
function InputText:init()
|
||||||
self:StringToCharlist(self.text)
|
self:StringToCharlist(self.text)
|
||||||
self:initTextBox()
|
self:initTextBox()
|
||||||
self:initKeyboard()
|
self:initKeyboard()
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:initTextBox()
|
function InputText:initTextBox()
|
||||||
local bgcolor = nil
|
local bgcolor = nil
|
||||||
local fgcolor = nil
|
local fgcolor = nil
|
||||||
if self.text == "" then
|
if self.text == "" then
|
||||||
self.text = self.hint
|
self.text = self.hint
|
||||||
bgcolor = 0.0
|
bgcolor = 0.0
|
||||||
fgcolor = 0.5
|
fgcolor = 0.5
|
||||||
else
|
else
|
||||||
bgcolor = 0.0
|
bgcolor = 0.0
|
||||||
fgcolor = 1.0
|
fgcolor = 1.0
|
||||||
end
|
end
|
||||||
local text_widget = nil
|
local text_widget = nil
|
||||||
if self.scroll then
|
if self.scroll then
|
||||||
text_widget = ScrollTextWidget:new{
|
text_widget = ScrollTextWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = self.face,
|
face = self.face,
|
||||||
bgcolor = bgcolor,
|
bgcolor = bgcolor,
|
||||||
fgcolor = fgcolor,
|
fgcolor = fgcolor,
|
||||||
width = self.width,
|
width = self.width,
|
||||||
height = self.height,
|
height = self.height,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
text_widget = TextBoxWidget:new{
|
text_widget = TextBoxWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = self.face,
|
face = self.face,
|
||||||
bgcolor = bgcolor,
|
bgcolor = bgcolor,
|
||||||
fgcolor = fgcolor,
|
fgcolor = fgcolor,
|
||||||
width = self.width,
|
width = self.width,
|
||||||
height = self.height,
|
height = self.height,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
self[1] = FrameContainer:new{
|
self[1] = FrameContainer:new{
|
||||||
bordersize = self.bordersize,
|
bordersize = self.bordersize,
|
||||||
padding = self.padding,
|
padding = self.padding,
|
||||||
margin = self.margin,
|
margin = self.margin,
|
||||||
text_widget,
|
text_widget,
|
||||||
}
|
}
|
||||||
self.dimen = self[1]:getSize()
|
self.dimen = self[1]:getSize()
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:initKeyboard()
|
function InputText:initKeyboard()
|
||||||
local keyboard_layout = 2
|
local keyboard_layout = 2
|
||||||
if self.input_type == "number" then
|
if self.input_type == "number" then
|
||||||
keyboard_layout = 3
|
keyboard_layout = 3
|
||||||
end
|
end
|
||||||
self.keyboard = VirtualKeyboard:new{
|
self.keyboard = VirtualKeyboard:new{
|
||||||
layout = keyboard_layout,
|
layout = keyboard_layout,
|
||||||
inputbox = self,
|
inputbox = self,
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
height = math.max(Screen:getWidth(), Screen:getHeight())*0.33,
|
height = math.max(Screen:getWidth(), Screen:getHeight())*0.33,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:onShowKeyboard()
|
function InputText:onShowKeyboard()
|
||||||
UIManager:show(self.keyboard)
|
UIManager:show(self.keyboard)
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:onCloseKeyboard()
|
function InputText:onCloseKeyboard()
|
||||||
UIManager:close(self.keyboard)
|
UIManager:close(self.keyboard)
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:getKeyboardDimen()
|
function InputText:getKeyboardDimen()
|
||||||
return self.keyboard.dimen
|
return self.keyboard.dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:addChar(char)
|
function InputText:addChar(char)
|
||||||
if self.enter_callback and char == '\n' then
|
if self.enter_callback and char == '\n' then
|
||||||
UIManager:scheduleIn(0.3, function() self.enter_callback() end)
|
UIManager:scheduleIn(0.3, function() self.enter_callback() end)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
table.insert(self.charlist, self.charpos, char)
|
table.insert(self.charlist, self.charpos, char)
|
||||||
self.charpos = self.charpos + 1
|
self.charpos = self.charpos + 1
|
||||||
self.text = self:CharlistToString()
|
self.text = self:CharlistToString()
|
||||||
self:initTextBox()
|
self:initTextBox()
|
||||||
UIManager:setDirty(self.parent, "partial")
|
UIManager:setDirty(self.parent, "partial")
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:delChar()
|
function InputText:delChar()
|
||||||
if self.charpos == 1 then return end
|
if self.charpos == 1 then return end
|
||||||
self.charpos = self.charpos - 1
|
self.charpos = self.charpos - 1
|
||||||
table.remove(self.charlist, self.charpos)
|
table.remove(self.charlist, self.charpos)
|
||||||
self.text = self:CharlistToString()
|
self.text = self:CharlistToString()
|
||||||
self:initTextBox()
|
self:initTextBox()
|
||||||
UIManager:setDirty(self.parent, "partial")
|
UIManager:setDirty(self.parent, "partial")
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:getText()
|
function InputText:getText()
|
||||||
return self.text
|
return self.text
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:setText(text)
|
function InputText:setText(text)
|
||||||
self:StringToCharlist(text)
|
self:StringToCharlist(text)
|
||||||
self:initTextBox()
|
self:initTextBox()
|
||||||
UIManager:setDirty(self.parent, "partial")
|
UIManager:setDirty(self.parent, "partial")
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:StringToCharlist(text)
|
function InputText:StringToCharlist(text)
|
||||||
if text == nil then return end
|
if text == nil then return end
|
||||||
-- clear
|
-- clear
|
||||||
self.charlist = {}
|
self.charlist = {}
|
||||||
self.charpos = 1
|
self.charpos = 1
|
||||||
local prevcharcode, charcode = 0
|
local prevcharcode, charcode = 0
|
||||||
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
|
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
|
||||||
charcode = util.utf8charcode(uchar)
|
charcode = util.utf8charcode(uchar)
|
||||||
if prevcharcode then -- utf8
|
if prevcharcode then -- utf8
|
||||||
self.charlist[#self.charlist+1] = uchar
|
self.charlist[#self.charlist+1] = uchar
|
||||||
end
|
end
|
||||||
prevcharcode = charcode
|
prevcharcode = charcode
|
||||||
end
|
end
|
||||||
self.text = self:CharlistToString()
|
self.text = self:CharlistToString()
|
||||||
self.charpos = #self.charlist+1
|
self.charpos = #self.charlist+1
|
||||||
end
|
end
|
||||||
|
|
||||||
function InputText:CharlistToString()
|
function InputText:CharlistToString()
|
||||||
local s, i = ""
|
local s, i = ""
|
||||||
for i=1, #self.charlist do
|
for i=1, #self.charlist do
|
||||||
s = s .. self.charlist[i]
|
s = s .. self.charlist[i]
|
||||||
end
|
end
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
return InputText
|
return InputText
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
local Widget = require("ui/widget/widget")
|
local Widget = require("ui/widget/widget")
|
||||||
|
|
||||||
local LineWidget = Widget:new{
|
local LineWidget = Widget:new{
|
||||||
style = "solid",
|
style = "solid",
|
||||||
background = 15,
|
background = 15,
|
||||||
dimen = nil,
|
dimen = nil,
|
||||||
--@TODO replay dirty hack here 13.03 2013 (houqp)
|
--@TODO replay dirty hack here 13.03 2013 (houqp)
|
||||||
empty_segments = nil,
|
empty_segments = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function LineWidget:paintTo(bb, x, y)
|
function LineWidget:paintTo(bb, x, y)
|
||||||
if self.style == "dashed" then
|
if self.style == "dashed" then
|
||||||
for i = 0, self.dimen.w - 20, 20 do
|
for i = 0, self.dimen.w - 20, 20 do
|
||||||
bb:paintRect(x + i, y,
|
bb:paintRect(x + i, y,
|
||||||
16, self.dimen.h, self.background)
|
16, self.dimen.h, self.background)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if self.empty_segments then
|
if self.empty_segments then
|
||||||
bb:paintRect(x, y,
|
bb:paintRect(x, y,
|
||||||
self.empty_segments[1].s,
|
self.empty_segments[1].s,
|
||||||
self.dimen.h,
|
self.dimen.h,
|
||||||
self.background)
|
self.background)
|
||||||
bb:paintRect(x + self.empty_segments[1].e, y,
|
bb:paintRect(x + self.empty_segments[1].e, y,
|
||||||
self.dimen.w - x - self.empty_segments[1].e,
|
self.dimen.w - x - self.empty_segments[1].e,
|
||||||
self.dimen.h,
|
self.dimen.h,
|
||||||
self.background)
|
self.background)
|
||||||
else
|
else
|
||||||
bb:paintRect(x, y, self.dimen.w, self.dimen.h, self.background)
|
bb:paintRect(x, y, self.dimen.w, self.dimen.h, self.background)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return LineWidget
|
return LineWidget
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,50 +14,50 @@ local Screen = require("ui/screen")
|
|||||||
Widget that displays a tiny notification on top of screen
|
Widget that displays a tiny notification on top of screen
|
||||||
--]]
|
--]]
|
||||||
local Notification = InputContainer:new{
|
local Notification = InputContainer:new{
|
||||||
face = Font:getFace("infofont", 20),
|
face = Font:getFace("infofont", 20),
|
||||||
text = "Null Message",
|
text = "Null Message",
|
||||||
timeout = nil,
|
timeout = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Notification:init()
|
function Notification:init()
|
||||||
if Device:hasKeyboard() then
|
if Device:hasKeyboard() then
|
||||||
self.key_events = {
|
self.key_events = {
|
||||||
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
|
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
-- we construct the actual content here because self.text is only available now
|
-- we construct the actual content here because self.text is only available now
|
||||||
self[1] = CenterContainer:new{
|
self[1] = CenterContainer:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight()/10,
|
h = Screen:getHeight()/10,
|
||||||
},
|
},
|
||||||
ignore = "height",
|
ignore = "height",
|
||||||
FrameContainer:new{
|
FrameContainer:new{
|
||||||
background = 0,
|
background = 0,
|
||||||
radius = 0,
|
radius = 0,
|
||||||
HorizontalGroup:new{
|
HorizontalGroup:new{
|
||||||
align = "center",
|
align = "center",
|
||||||
TextBoxWidget:new{
|
TextBoxWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = self.face,
|
face = self.face,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function Notification:onShow()
|
function Notification:onShow()
|
||||||
-- triggered by the UIManager after we got successfully shown (not yet painted)
|
-- triggered by the UIManager after we got successfully shown (not yet painted)
|
||||||
if self.timeout then
|
if self.timeout then
|
||||||
UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end)
|
UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Notification:onAnyKeyPressed()
|
function Notification:onAnyKeyPressed()
|
||||||
-- triggered by our defined key events
|
-- triggered by our defined key events
|
||||||
UIManager:close(self)
|
UIManager:close(self)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return Notification
|
return Notification
|
||||||
|
|||||||
@@ -4,48 +4,48 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|||||||
A Layout widget that puts objects above each other
|
A Layout widget that puts objects above each other
|
||||||
--]]
|
--]]
|
||||||
local OverlapGroup = WidgetContainer:new{
|
local OverlapGroup = WidgetContainer:new{
|
||||||
_size = nil,
|
_size = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function OverlapGroup:getSize()
|
function OverlapGroup:getSize()
|
||||||
if not self._size then
|
if not self._size then
|
||||||
self._size = {w = 0, h = 0}
|
self._size = {w = 0, h = 0}
|
||||||
self._offsets = { x = math.huge, y = math.huge }
|
self._offsets = { x = math.huge, y = math.huge }
|
||||||
for i, widget in ipairs(self) do
|
for i, widget in ipairs(self) do
|
||||||
local w_size = widget:getSize()
|
local w_size = widget:getSize()
|
||||||
if self._size.h < w_size.h then
|
if self._size.h < w_size.h then
|
||||||
self._size.h = w_size.h
|
self._size.h = w_size.h
|
||||||
end
|
end
|
||||||
if self._size.w < w_size.w then
|
if self._size.w < w_size.w then
|
||||||
self._size.w = w_size.w
|
self._size.w = w_size.w
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.dimen.w then
|
if self.dimen.w then
|
||||||
self._size.w = self.dimen.w
|
self._size.w = self.dimen.w
|
||||||
end
|
end
|
||||||
if self.dimen.h then
|
if self.dimen.h then
|
||||||
self._size.h = self.dimen.h
|
self._size.h = self.dimen.h
|
||||||
end
|
end
|
||||||
|
|
||||||
return self._size
|
return self._size
|
||||||
end
|
end
|
||||||
|
|
||||||
function OverlapGroup:paintTo(bb, x, y)
|
function OverlapGroup:paintTo(bb, x, y)
|
||||||
local size = self:getSize()
|
local size = self:getSize()
|
||||||
|
|
||||||
for i, wget in ipairs(self) do
|
for i, wget in ipairs(self) do
|
||||||
local wget_size = wget:getSize()
|
local wget_size = wget:getSize()
|
||||||
if wget.align == "right" then
|
if wget.align == "right" then
|
||||||
wget:paintTo(bb, x+size.w-wget_size.w, y)
|
wget:paintTo(bb, x+size.w-wget_size.w, y)
|
||||||
elseif wget.align == "center" then
|
elseif wget.align == "center" then
|
||||||
wget:paintTo(bb, x+math.floor((size.w-wget_size.w)/2), y)
|
wget:paintTo(bb, x+math.floor((size.w-wget_size.w)/2), y)
|
||||||
else
|
else
|
||||||
-- default to left
|
-- default to left
|
||||||
wget:paintTo(bb, x, y)
|
wget:paintTo(bb, x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return OverlapGroup
|
return OverlapGroup
|
||||||
|
|||||||
@@ -5,39 +5,39 @@ local Geom = require("ui/geometry")
|
|||||||
ProgressWidget shows a progress bar
|
ProgressWidget shows a progress bar
|
||||||
--]]
|
--]]
|
||||||
local ProgressWidget = Widget:new{
|
local ProgressWidget = Widget:new{
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
margin_h = 3,
|
margin_h = 3,
|
||||||
margin_v = 1,
|
margin_v = 1,
|
||||||
radius = 2,
|
radius = 2,
|
||||||
bordersize = 1,
|
bordersize = 1,
|
||||||
bordercolor = 15,
|
bordercolor = 15,
|
||||||
bgcolor = 0,
|
bgcolor = 0,
|
||||||
rectcolor = 10,
|
rectcolor = 10,
|
||||||
percentage = nil,
|
percentage = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProgressWidget:getSize()
|
function ProgressWidget:getSize()
|
||||||
return { w = self.width, h = self.height }
|
return { w = self.width, h = self.height }
|
||||||
end
|
end
|
||||||
|
|
||||||
function ProgressWidget:paintTo(bb, x, y)
|
function ProgressWidget:paintTo(bb, x, y)
|
||||||
local my_size = self:getSize()
|
local my_size = self:getSize()
|
||||||
self.dimen = Geom:new{
|
self.dimen = Geom:new{
|
||||||
x = x, y = y,
|
x = x, y = y,
|
||||||
w = my_size.w,
|
w = my_size.w,
|
||||||
h = my_size.h
|
h = my_size.h
|
||||||
}
|
}
|
||||||
bb:paintRoundedRect(x, y, my_size.w, my_size.h, self.bgcolor, self.radius)
|
bb:paintRoundedRect(x, y, my_size.w, my_size.h, self.bgcolor, self.radius)
|
||||||
bb:paintBorder(x, y, my_size.w, my_size.h,
|
bb:paintBorder(x, y, my_size.w, my_size.h,
|
||||||
self.bordersize, self.bordercolor, self.radius)
|
self.bordersize, self.bordercolor, self.radius)
|
||||||
bb:paintRect(x+self.margin_h, y+self.margin_v+self.bordersize,
|
bb:paintRect(x+self.margin_h, y+self.margin_v+self.bordersize,
|
||||||
(my_size.w-2*self.margin_h)*self.percentage,
|
(my_size.w-2*self.margin_h)*self.percentage,
|
||||||
(my_size.h-2*(self.margin_v+self.bordersize)), self.rectcolor)
|
(my_size.h-2*(self.margin_v+self.bordersize)), self.rectcolor)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ProgressWidget:setPercentage(percentage)
|
function ProgressWidget:setPercentage(percentage)
|
||||||
self.percentage = percentage
|
self.percentage = percentage
|
||||||
end
|
end
|
||||||
|
|
||||||
return ProgressWidget
|
return ProgressWidget
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ local Widget = require("ui/widget/widget")
|
|||||||
Dummy Widget that reserves vertical and horizontal space
|
Dummy Widget that reserves vertical and horizontal space
|
||||||
]]
|
]]
|
||||||
local RectSpan = Widget:new{
|
local RectSpan = Widget:new{
|
||||||
width = 0,
|
width = 0,
|
||||||
hright = 0,
|
hright = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function RectSpan:getSize()
|
function RectSpan:getSize()
|
||||||
return {w = self.width, h = self.height}
|
return {w = self.width, h = self.height}
|
||||||
end
|
end
|
||||||
|
|
||||||
return RectSpan
|
return RectSpan
|
||||||
|
|||||||
@@ -13,73 +13,73 @@ local Device = require("ui/device")
|
|||||||
Text widget with vertical scroll bar
|
Text widget with vertical scroll bar
|
||||||
--]]
|
--]]
|
||||||
local ScrollTextWidget = InputContainer:new{
|
local ScrollTextWidget = InputContainer:new{
|
||||||
text = nil,
|
text = nil,
|
||||||
face = nil,
|
face = nil,
|
||||||
bgcolor = 0.0, -- [0.0, 1.0]
|
bgcolor = 0.0, -- [0.0, 1.0]
|
||||||
fgcolor = 1.0, -- [0.0, 1.0]
|
fgcolor = 1.0, -- [0.0, 1.0]
|
||||||
width = 400,
|
width = 400,
|
||||||
height = 20,
|
height = 20,
|
||||||
scroll_bar_width = Screen:scaleByDPI(6),
|
scroll_bar_width = Screen:scaleByDPI(6),
|
||||||
text_scroll_span = Screen:scaleByDPI(6),
|
text_scroll_span = Screen:scaleByDPI(6),
|
||||||
dialog = nil,
|
dialog = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScrollTextWidget:init()
|
function ScrollTextWidget:init()
|
||||||
self.text_widget = TextBoxWidget:new{
|
self.text_widget = TextBoxWidget:new{
|
||||||
text = self.text,
|
text = self.text,
|
||||||
face = self.face,
|
face = self.face,
|
||||||
bgcolor = self.bgcolor,
|
bgcolor = self.bgcolor,
|
||||||
fgcolor = self.fgcolor,
|
fgcolor = self.fgcolor,
|
||||||
width = self.width - self.scroll_bar_width - self.text_scroll_span,
|
width = self.width - self.scroll_bar_width - self.text_scroll_span,
|
||||||
height = self.height
|
height = self.height
|
||||||
}
|
}
|
||||||
local visible_line_count = self.text_widget:getVisLineCount()
|
local visible_line_count = self.text_widget:getVisLineCount()
|
||||||
local total_line_count = self.text_widget:getAllLineCount()
|
local total_line_count = self.text_widget:getAllLineCount()
|
||||||
self.v_scroll_bar = VerticalScrollBar:new{
|
self.v_scroll_bar = VerticalScrollBar:new{
|
||||||
enable = visible_line_count < total_line_count,
|
enable = visible_line_count < total_line_count,
|
||||||
low = 0,
|
low = 0,
|
||||||
high = visible_line_count/total_line_count,
|
high = visible_line_count/total_line_count,
|
||||||
width = Screen:scaleByDPI(6),
|
width = Screen:scaleByDPI(6),
|
||||||
height = self.height,
|
height = self.height,
|
||||||
}
|
}
|
||||||
local horizontal_group = HorizontalGroup:new{}
|
local horizontal_group = HorizontalGroup:new{}
|
||||||
table.insert(horizontal_group, self.text_widget)
|
table.insert(horizontal_group, self.text_widget)
|
||||||
table.insert(horizontal_group, HorizontalSpan:new{width = Screen:scaleByDPI(6)})
|
table.insert(horizontal_group, HorizontalSpan:new{width = Screen:scaleByDPI(6)})
|
||||||
table.insert(horizontal_group, self.v_scroll_bar)
|
table.insert(horizontal_group, self.v_scroll_bar)
|
||||||
self[1] = horizontal_group
|
self[1] = horizontal_group
|
||||||
self.dimen = Geom:new(self[1]:getSize())
|
self.dimen = Geom:new(self[1]:getSize())
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
Swipe = {
|
Swipe = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ScrollTextWidget:updateScrollBar(text)
|
function ScrollTextWidget:updateScrollBar(text)
|
||||||
local virtual_line_num = text:getVirtualLineNum()
|
local virtual_line_num = text:getVirtualLineNum()
|
||||||
local visible_line_count = text:getVisLineCount()
|
local visible_line_count = text:getVisLineCount()
|
||||||
local all_line_count = text:getAllLineCount()
|
local all_line_count = text:getAllLineCount()
|
||||||
self.v_scroll_bar:set(
|
self.v_scroll_bar:set(
|
||||||
(virtual_line_num - 1) / all_line_count,
|
(virtual_line_num - 1) / all_line_count,
|
||||||
(virtual_line_num - 1 + visible_line_count) / all_line_count
|
(virtual_line_num - 1 + visible_line_count) / all_line_count
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ScrollTextWidget:onSwipe(arg, ges)
|
function ScrollTextWidget:onSwipe(arg, ges)
|
||||||
if ges.direction == "north" then
|
if ges.direction == "north" then
|
||||||
self.text_widget:scrollDown()
|
self.text_widget:scrollDown()
|
||||||
self:updateScrollBar(self.text_widget)
|
self:updateScrollBar(self.text_widget)
|
||||||
elseif ges.direction == "south" then
|
elseif ges.direction == "south" then
|
||||||
self.text_widget:scrollUp()
|
self.text_widget:scrollUp()
|
||||||
self:updateScrollBar(self.text_widget)
|
self:updateScrollBar(self.text_widget)
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.dialog, "partial")
|
UIManager:setDirty(self.dialog, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ScrollTextWidget
|
return ScrollTextWidget
|
||||||
|
|||||||
@@ -9,59 +9,59 @@ local Geom = require("ui/geometry")
|
|||||||
A TextWidget that handles long text wrapping
|
A TextWidget that handles long text wrapping
|
||||||
--]]
|
--]]
|
||||||
local TextBoxWidget = Widget:new{
|
local TextBoxWidget = Widget:new{
|
||||||
text = nil,
|
text = nil,
|
||||||
face = nil,
|
face = nil,
|
||||||
bold = nil,
|
bold = nil,
|
||||||
bgcolor = 0.0, -- [0.0, 1.0]
|
bgcolor = 0.0, -- [0.0, 1.0]
|
||||||
fgcolor = 1.0, -- [0.0, 1.0]
|
fgcolor = 1.0, -- [0.0, 1.0]
|
||||||
width = 400, -- in pixels
|
width = 400, -- in pixels
|
||||||
height = nil,
|
height = nil,
|
||||||
first_line = 1,
|
first_line = 1,
|
||||||
virtual_line = 1, -- used by scroll bar
|
virtual_line = 1, -- used by scroll bar
|
||||||
line_height = 0.3, -- in em
|
line_height = 0.3, -- in em
|
||||||
v_list = nil,
|
v_list = nil,
|
||||||
_bb = nil,
|
_bb = nil,
|
||||||
_length = 0,
|
_length = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextBoxWidget:init()
|
function TextBoxWidget:init()
|
||||||
local v_list = nil
|
local v_list = nil
|
||||||
if self.height then
|
if self.height then
|
||||||
v_list = self:_getCurrentVerticalList()
|
v_list = self:_getCurrentVerticalList()
|
||||||
else
|
else
|
||||||
v_list = self:_getVerticalList()
|
v_list = self:_getVerticalList()
|
||||||
end
|
end
|
||||||
self:_render(v_list)
|
self:_render(v_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_wrapGreedyAlg(h_list)
|
function TextBoxWidget:_wrapGreedyAlg(h_list)
|
||||||
local cur_line_width = 0
|
local cur_line_width = 0
|
||||||
local cur_line = {}
|
local cur_line = {}
|
||||||
local v_list = {}
|
local v_list = {}
|
||||||
|
|
||||||
for k,w in ipairs(h_list) do
|
for k,w in ipairs(h_list) do
|
||||||
cur_line_width = cur_line_width + w.width
|
cur_line_width = cur_line_width + w.width
|
||||||
if w.word == "\n" then
|
if w.word == "\n" then
|
||||||
if cur_line_width > 0 then
|
if cur_line_width > 0 then
|
||||||
-- hard line break
|
-- hard line break
|
||||||
table.insert(v_list, cur_line)
|
table.insert(v_list, cur_line)
|
||||||
cur_line = {}
|
cur_line = {}
|
||||||
cur_line_width = 0
|
cur_line_width = 0
|
||||||
end
|
end
|
||||||
elseif cur_line_width > self.width then
|
elseif cur_line_width > self.width then
|
||||||
-- wrap to next line
|
-- wrap to next line
|
||||||
table.insert(v_list, cur_line)
|
table.insert(v_list, cur_line)
|
||||||
cur_line = {}
|
cur_line = {}
|
||||||
cur_line_width = w.width
|
cur_line_width = w.width
|
||||||
table.insert(cur_line, w)
|
table.insert(cur_line, w)
|
||||||
else
|
else
|
||||||
table.insert(cur_line, w)
|
table.insert(cur_line, w)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- handle last line
|
-- handle last line
|
||||||
table.insert(v_list, cur_line)
|
table.insert(v_list, cur_line)
|
||||||
|
|
||||||
return v_list
|
return v_list
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -77,199 +77,199 @@ License: MIT/X11
|
|||||||
Source: http://snippets.luacode.org/snippets/String_splitting_130
|
Source: http://snippets.luacode.org/snippets/String_splitting_130
|
||||||
--]]
|
--]]
|
||||||
function string:gsplit(pattern, capture)
|
function string:gsplit(pattern, capture)
|
||||||
pattern = pattern and tostring(pattern) or '%s+'
|
pattern = pattern and tostring(pattern) or '%s+'
|
||||||
if (''):find(pattern) then
|
if (''):find(pattern) then
|
||||||
error('pattern matches empty string!', 2)
|
error('pattern matches empty string!', 2)
|
||||||
end
|
end
|
||||||
return coroutine.wrap(function()
|
return coroutine.wrap(function()
|
||||||
local index = 1
|
local index = 1
|
||||||
repeat
|
repeat
|
||||||
local first, last = self:find(pattern, index)
|
local first, last = self:find(pattern, index)
|
||||||
if first and last then
|
if first and last then
|
||||||
if index < first then
|
if index < first then
|
||||||
coroutine.yield(self:sub(index, first - 1))
|
coroutine.yield(self:sub(index, first - 1))
|
||||||
end
|
end
|
||||||
if capture then
|
if capture then
|
||||||
coroutine.yield(self:sub(first, last))
|
coroutine.yield(self:sub(first, last))
|
||||||
end
|
end
|
||||||
index = last + 1
|
index = last + 1
|
||||||
else
|
else
|
||||||
if index <= #self then
|
if index <= #self then
|
||||||
coroutine.yield(self:sub(index))
|
coroutine.yield(self:sub(index))
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
until index > #self
|
until index > #self
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_getVerticalList(alg)
|
function TextBoxWidget:_getVerticalList(alg)
|
||||||
if self.vertical_list then
|
if self.vertical_list then
|
||||||
return self.vertical_list
|
return self.vertical_list
|
||||||
end
|
end
|
||||||
-- build horizontal list
|
-- build horizontal list
|
||||||
local h_list = {}
|
local h_list = {}
|
||||||
local line_count = 0
|
local line_count = 0
|
||||||
for line in self.text:gsplit("\n", true) do
|
for line in self.text:gsplit("\n", true) do
|
||||||
for words in line:gmatch("[\32-\127\192-\255]+[\128-\191]*") do
|
for words in line:gmatch("[\32-\127\192-\255]+[\128-\191]*") do
|
||||||
for word in words:gsplit("%s+", true) do
|
for word in words:gsplit("%s+", true) do
|
||||||
for w in word:gsplit("%p+", true) do
|
for w in word:gsplit("%p+", true) do
|
||||||
local word_box = {}
|
local word_box = {}
|
||||||
word_box.word = w
|
word_box.word = w
|
||||||
word_box.width = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, w, true, self.bold).x
|
word_box.width = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, w, true, self.bold).x
|
||||||
table.insert(h_list, word_box)
|
table.insert(h_list, word_box)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if line:sub(-1) == "\n" then table.insert(h_list, {word = '\n', width = 0}) end
|
if line:sub(-1) == "\n" then table.insert(h_list, {word = '\n', width = 0}) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @TODO check alg here 25.04 2012 (houqp)
|
-- @TODO check alg here 25.04 2012 (houqp)
|
||||||
-- @TODO replace greedy algorithm with K&P algorithm 25.04 2012 (houqp)
|
-- @TODO replace greedy algorithm with K&P algorithm 25.04 2012 (houqp)
|
||||||
self.vertical_list = self:_wrapGreedyAlg(h_list)
|
self.vertical_list = self:_wrapGreedyAlg(h_list)
|
||||||
return self.vertical_list
|
return self.vertical_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_getCurrentVerticalList()
|
function TextBoxWidget:_getCurrentVerticalList()
|
||||||
local line_height = (1 + self.line_height) * self.face.size
|
local line_height = (1 + self.line_height) * self.face.size
|
||||||
local v_list = self:_getVerticalList()
|
local v_list = self:_getVerticalList()
|
||||||
local current_v_list = {}
|
local current_v_list = {}
|
||||||
local height = 0
|
local height = 0
|
||||||
for i = self.first_line, #v_list do
|
for i = self.first_line, #v_list do
|
||||||
if height < self.height - line_height then
|
if height < self.height - line_height then
|
||||||
table.insert(current_v_list, v_list[i])
|
table.insert(current_v_list, v_list[i])
|
||||||
height = height + line_height
|
height = height + line_height
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return current_v_list
|
return current_v_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_getPreviousVerticalList()
|
function TextBoxWidget:_getPreviousVerticalList()
|
||||||
local line_height = (1 + self.line_height) * self.face.size
|
local line_height = (1 + self.line_height) * self.face.size
|
||||||
local v_list = self:_getVerticalList()
|
local v_list = self:_getVerticalList()
|
||||||
local previous_v_list = {}
|
local previous_v_list = {}
|
||||||
local height = 0
|
local height = 0
|
||||||
if self.first_line == 1 then
|
if self.first_line == 1 then
|
||||||
return self:_getCurrentVerticalList()
|
return self:_getCurrentVerticalList()
|
||||||
end
|
end
|
||||||
self.virtual_line = self.first_line
|
self.virtual_line = self.first_line
|
||||||
for i = self.first_line - 1, 1, -1 do
|
for i = self.first_line - 1, 1, -1 do
|
||||||
if height < self.height - line_height then
|
if height < self.height - line_height then
|
||||||
table.insert(previous_v_list, 1, v_list[i])
|
table.insert(previous_v_list, 1, v_list[i])
|
||||||
height = height + line_height
|
height = height + line_height
|
||||||
self.virtual_line = self.virtual_line - 1
|
self.virtual_line = self.virtual_line - 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i = self.first_line, #v_list do
|
for i = self.first_line, #v_list do
|
||||||
if height < self.height - line_height then
|
if height < self.height - line_height then
|
||||||
table.insert(previous_v_list, v_list[i])
|
table.insert(previous_v_list, v_list[i])
|
||||||
height = height + line_height
|
height = height + line_height
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.first_line > #previous_v_list then
|
if self.first_line > #previous_v_list then
|
||||||
self.first_line = self.first_line - #previous_v_list
|
self.first_line = self.first_line - #previous_v_list
|
||||||
else
|
else
|
||||||
self.first_line = 1
|
self.first_line = 1
|
||||||
end
|
end
|
||||||
return previous_v_list
|
return previous_v_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_getNextVerticalList()
|
function TextBoxWidget:_getNextVerticalList()
|
||||||
local line_height = (1 + self.line_height) * self.face.size
|
local line_height = (1 + self.line_height) * self.face.size
|
||||||
local v_list = self:_getVerticalList()
|
local v_list = self:_getVerticalList()
|
||||||
local current_v_list = self:_getCurrentVerticalList()
|
local current_v_list = self:_getCurrentVerticalList()
|
||||||
local next_v_list = {}
|
local next_v_list = {}
|
||||||
local height = 0
|
local height = 0
|
||||||
if self.first_line + #current_v_list > #v_list then
|
if self.first_line + #current_v_list > #v_list then
|
||||||
return current_v_list
|
return current_v_list
|
||||||
end
|
end
|
||||||
self.virtual_line = self.first_line
|
self.virtual_line = self.first_line
|
||||||
for i = self.first_line + #current_v_list, #v_list do
|
for i = self.first_line + #current_v_list, #v_list do
|
||||||
if height < self.height - line_height then
|
if height < self.height - line_height then
|
||||||
table.insert(next_v_list, v_list[i])
|
table.insert(next_v_list, v_list[i])
|
||||||
height = height + line_height
|
height = height + line_height
|
||||||
self.virtual_line = self.virtual_line + 1
|
self.virtual_line = self.virtual_line + 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.first_line = self.first_line + #current_v_list
|
self.first_line = self.first_line + #current_v_list
|
||||||
return next_v_list
|
return next_v_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:_render(v_list)
|
function TextBoxWidget:_render(v_list)
|
||||||
local font_height = self.face.size
|
local font_height = self.face.size
|
||||||
local line_height_px = self.line_height * font_height
|
local line_height_px = self.line_height * font_height
|
||||||
local space_w = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x
|
local space_w = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x
|
||||||
local h = (font_height + line_height_px) * #v_list
|
local h = (font_height + line_height_px) * #v_list
|
||||||
self._bb = Blitbuffer.new(self.width, h)
|
self._bb = Blitbuffer.new(self.width, h)
|
||||||
local y = font_height
|
local y = font_height
|
||||||
local pen_x = 0
|
local pen_x = 0
|
||||||
for _,l in ipairs(v_list) do
|
for _,l in ipairs(v_list) do
|
||||||
pen_x = 0
|
pen_x = 0
|
||||||
for _,w in ipairs(l) do
|
for _,w in ipairs(l) do
|
||||||
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
||||||
-- refert to cb25029dddc42693cc7aaefbe47e9bd3b7e1a750 in master tree
|
-- refert to cb25029dddc42693cc7aaefbe47e9bd3b7e1a750 in master tree
|
||||||
RenderText:renderUtf8Text(self._bb, pen_x, y, self.face, w.word, true, self.bold, self.bgcolor, self.fgcolor)
|
RenderText:renderUtf8Text(self._bb, pen_x, y, self.face, w.word, true, self.bold, self.bgcolor, self.fgcolor)
|
||||||
pen_x = pen_x + w.width
|
pen_x = pen_x + w.width
|
||||||
end
|
end
|
||||||
y = y + line_height_px + font_height
|
y = y + line_height_px + font_height
|
||||||
end
|
end
|
||||||
-- -- if text is shorter than one line, shrink to text's width
|
-- -- if text is shorter than one line, shrink to text's width
|
||||||
-- if #v_list == 1 then
|
-- if #v_list == 1 then
|
||||||
-- self.width = pen_x
|
-- self.width = pen_x
|
||||||
-- end
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:getVirtualLineNum()
|
function TextBoxWidget:getVirtualLineNum()
|
||||||
return self.virtual_line
|
return self.virtual_line
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:getAllLineCount()
|
function TextBoxWidget:getAllLineCount()
|
||||||
local v_list = self:_getVerticalList()
|
local v_list = self:_getVerticalList()
|
||||||
return #v_list
|
return #v_list
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:getVisLineCount()
|
function TextBoxWidget:getVisLineCount()
|
||||||
local line_height = (1 + self.line_height) * self.face.size
|
local line_height = (1 + self.line_height) * self.face.size
|
||||||
return math.floor(self.height / line_height)
|
return math.floor(self.height / line_height)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:scrollDown()
|
function TextBoxWidget:scrollDown()
|
||||||
local next_v_list = self:_getNextVerticalList()
|
local next_v_list = self:_getNextVerticalList()
|
||||||
self:free()
|
self:free()
|
||||||
self:_render(next_v_list)
|
self:_render(next_v_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:scrollUp()
|
function TextBoxWidget:scrollUp()
|
||||||
local previous_v_list = self:_getPreviousVerticalList()
|
local previous_v_list = self:_getPreviousVerticalList()
|
||||||
self:free()
|
self:free()
|
||||||
self:_render(previous_v_list)
|
self:_render(previous_v_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:getSize()
|
function TextBoxWidget:getSize()
|
||||||
if self.width and self.height then
|
if self.width and self.height then
|
||||||
return Geom:new{ w = self.width, h = self.height}
|
return Geom:new{ w = self.width, h = self.height}
|
||||||
else
|
else
|
||||||
return Geom:new{ w = self.width, h = self._bb:getHeight()}
|
return Geom:new{ w = self.width, h = self._bb:getHeight()}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:paintTo(bb, x, y)
|
function TextBoxWidget:paintTo(bb, x, y)
|
||||||
bb:blitFrom(self._bb, x, y, 0, 0, self.width, self._bb:getHeight())
|
bb:blitFrom(self._bb, x, y, 0, 0, self.width, self._bb:getHeight())
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextBoxWidget:free()
|
function TextBoxWidget:free()
|
||||||
if self._bb then
|
if self._bb then
|
||||||
self._bb:free()
|
self._bb:free()
|
||||||
self._bb = nil
|
self._bb = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return TextBoxWidget
|
return TextBoxWidget
|
||||||
|
|||||||
@@ -7,55 +7,55 @@ local Geom = require("ui/geometry")
|
|||||||
A TextWidget puts a string on a single line
|
A TextWidget puts a string on a single line
|
||||||
--]]
|
--]]
|
||||||
local TextWidget = Widget:new{
|
local TextWidget = Widget:new{
|
||||||
text = nil,
|
text = nil,
|
||||||
face = nil,
|
face = nil,
|
||||||
bold = nil,
|
bold = nil,
|
||||||
bgcolor = 0.0, -- [0.0, 1.0]
|
bgcolor = 0.0, -- [0.0, 1.0]
|
||||||
fgcolor = 1.0, -- [0.0, 1.0]
|
fgcolor = 1.0, -- [0.0, 1.0]
|
||||||
_bb = nil,
|
_bb = nil,
|
||||||
_length = 0,
|
_length = 0,
|
||||||
_height = 0,
|
_height = 0,
|
||||||
_maxlength = 1200,
|
_maxlength = 1200,
|
||||||
}
|
}
|
||||||
|
|
||||||
--function TextWidget:_render()
|
--function TextWidget:_render()
|
||||||
--local h = self.face.size * 1.3
|
--local h = self.face.size * 1.3
|
||||||
--self._bb = Blitbuffer.new(self._maxlength, h)
|
--self._bb = Blitbuffer.new(self._maxlength, h)
|
||||||
--self._length = RenderText:renderUtf8Text(self._bb, 0, h*0.8, self.face, self.text, true, self.bold)
|
--self._length = RenderText:renderUtf8Text(self._bb, 0, h*0.8, self.face, self.text, true, self.bold)
|
||||||
--end
|
--end
|
||||||
|
|
||||||
function TextWidget:getSize()
|
function TextWidget:getSize()
|
||||||
--if not self._bb then
|
--if not self._bb then
|
||||||
--self:_render()
|
--self:_render()
|
||||||
--end
|
--end
|
||||||
--return { w = self._length, h = self._bb:getHeight() }
|
--return { w = self._length, h = self._bb:getHeight() }
|
||||||
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
|
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
|
||||||
if not tsize then
|
if not tsize then
|
||||||
return Geom:new{}
|
return Geom:new{}
|
||||||
end
|
end
|
||||||
self._length = tsize.x
|
self._length = tsize.x
|
||||||
self._height = self.face.size * 1.5
|
self._height = self.face.size * 1.5
|
||||||
return Geom:new{
|
return Geom:new{
|
||||||
w = self._length,
|
w = self._length,
|
||||||
h = self._height,
|
h = self._height,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextWidget:paintTo(bb, x, y)
|
function TextWidget:paintTo(bb, x, y)
|
||||||
--if not self._bb then
|
--if not self._bb then
|
||||||
--self:_render()
|
--self:_render()
|
||||||
--end
|
--end
|
||||||
--bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
|
--bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
|
||||||
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
||||||
RenderText:renderUtf8Text(bb, x, y+self._height*0.7, self.face, self.text, true, self.bold,
|
RenderText:renderUtf8Text(bb, x, y+self._height*0.7, self.face, self.text, true, self.bold,
|
||||||
self.bgcolor, self.fgcolor, self.width)
|
self.bgcolor, self.fgcolor, self.width)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TextWidget:free()
|
function TextWidget:free()
|
||||||
if self._bb then
|
if self._bb then
|
||||||
self._bb:free()
|
self._bb:free()
|
||||||
self._bb = nil
|
self._bb = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return TextWidget
|
return TextWidget
|
||||||
|
|||||||
@@ -14,126 +14,126 @@ local DEBUG = require("dbg")
|
|||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
|
|
||||||
local ToggleLabel = TextWidget:new{
|
local ToggleLabel = TextWidget:new{
|
||||||
bold = true,
|
bold = true,
|
||||||
bgcolor = 0,
|
bgcolor = 0,
|
||||||
fgcolor = 1,
|
fgcolor = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToggleLabel:paintTo(bb, x, y)
|
function ToggleLabel:paintTo(bb, x, y)
|
||||||
RenderText:renderUtf8Text(bb, x, y+self._height*0.75, self.face, self.text, true, self.bold, self.bgcolor, self.fgcolor)
|
RenderText:renderUtf8Text(bb, x, y+self._height*0.75, self.face, self.text, true, self.bold, self.bgcolor, self.fgcolor)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ToggleSwitch = InputContainer:new{
|
local ToggleSwitch = InputContainer:new{
|
||||||
width = Screen:scaleByDPI(216),
|
width = Screen:scaleByDPI(216),
|
||||||
height = Screen:scaleByDPI(30),
|
height = Screen:scaleByDPI(30),
|
||||||
bgcolor = 0, -- unfoused item color
|
bgcolor = 0, -- unfoused item color
|
||||||
fgcolor = 7, -- focused item color
|
fgcolor = 7, -- focused item color
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToggleSwitch:init()
|
function ToggleSwitch:init()
|
||||||
self.n_pos = #self.toggle
|
self.n_pos = #self.toggle
|
||||||
self.position = nil
|
self.position = nil
|
||||||
|
|
||||||
local label_font_face = "cfont"
|
local label_font_face = "cfont"
|
||||||
local label_font_size = 16
|
local label_font_size = 16
|
||||||
|
|
||||||
self.toggle_frame = FrameContainer:new{background = 0, color = 7, radius = 7, bordersize = 1, padding = 2,}
|
self.toggle_frame = FrameContainer:new{background = 0, color = 7, radius = 7, bordersize = 1, padding = 2,}
|
||||||
self.toggle_content = HorizontalGroup:new{}
|
self.toggle_content = HorizontalGroup:new{}
|
||||||
|
|
||||||
for i=1,#self.toggle do
|
for i=1,#self.toggle do
|
||||||
local label = ToggleLabel:new{
|
local label = ToggleLabel:new{
|
||||||
align = "center",
|
align = "center",
|
||||||
text = self.toggle[i],
|
text = self.toggle[i],
|
||||||
face = Font:getFace(label_font_face, label_font_size),
|
face = Font:getFace(label_font_face, label_font_size),
|
||||||
}
|
}
|
||||||
local content = CenterContainer:new{
|
local content = CenterContainer:new{
|
||||||
dimen = Geom:new{w = self.width/self.n_pos, h = self.height},
|
dimen = Geom:new{w = self.width/self.n_pos, h = self.height},
|
||||||
label,
|
label,
|
||||||
}
|
}
|
||||||
local button = FrameContainer:new{
|
local button = FrameContainer:new{
|
||||||
background = 0,
|
background = 0,
|
||||||
color = 7,
|
color = 7,
|
||||||
margin = 0,
|
margin = 0,
|
||||||
radius = 5,
|
radius = 5,
|
||||||
bordersize = 1,
|
bordersize = 1,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
content,
|
content,
|
||||||
}
|
}
|
||||||
table.insert(self.toggle_content, button)
|
table.insert(self.toggle_content, button)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.toggle_frame[1] = self.toggle_content
|
self.toggle_frame[1] = self.toggle_content
|
||||||
self[1] = self.toggle_frame
|
self[1] = self.toggle_frame
|
||||||
self.dimen = Geom:new(self.toggle_frame:getSize())
|
self.dimen = Geom:new(self.toggle_frame:getSize())
|
||||||
if Device:isTouchDevice() then
|
if Device:isTouchDevice() then
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Toggle switch"),
|
doc = _("Toggle switch"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ToggleSwitch:update()
|
function ToggleSwitch:update()
|
||||||
local pos = self.position
|
local pos = self.position
|
||||||
for i=1,#self.toggle_content do
|
for i=1,#self.toggle_content do
|
||||||
if pos == i then
|
if pos == i then
|
||||||
self.toggle_content[i].color = self.fgcolor
|
self.toggle_content[i].color = self.fgcolor
|
||||||
self.toggle_content[i].background = self.fgcolor
|
self.toggle_content[i].background = self.fgcolor
|
||||||
self.toggle_content[i][1][1].bgcolor = self.fgcolor/15
|
self.toggle_content[i][1][1].bgcolor = self.fgcolor/15
|
||||||
self.toggle_content[i][1][1].fgcolor = 0.0
|
self.toggle_content[i][1][1].fgcolor = 0.0
|
||||||
else
|
else
|
||||||
self.toggle_content[i].color = self.bgcolor
|
self.toggle_content[i].color = self.bgcolor
|
||||||
self.toggle_content[i].background = self.bgcolor
|
self.toggle_content[i].background = self.bgcolor
|
||||||
self.toggle_content[i][1][1].bgcolor = 0.0
|
self.toggle_content[i][1][1].bgcolor = 0.0
|
||||||
self.toggle_content[i][1][1].fgcolor = 1.0
|
self.toggle_content[i][1][1].fgcolor = 1.0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ToggleSwitch:setPosition(position)
|
function ToggleSwitch:setPosition(position)
|
||||||
self.position = position
|
self.position = position
|
||||||
self:update()
|
self:update()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ToggleSwitch:togglePosition(position)
|
function ToggleSwitch:togglePosition(position)
|
||||||
if self.n_pos == 2 and self.alternate ~= false then
|
if self.n_pos == 2 and self.alternate ~= false then
|
||||||
self.position = (self.position+1)%self.n_pos
|
self.position = (self.position+1)%self.n_pos
|
||||||
self.position = self.position == 0 and self.n_pos or self.position
|
self.position = self.position == 0 and self.n_pos or self.position
|
||||||
elseif self.n_pos == 1 then
|
elseif self.n_pos == 1 then
|
||||||
self.position = self.position == 1 and 0 or 1
|
self.position = self.position == 1 and 0 or 1
|
||||||
else
|
else
|
||||||
self.position = position
|
self.position = position
|
||||||
end
|
end
|
||||||
self:update()
|
self:update()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ToggleSwitch:onTapSelect(arg, gev)
|
function ToggleSwitch:onTapSelect(arg, gev)
|
||||||
local position = math.ceil(
|
local position = math.ceil(
|
||||||
(gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos
|
(gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos
|
||||||
)
|
)
|
||||||
--DEBUG("toggle position:", position)
|
--DEBUG("toggle position:", position)
|
||||||
self:togglePosition(position)
|
self:togglePosition(position)
|
||||||
--[[
|
--[[
|
||||||
if self.values then
|
if self.values then
|
||||||
self.values = self.values or {}
|
self.values = self.values or {}
|
||||||
self.config:onConfigChoice(self.name, self.values[self.position])
|
self.config:onConfigChoice(self.name, self.values[self.position])
|
||||||
end
|
end
|
||||||
if self.event then
|
if self.event then
|
||||||
self.args = self.args or {}
|
self.args = self.args or {}
|
||||||
self.config:onConfigEvent(self.event, self.args[self.position])
|
self.config:onConfigEvent(self.event, self.args[self.position])
|
||||||
end
|
end
|
||||||
if self.events then
|
if self.events then
|
||||||
self.config:onConfigEvents(self.events, self.position)
|
self.config:onConfigEvents(self.events, self.position)
|
||||||
end
|
end
|
||||||
--]]
|
--]]
|
||||||
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.position)
|
self.config:onConfigChoose(self.values, self.name, self.event, self.args, self.events, self.position)
|
||||||
UIManager:setDirty(self.config, "partial")
|
UIManager:setDirty(self.config, "partial")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ToggleSwitch
|
return ToggleSwitch
|
||||||
|
|||||||
@@ -22,49 +22,49 @@ local _ = require("gettext")
|
|||||||
TouchMenuItem widget
|
TouchMenuItem widget
|
||||||
--]]
|
--]]
|
||||||
local TouchMenuItem = InputContainer:new{
|
local TouchMenuItem = InputContainer:new{
|
||||||
menu = nil,
|
menu = nil,
|
||||||
vertical_align = "center",
|
vertical_align = "center",
|
||||||
item = nil,
|
item = nil,
|
||||||
dimen = nil,
|
dimen = nil,
|
||||||
face = Font:getFace("cfont", 22),
|
face = Font:getFace("cfont", 22),
|
||||||
show_parent = nil,
|
show_parent = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function TouchMenuItem:init()
|
function TouchMenuItem:init()
|
||||||
self.ges_events = {
|
self.ges_events = {
|
||||||
TapSelect = {
|
TapSelect = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
},
|
},
|
||||||
doc = _("Select Menu Item"),
|
doc = _("Select Menu Item"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self.item_frame = FrameContainer:new{
|
self.item_frame = FrameContainer:new{
|
||||||
width = self.dimen.w,
|
width = self.dimen.w,
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
color = 15,
|
color = 15,
|
||||||
HorizontalGroup:new {
|
HorizontalGroup:new {
|
||||||
align = "center",
|
align = "center",
|
||||||
HorizontalSpan:new{ width = 10 },
|
HorizontalSpan:new{ width = 10 },
|
||||||
TextWidget:new{
|
TextWidget:new{
|
||||||
text = self.item.text or self.item.text_func(),
|
text = self.item.text or self.item.text_func(),
|
||||||
face = self.face,
|
face = self.face,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
self[1] = self.item_frame
|
self[1] = self.item_frame
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenuItem:onTapSelect(arg, ges)
|
function TouchMenuItem:onTapSelect(arg, ges)
|
||||||
self.item_frame.invert = true
|
self.item_frame.invert = true
|
||||||
UIManager:setDirty(self.show_parent, "partial")
|
UIManager:setDirty(self.show_parent, "partial")
|
||||||
UIManager:scheduleIn(0.5, function()
|
UIManager:scheduleIn(0.5, function()
|
||||||
self.item_frame.invert = false
|
self.item_frame.invert = false
|
||||||
UIManager:setDirty(self.show_parent, "partial")
|
UIManager:setDirty(self.show_parent, "partial")
|
||||||
end)
|
end)
|
||||||
self.menu:onMenuSelect(self.item)
|
self.menu:onMenuSelect(self.item)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -72,97 +72,97 @@ end
|
|||||||
TouchMenuBar widget
|
TouchMenuBar widget
|
||||||
--]]
|
--]]
|
||||||
local TouchMenuBar = InputContainer:new{
|
local TouchMenuBar = InputContainer:new{
|
||||||
height = Screen:scaleByDPI(70),
|
height = Screen:scaleByDPI(70),
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
icons = {},
|
icons = {},
|
||||||
-- touch menu that holds the bar, used for trigger repaint on icons
|
-- touch menu that holds the bar, used for trigger repaint on icons
|
||||||
show_parent = nil,
|
show_parent = nil,
|
||||||
menu = nil,
|
menu = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function TouchMenuBar:init()
|
function TouchMenuBar:init()
|
||||||
self.show_parent = self.show_parent or self
|
self.show_parent = self.show_parent or self
|
||||||
|
|
||||||
self.dimen = Geom:new{
|
self.dimen = Geom:new{
|
||||||
w = self.width,
|
w = self.width,
|
||||||
h = self.height,
|
h = self.height,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.bar_icon_group = HorizontalGroup:new{}
|
self.bar_icon_group = HorizontalGroup:new{}
|
||||||
|
|
||||||
local icon_sep = LineWidget:new{
|
local icon_sep = LineWidget:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = Screen:scaleByDPI(2),
|
w = Screen:scaleByDPI(2),
|
||||||
h = self.height,
|
h = self.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local icon_span = HorizontalSpan:new{ width = Screen:scaleByDPI(20) }
|
local icon_span = HorizontalSpan:new{ width = Screen:scaleByDPI(20) }
|
||||||
|
|
||||||
-- build up image widget for menu icon bar
|
-- build up image widget for menu icon bar
|
||||||
self.icon_widgets = {}
|
self.icon_widgets = {}
|
||||||
-- the start_seg for first icon_widget should be 0
|
-- the start_seg for first icon_widget should be 0
|
||||||
-- we asign negative here to offset it in the loop
|
-- we asign negative here to offset it in the loop
|
||||||
start_seg = -icon_sep:getSize().w
|
start_seg = -icon_sep:getSize().w
|
||||||
end_seg = start_seg
|
end_seg = start_seg
|
||||||
for k, v in ipairs(self.icons) do
|
for k, v in ipairs(self.icons) do
|
||||||
local ib = IconButton:new{
|
local ib = IconButton:new{
|
||||||
show_parent = self.show_parent,
|
show_parent = self.show_parent,
|
||||||
icon_file = v,
|
icon_file = v,
|
||||||
callback = nil,
|
callback = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
table.insert(self.icon_widgets, HorizontalGroup:new{
|
table.insert(self.icon_widgets, HorizontalGroup:new{
|
||||||
icon_span,
|
icon_span,
|
||||||
ib,
|
ib,
|
||||||
icon_span,
|
icon_span,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- we have to use local variable here for closure callback
|
-- we have to use local variable here for closure callback
|
||||||
local _start_seg = end_seg + icon_sep:getSize().w
|
local _start_seg = end_seg + icon_sep:getSize().w
|
||||||
local _end_seg = _start_seg + self.icon_widgets[k]:getSize().w
|
local _end_seg = _start_seg + self.icon_widgets[k]:getSize().w
|
||||||
|
|
||||||
if k == 1 then
|
if k == 1 then
|
||||||
self.bar_sep = LineWidget:new{
|
self.bar_sep = LineWidget:new{
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = self.width,
|
w = self.width,
|
||||||
h = Screen:scaleByDPI(2),
|
h = Screen:scaleByDPI(2),
|
||||||
},
|
},
|
||||||
empty_segments = {
|
empty_segments = {
|
||||||
{
|
{
|
||||||
s = _start_seg, e = _end_seg
|
s = _start_seg, e = _end_seg
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
ib.callback = function()
|
ib.callback = function()
|
||||||
self.bar_sep.empty_segments = {
|
self.bar_sep.empty_segments = {
|
||||||
{
|
{
|
||||||
s = _start_seg, e = _end_seg
|
s = _start_seg, e = _end_seg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.menu:switchMenuTab(k)
|
self.menu:switchMenuTab(k)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.bar_icon_group, self.icon_widgets[k])
|
table.insert(self.bar_icon_group, self.icon_widgets[k])
|
||||||
table.insert(self.bar_icon_group, icon_sep)
|
table.insert(self.bar_icon_group, icon_sep)
|
||||||
|
|
||||||
start_seg = _start_seg
|
start_seg = _start_seg
|
||||||
end_seg = _end_seg
|
end_seg = _end_seg
|
||||||
end
|
end
|
||||||
|
|
||||||
self[1] = FrameContainer:new{
|
self[1] = FrameContainer:new{
|
||||||
bordersize = 0,
|
bordersize = 0,
|
||||||
padding = 0,
|
padding = 0,
|
||||||
VerticalGroup:new{
|
VerticalGroup:new{
|
||||||
align = "left",
|
align = "left",
|
||||||
-- bar icons
|
-- bar icons
|
||||||
self.bar_icon_group,
|
self.bar_icon_group,
|
||||||
-- separate line
|
-- separate line
|
||||||
self.bar_sep
|
self.bar_sep
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -170,258 +170,258 @@ end
|
|||||||
TouchMenu widget
|
TouchMenu widget
|
||||||
--]]
|
--]]
|
||||||
local TouchMenu = InputContainer:new{
|
local TouchMenu = InputContainer:new{
|
||||||
tab_item_table = {},
|
tab_item_table = {},
|
||||||
-- for returnning in multi-level menus
|
-- for returnning in multi-level menus
|
||||||
item_table_stack = nil,
|
item_table_stack = nil,
|
||||||
item_table = nil,
|
item_table = nil,
|
||||||
item_height = Screen:scaleByDPI(50),
|
item_height = Screen:scaleByDPI(50),
|
||||||
bordersize = Screen:scaleByDPI(2),
|
bordersize = Screen:scaleByDPI(2),
|
||||||
padding = Screen:scaleByDPI(5),
|
padding = Screen:scaleByDPI(5),
|
||||||
footer_height = Screen:scaleByDPI(50),
|
footer_height = Screen:scaleByDPI(50),
|
||||||
width = nil,
|
width = nil,
|
||||||
height = nil,
|
height = nil,
|
||||||
page = 1,
|
page = 1,
|
||||||
max_per_page = 10,
|
max_per_page = 10,
|
||||||
-- for UIManager:setDirty
|
-- for UIManager:setDirty
|
||||||
show_parent = nil,
|
show_parent = nil,
|
||||||
cur_tab = -1,
|
cur_tab = -1,
|
||||||
close_callback = nil,
|
close_callback = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function TouchMenu:init()
|
function TouchMenu:init()
|
||||||
self.show_parent = self.show_parent or self
|
self.show_parent = self.show_parent or self
|
||||||
if not self.close_callback then
|
if not self.close_callback then
|
||||||
self.close_callback = function()
|
self.close_callback = function()
|
||||||
UIManager:close(self.show_parent)
|
UIManager:close(self.show_parent)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.ges_events.TapCloseAllMenus = {
|
self.ges_events.TapCloseAllMenus = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "tap",
|
ges = "tap",
|
||||||
range = Geom:new{
|
range = Geom:new{
|
||||||
x = 0, y = 0,
|
x = 0, y = 0,
|
||||||
w = Screen:getWidth(),
|
w = Screen:getWidth(),
|
||||||
h = Screen:getHeight(),
|
h = Screen:getHeight(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ges_events.Swipe = {
|
self.ges_events.Swipe = {
|
||||||
GestureRange:new{
|
GestureRange:new{
|
||||||
ges = "swipe",
|
ges = "swipe",
|
||||||
range = self.dimen,
|
range = self.dimen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local icons = {}
|
local icons = {}
|
||||||
for _,v in ipairs(self.tab_item_table) do
|
for _,v in ipairs(self.tab_item_table) do
|
||||||
table.insert(icons, v.icon)
|
table.insert(icons, v.icon)
|
||||||
end
|
end
|
||||||
self.bar = TouchMenuBar:new{
|
self.bar = TouchMenuBar:new{
|
||||||
width = self.width - self.padding * 2 - self.bordersize * 2,
|
width = self.width - self.padding * 2 - self.bordersize * 2,
|
||||||
icons = icons,
|
icons = icons,
|
||||||
show_parent = self.show_parent,
|
show_parent = self.show_parent,
|
||||||
menu = self,
|
menu = self,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.item_group = VerticalGroup:new{
|
self.item_group = VerticalGroup:new{
|
||||||
align = "left",
|
align = "left",
|
||||||
}
|
}
|
||||||
|
|
||||||
self.footer_page = TextWidget:new{
|
self.footer_page = TextWidget:new{
|
||||||
face = Font:getFace("ffont", 20),
|
face = Font:getFace("ffont", 20),
|
||||||
text = "",
|
text = "",
|
||||||
}
|
}
|
||||||
self.time_info = TextWidget:new{
|
self.time_info = TextWidget:new{
|
||||||
face = Font:getFace("ffont", 20),
|
face = Font:getFace("ffont", 20),
|
||||||
text = "",
|
text = "",
|
||||||
}
|
}
|
||||||
local footer_width = self.width - self.padding*2 - self.bordersize*2
|
local footer_width = self.width - self.padding*2 - self.bordersize*2
|
||||||
self.footer = HorizontalGroup:new{
|
self.footer = HorizontalGroup:new{
|
||||||
LeftContainer:new{
|
LeftContainer:new{
|
||||||
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
||||||
IconButton:new{
|
IconButton:new{
|
||||||
invert = true,
|
invert = true,
|
||||||
icon_file = "resources/icons/appbar.chevron.up.png",
|
icon_file = "resources/icons/appbar.chevron.up.png",
|
||||||
show_parent = self.show_parent,
|
show_parent = self.show_parent,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:backToUpperMenu()
|
self:backToUpperMenu()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CenterContainer:new{
|
CenterContainer:new{
|
||||||
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
||||||
self.footer_page,
|
self.footer_page,
|
||||||
},
|
},
|
||||||
RightContainer:new{
|
RightContainer:new{
|
||||||
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
dimen = Geom:new{ w = footer_width*0.33, h = self.footer_height},
|
||||||
self.time_info,
|
self.time_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self[1] = FrameContainer:new{
|
self[1] = FrameContainer:new{
|
||||||
padding = self.padding,
|
padding = self.padding,
|
||||||
bordersize = self.bordersize,
|
bordersize = self.bordersize,
|
||||||
background = 0,
|
background = 0,
|
||||||
-- menubar and footer will be inserted in
|
-- menubar and footer will be inserted in
|
||||||
-- item_group in updateItems
|
-- item_group in updateItems
|
||||||
self.item_group,
|
self.item_group,
|
||||||
}
|
}
|
||||||
|
|
||||||
self:switchMenuTab(1)
|
self:switchMenuTab(1)
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:_recalculateDimen()
|
function TouchMenu:_recalculateDimen()
|
||||||
self.dimen.w = self.width
|
self.dimen.w = self.width
|
||||||
|
|
||||||
-- if height not given, dynamically calculate it
|
-- if height not given, dynamically calculate it
|
||||||
if not self.height then
|
if not self.height then
|
||||||
self.dimen.h = (#self.item_table + 2) * self.item_height
|
self.dimen.h = (#self.item_table + 2) * self.item_height
|
||||||
+ self.bar:getSize().h
|
+ self.bar:getSize().h
|
||||||
else
|
else
|
||||||
self.dimen.h = self.height
|
self.dimen.h = self.height
|
||||||
end
|
end
|
||||||
-- make sure self.dimen.h does not overflow screen height
|
-- make sure self.dimen.h does not overflow screen height
|
||||||
if self.dimen.h > Screen:getHeight() then
|
if self.dimen.h > Screen:getHeight() then
|
||||||
self.dimen.h = Screen:getHeight() - self.bar:getSize().h
|
self.dimen.h = Screen:getHeight() - self.bar:getSize().h
|
||||||
end
|
end
|
||||||
|
|
||||||
self.perpage = math.floor(self.dimen.h / self.item_height) - 2
|
self.perpage = math.floor(self.dimen.h / self.item_height) - 2
|
||||||
if self.perpage > self.max_per_page then
|
if self.perpage > self.max_per_page then
|
||||||
self.perpage = self.max_per_page
|
self.perpage = self.max_per_page
|
||||||
end
|
end
|
||||||
|
|
||||||
self.page_num = math.ceil(#self.item_table / self.perpage)
|
self.page_num = math.ceil(#self.item_table / self.perpage)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:updateItems()
|
function TouchMenu:updateItems()
|
||||||
self:_recalculateDimen()
|
self:_recalculateDimen()
|
||||||
self.item_group:clear()
|
self.item_group:clear()
|
||||||
table.insert(self.item_group, self.bar)
|
table.insert(self.item_group, self.bar)
|
||||||
|
|
||||||
local item_width = self.dimen.w - self.padding*2 - self.bordersize*2
|
local item_width = self.dimen.w - self.padding*2 - self.bordersize*2
|
||||||
|
|
||||||
for c = 1, self.perpage do
|
for c = 1, self.perpage do
|
||||||
-- calculate index in item_table
|
-- calculate index in item_table
|
||||||
local i = (self.page - 1) * self.perpage + c
|
local i = (self.page - 1) * self.perpage + c
|
||||||
if i <= #self.item_table then
|
if i <= #self.item_table then
|
||||||
local item_tmp = TouchMenuItem:new{
|
local item_tmp = TouchMenuItem:new{
|
||||||
item = self.item_table[i],
|
item = self.item_table[i],
|
||||||
menu = self,
|
menu = self,
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = item_width,
|
w = item_width,
|
||||||
h = self.item_height,
|
h = self.item_height,
|
||||||
},
|
},
|
||||||
show_parent = self.show_parent,
|
show_parent = self.show_parent,
|
||||||
}
|
}
|
||||||
table.insert(self.item_group, item_tmp)
|
table.insert(self.item_group, item_tmp)
|
||||||
-- insert split line
|
-- insert split line
|
||||||
if c ~= self.perpage then
|
if c ~= self.perpage then
|
||||||
table.insert(self.item_group, HorizontalGroup:new{
|
table.insert(self.item_group, HorizontalGroup:new{
|
||||||
-- pad with 10 pixel to align with the up arrow in footer
|
-- pad with 10 pixel to align with the up arrow in footer
|
||||||
HorizontalSpan:new{width = 10},
|
HorizontalSpan:new{width = 10},
|
||||||
LineWidget:new{
|
LineWidget:new{
|
||||||
style = "dashed",
|
style = "dashed",
|
||||||
dimen = Geom:new{
|
dimen = Geom:new{
|
||||||
w = item_width - 20,
|
w = item_width - 20,
|
||||||
h = 1,
|
h = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- item not enough to fill the whole page, break out of loop
|
-- item not enough to fill the whole page, break out of loop
|
||||||
--table.insert(self.item_group,
|
--table.insert(self.item_group,
|
||||||
--VerticalSpan:new{
|
--VerticalSpan:new{
|
||||||
--width = self.item_height
|
--width = self.item_height
|
||||||
--})
|
--})
|
||||||
--break
|
--break
|
||||||
end -- if i <= self.items
|
end -- if i <= self.items
|
||||||
end -- for c=1, self.perpage
|
end -- for c=1, self.perpage
|
||||||
|
|
||||||
table.insert(self.item_group, VerticalSpan:new{width = Screen:scaleByDPI(2)})
|
table.insert(self.item_group, VerticalSpan:new{width = Screen:scaleByDPI(2)})
|
||||||
table.insert(self.item_group, self.footer)
|
table.insert(self.item_group, self.footer)
|
||||||
self.footer_page.text = _("Page ")..self.page.."/"..self.page_num
|
self.footer_page.text = _("Page ")..self.page.."/"..self.page_num
|
||||||
self.time_info.text = os.date("%H:%M")
|
self.time_info.text = os.date("%H:%M")
|
||||||
-- FIXME: this is a dirty hack to clear previous menus
|
-- FIXME: this is a dirty hack to clear previous menus
|
||||||
-- refert to issue #664
|
-- refert to issue #664
|
||||||
UIManager.repaint_all = true
|
UIManager.repaint_all = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:switchMenuTab(tab_num)
|
function TouchMenu:switchMenuTab(tab_num)
|
||||||
if self.tab_item_table[tab_num].callback then
|
if self.tab_item_table[tab_num].callback then
|
||||||
self.tab_item_table[tab_num].callback()
|
self.tab_item_table[tab_num].callback()
|
||||||
end
|
end
|
||||||
if self.cur_tab ~= tab_num then
|
if self.cur_tab ~= tab_num then
|
||||||
-- it's like getting a new menu everytime we switch tab!
|
-- it's like getting a new menu everytime we switch tab!
|
||||||
self.page = 1
|
self.page = 1
|
||||||
-- clear item table stack
|
-- clear item table stack
|
||||||
self.item_table_stack = {}
|
self.item_table_stack = {}
|
||||||
self.cur_tab = tab_num
|
self.cur_tab = tab_num
|
||||||
self.item_table = self.tab_item_table[tab_num]
|
self.item_table = self.tab_item_table[tab_num]
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:backToUpperMenu()
|
function TouchMenu:backToUpperMenu()
|
||||||
if #self.item_table_stack ~= 0 then
|
if #self.item_table_stack ~= 0 then
|
||||||
self.item_table = table.remove(self.item_table_stack)
|
self.item_table = table.remove(self.item_table_stack)
|
||||||
self.page = 1
|
self.page = 1
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:closeMenu()
|
function TouchMenu:closeMenu()
|
||||||
self.close_callback()
|
self.close_callback()
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:onNextPage()
|
function TouchMenu:onNextPage()
|
||||||
if self.page < self.page_num then
|
if self.page < self.page_num then
|
||||||
self.page = self.page + 1
|
self.page = self.page + 1
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:onPrevPage()
|
function TouchMenu:onPrevPage()
|
||||||
if self.page > 1 then
|
if self.page > 1 then
|
||||||
self.page = self.page - 1
|
self.page = self.page - 1
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:onSwipe(arg, ges_ev)
|
function TouchMenu:onSwipe(arg, ges_ev)
|
||||||
if ges_ev.direction == "west" or ges_ev.direction == "north" then
|
if ges_ev.direction == "west" or ges_ev.direction == "north" then
|
||||||
self:onNextPage()
|
self:onNextPage()
|
||||||
elseif ges_ev.direction == "east" or ges_ev.direction == "south" then
|
elseif ges_ev.direction == "east" or ges_ev.direction == "south" then
|
||||||
self:onPrevPage()
|
self:onPrevPage()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:onMenuSelect(item)
|
function TouchMenu:onMenuSelect(item)
|
||||||
if item.sub_item_table == nil then
|
if item.sub_item_table == nil then
|
||||||
if item.callback then
|
if item.callback then
|
||||||
-- put stuff in scheduler so we can See
|
-- put stuff in scheduler so we can See
|
||||||
-- the effect of inverted menu item
|
-- the effect of inverted menu item
|
||||||
UIManager:scheduleIn(0.1, function()
|
UIManager:scheduleIn(0.1, function()
|
||||||
self:closeMenu()
|
self:closeMenu()
|
||||||
item.callback()
|
item.callback()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
table.insert(self.item_table_stack, self.item_table)
|
table.insert(self.item_table_stack, self.item_table)
|
||||||
self.item_table = item.sub_item_table
|
self.item_table = item.sub_item_table
|
||||||
self:updateItems()
|
self:updateItems()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function TouchMenu:onTapCloseAllMenus(arg, ges_ev)
|
function TouchMenu:onTapCloseAllMenus(arg, ges_ev)
|
||||||
if ges_ev.pos:notIntersectWith(self.dimen) then
|
if ges_ev.pos:notIntersectWith(self.dimen) then
|
||||||
self:closeMenu()
|
self:closeMenu()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return TouchMenu
|
return TouchMenu
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user