|
|
@ -10,6 +10,7 @@ Displays some text in a scrollable view.
|
|
|
|
]]
|
|
|
|
]]
|
|
|
|
local BD = require("ui/bidi")
|
|
|
|
local BD = require("ui/bidi")
|
|
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
|
|
|
|
|
|
local ButtonDialog = require("ui/widget/buttondialog")
|
|
|
|
local ButtonTable = require("ui/widget/buttontable")
|
|
|
|
local ButtonTable = require("ui/widget/buttontable")
|
|
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
|
|
local CheckButton = require("ui/widget/checkbutton")
|
|
|
|
local CheckButton = require("ui/widget/checkbutton")
|
|
|
@ -47,7 +48,6 @@ local TextViewer = InputContainer:extend{
|
|
|
|
-- When used to display more technical text (HTML, CSS,
|
|
|
|
-- When used to display more technical text (HTML, CSS,
|
|
|
|
-- application logs...), it's best to reset them to false.
|
|
|
|
-- application logs...), it's best to reset them to false.
|
|
|
|
alignment = "left",
|
|
|
|
alignment = "left",
|
|
|
|
justified = nil,
|
|
|
|
|
|
|
|
lang = nil,
|
|
|
|
lang = nil,
|
|
|
|
para_direction_rtl = nil,
|
|
|
|
para_direction_rtl = nil,
|
|
|
|
auto_para_direction = true,
|
|
|
|
auto_para_direction = true,
|
|
|
@ -57,8 +57,11 @@ local TextViewer = InputContainer:extend{
|
|
|
|
title_multilines = nil, -- see TitleBar for details
|
|
|
|
title_multilines = nil, -- see TitleBar for details
|
|
|
|
title_shrink_font_to_fit = nil, -- see TitleBar for details
|
|
|
|
title_shrink_font_to_fit = nil, -- see TitleBar for details
|
|
|
|
|
|
|
|
|
|
|
|
text_font_face = nil, -- default "x_smallinfofont"
|
|
|
|
show_menu = true, -- titlebar left icon
|
|
|
|
text_font_size = nil,
|
|
|
|
monospace_font = nil, -- internal
|
|
|
|
|
|
|
|
text_font_size = nil, -- internal
|
|
|
|
|
|
|
|
justified = nil, -- internal
|
|
|
|
|
|
|
|
|
|
|
|
fgcolor = Blitbuffer.COLOR_BLACK,
|
|
|
|
fgcolor = Blitbuffer.COLOR_BLACK,
|
|
|
|
text_padding = Size.padding.large,
|
|
|
|
text_padding = Size.padding.large,
|
|
|
|
text_margin = Size.margin.small,
|
|
|
|
text_margin = Size.margin.small,
|
|
|
@ -67,28 +70,38 @@ local TextViewer = InputContainer:extend{
|
|
|
|
add_default_buttons = nil,
|
|
|
|
add_default_buttons = nil,
|
|
|
|
default_hold_callback = nil, -- on each default button
|
|
|
|
default_hold_callback = nil, -- on each default button
|
|
|
|
find_centered_lines_count = 5, -- line with find results to be not far from the center
|
|
|
|
find_centered_lines_count = 5, -- line with find results to be not far from the center
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
text_type = "general",
|
|
|
|
|
|
|
|
text_types = {
|
|
|
|
|
|
|
|
general = { monospace_font = false, font_size = 20, justified = false },
|
|
|
|
|
|
|
|
file_content = { monospace_font = false, font_size = 20, justified = false },
|
|
|
|
|
|
|
|
book_info = { monospace_font = false, font_size = 20, justified = true },
|
|
|
|
|
|
|
|
bookmark = { monospace_font = false, font_size = 20, justified = true },
|
|
|
|
|
|
|
|
lookup = { monospace_font = false, font_size = 20, justified = false },
|
|
|
|
|
|
|
|
code = { monospace_font = true, font_size = 16, justified = false },
|
|
|
|
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function TextViewer:init()
|
|
|
|
function TextViewer:init(reinit)
|
|
|
|
-- calculate window dimension
|
|
|
|
local screen_w = Screen:getWidth()
|
|
|
|
|
|
|
|
local screen_h = Screen:getHeight()
|
|
|
|
|
|
|
|
|
|
|
|
self.align = "center"
|
|
|
|
self.align = "center"
|
|
|
|
self.region = Geom:new{
|
|
|
|
self.region = Geom:new{
|
|
|
|
x = 0, y = 0,
|
|
|
|
w = screen_w,
|
|
|
|
w = Screen:getWidth(),
|
|
|
|
h = screen_h,
|
|
|
|
h = Screen:getHeight(),
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.width = self.width or Screen:getWidth() - Screen:scaleBySize(30)
|
|
|
|
self.width = self.width or screen_w - Screen:scaleBySize(30)
|
|
|
|
self.height = self.height or Screen:getHeight() - Screen:scaleBySize(30)
|
|
|
|
self.height = self.height or screen_h - Screen:scaleBySize(30)
|
|
|
|
|
|
|
|
|
|
|
|
if self.justified == nil then
|
|
|
|
if not reinit then
|
|
|
|
self.justified = G_reader_settings:nilOrTrue("dict_justify")
|
|
|
|
local text_types = G_reader_settings:readSetting("textviewer_text_types")
|
|
|
|
end
|
|
|
|
local text_settings = text_types and text_types[self.text_type] or self.text_types[self.text_type]
|
|
|
|
if self.text_font_face == nil then
|
|
|
|
self.monospace_font = text_settings.monospace_font
|
|
|
|
self.text_font_face = "x_smallinfofont"
|
|
|
|
self.text_font_size = text_settings.font_size
|
|
|
|
if self.text_font_size == nil then
|
|
|
|
self.justified = text_settings.justified
|
|
|
|
self.text_font_size = G_reader_settings:readSetting("dict_font_size")
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local text_font_face = self.monospace_font and "smallinfont" or "x_smallinfofont"
|
|
|
|
|
|
|
|
|
|
|
|
self._find_next = false
|
|
|
|
self._find_next = false
|
|
|
|
self._find_next_button = false
|
|
|
|
self._find_next_button = false
|
|
|
@ -100,9 +113,8 @@ function TextViewer:init()
|
|
|
|
|
|
|
|
|
|
|
|
if Device:isTouchDevice() then
|
|
|
|
if Device:isTouchDevice() then
|
|
|
|
local range = Geom:new{
|
|
|
|
local range = Geom:new{
|
|
|
|
x = 0, y = 0,
|
|
|
|
w = screen_w,
|
|
|
|
w = Screen:getWidth(),
|
|
|
|
h = screen_h,
|
|
|
|
h = Screen:getHeight(),
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.ges_events = {
|
|
|
|
self.ges_events = {
|
|
|
|
TapClose = {
|
|
|
|
TapClose = {
|
|
|
@ -153,7 +165,7 @@ function TextViewer:init()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local titlebar = TitleBar:new{
|
|
|
|
self.titlebar = TitleBar:new{
|
|
|
|
width = self.width,
|
|
|
|
width = self.width,
|
|
|
|
align = "left",
|
|
|
|
align = "left",
|
|
|
|
with_bottom_line = true,
|
|
|
|
with_bottom_line = true,
|
|
|
@ -161,6 +173,8 @@ function TextViewer:init()
|
|
|
|
title_face = self.title_face,
|
|
|
|
title_face = self.title_face,
|
|
|
|
title_multilines = self.title_multilines,
|
|
|
|
title_multilines = self.title_multilines,
|
|
|
|
title_shrink_font_to_fit = self.title_shrink_font_to_fit,
|
|
|
|
title_shrink_font_to_fit = self.title_shrink_font_to_fit,
|
|
|
|
|
|
|
|
left_icon = self.show_menu and "appbar.menu",
|
|
|
|
|
|
|
|
left_icon_tap_callback = function() self:showMenu() end,
|
|
|
|
close_callback = function() self:onClose() end,
|
|
|
|
close_callback = function() self:onClose() end,
|
|
|
|
show_parent = self,
|
|
|
|
show_parent = self,
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -246,7 +260,7 @@ function TextViewer:init()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
local buttons = self.buttons_table or {}
|
|
|
|
local buttons = self.buttons_table or {}
|
|
|
|
if self.add_default_buttons or not self.buttons_table then
|
|
|
|
if (self.add_default_buttons and not reinit) or not self.buttons_table then
|
|
|
|
table.insert(buttons, default_buttons)
|
|
|
|
table.insert(buttons, default_buttons)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self.button_table = ButtonTable:new{
|
|
|
|
self.button_table = ButtonTable:new{
|
|
|
@ -256,11 +270,11 @@ function TextViewer:init()
|
|
|
|
show_parent = self,
|
|
|
|
show_parent = self,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
local textw_height = self.height - titlebar:getHeight() - self.button_table:getSize().h
|
|
|
|
local textw_height = self.height - self.titlebar:getHeight() - self.button_table:getSize().h
|
|
|
|
|
|
|
|
|
|
|
|
self.scroll_text_w = ScrollTextWidget:new{
|
|
|
|
self.scroll_text_w = ScrollTextWidget:new{
|
|
|
|
text = self.text,
|
|
|
|
text = self.text,
|
|
|
|
face = Font:getFace(self.text_font_face, self.text_font_size),
|
|
|
|
face = Font:getFace(text_font_face, self.text_font_size),
|
|
|
|
fgcolor = self.fgcolor,
|
|
|
|
fgcolor = self.fgcolor,
|
|
|
|
width = self.width - 2*self.text_padding - 2*self.text_margin,
|
|
|
|
width = self.width - 2*self.text_padding - 2*self.text_margin,
|
|
|
|
height = textw_height - 2*self.text_padding -2*self.text_margin,
|
|
|
|
height = textw_height - 2*self.text_padding -2*self.text_margin,
|
|
|
@ -286,7 +300,7 @@ function TextViewer:init()
|
|
|
|
margin = 0,
|
|
|
|
margin = 0,
|
|
|
|
background = Blitbuffer.COLOR_WHITE,
|
|
|
|
background = Blitbuffer.COLOR_WHITE,
|
|
|
|
VerticalGroup:new{
|
|
|
|
VerticalGroup:new{
|
|
|
|
titlebar,
|
|
|
|
self.titlebar,
|
|
|
|
CenterContainer:new{
|
|
|
|
CenterContainer:new{
|
|
|
|
dimen = Geom:new{
|
|
|
|
dimen = Geom:new{
|
|
|
|
w = self.width,
|
|
|
|
w = self.width,
|
|
|
@ -433,7 +447,7 @@ function TextViewer:onForwardingPanRelease(arg, ges)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function TextViewer:findDialog()
|
|
|
|
function TextViewer:findDialog()
|
|
|
|
local input_dialog
|
|
|
|
local input_dialog, check_button_case
|
|
|
|
input_dialog = InputDialog:new{
|
|
|
|
input_dialog = InputDialog:new{
|
|
|
|
title = _("Enter text to search for"),
|
|
|
|
title = _("Enter text to search for"),
|
|
|
|
input = self.search_value,
|
|
|
|
input = self.search_value,
|
|
|
@ -464,15 +478,15 @@ function TextViewer:findDialog()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.check_button_case = CheckButton:new{
|
|
|
|
check_button_case = CheckButton:new{
|
|
|
|
text = _("Case sensitive"),
|
|
|
|
text = _("Case sensitive"),
|
|
|
|
checked = self.case_sensitive,
|
|
|
|
checked = self.case_sensitive,
|
|
|
|
parent = input_dialog,
|
|
|
|
parent = input_dialog,
|
|
|
|
callback = function()
|
|
|
|
callback = function()
|
|
|
|
self.case_sensitive = self.check_button_case.checked
|
|
|
|
self.case_sensitive = check_button_case.checked
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
input_dialog:addWidget(self.check_button_case)
|
|
|
|
input_dialog:addWidget(check_button_case)
|
|
|
|
|
|
|
|
|
|
|
|
UIManager:show(input_dialog)
|
|
|
|
UIManager:show(input_dialog)
|
|
|
|
input_dialog:onShowKeyboard(true)
|
|
|
|
input_dialog:onShowKeyboard(true)
|
|
|
@ -531,6 +545,75 @@ function TextViewer:handleTextSelection(text, hold_duration, start_idx, end_idx,
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TextViewer:reinit()
|
|
|
|
|
|
|
|
local text_settings = G_reader_settings:readSetting("textviewer_text_types", {})
|
|
|
|
|
|
|
|
text_settings[self.text_type] = { monospace_font = self.monospace_font, font_size = self.text_font_size, justified = self.justified }
|
|
|
|
|
|
|
|
local low, high = self.scroll_text_w.text_widget:getVisibleHeightRatios() -- try to keep position
|
|
|
|
|
|
|
|
local ratio = low == 0 and 0 or (low + high) / 2 -- if we are at the beginning, keep the first line visible
|
|
|
|
|
|
|
|
self:init(true) -- do not add default buttons once more
|
|
|
|
|
|
|
|
UIManager:setDirty("all", "partial", self.frame.dimen)
|
|
|
|
|
|
|
|
self.scroll_text_w:scrollToRatio(ratio, ratio == 0)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TextViewer:showMenu()
|
|
|
|
|
|
|
|
local dialog
|
|
|
|
|
|
|
|
local buttons = {
|
|
|
|
|
|
|
|
{{
|
|
|
|
|
|
|
|
text_func = function()
|
|
|
|
|
|
|
|
return T(_("Font size: %1"), self.text_font_size)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
align = "left",
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
UIManager:close(dialog)
|
|
|
|
|
|
|
|
local SpinWidget = require("ui/widget/spinwidget")
|
|
|
|
|
|
|
|
local widget = SpinWidget:new{
|
|
|
|
|
|
|
|
title_text = _("Font size"),
|
|
|
|
|
|
|
|
value = self.text_font_size,
|
|
|
|
|
|
|
|
value_min = 12,
|
|
|
|
|
|
|
|
value_max = 30,
|
|
|
|
|
|
|
|
default_value = self.monospace_font and 16 or 20,
|
|
|
|
|
|
|
|
keep_shown_on_apply = true,
|
|
|
|
|
|
|
|
callback = function(spin)
|
|
|
|
|
|
|
|
self.text_font_size = spin.value
|
|
|
|
|
|
|
|
self:reinit()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:show(widget)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}},
|
|
|
|
|
|
|
|
{{
|
|
|
|
|
|
|
|
text = _("Monospace font"),
|
|
|
|
|
|
|
|
checked_func = function()
|
|
|
|
|
|
|
|
return self.monospace_font
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
align = "left",
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self.monospace_font = not self.monospace_font
|
|
|
|
|
|
|
|
self:reinit()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}},
|
|
|
|
|
|
|
|
{{
|
|
|
|
|
|
|
|
text = _("Justify"),
|
|
|
|
|
|
|
|
checked_func = function()
|
|
|
|
|
|
|
|
return self.justified
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
align = "left",
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self.justified = not self.justified
|
|
|
|
|
|
|
|
self:reinit()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}},
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
dialog = ButtonDialog:new{
|
|
|
|
|
|
|
|
shrink_unneeded_width = true,
|
|
|
|
|
|
|
|
buttons = buttons,
|
|
|
|
|
|
|
|
anchor = function()
|
|
|
|
|
|
|
|
return self.titlebar.left_button.image.dimen
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:show(dialog)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- Register DocumentRegistry auxiliary provider.
|
|
|
|
-- Register DocumentRegistry auxiliary provider.
|
|
|
|
function TextViewer:register(registry)
|
|
|
|
function TextViewer:register(registry)
|
|
|
|
registry:addAuxProvider({
|
|
|
|
registry:addAuxProvider({
|
|
|
@ -555,8 +638,8 @@ function TextViewer.openFile(file)
|
|
|
|
UIManager:show(TextViewer:new{
|
|
|
|
UIManager:show(TextViewer:new{
|
|
|
|
title = file_path,
|
|
|
|
title = file_path,
|
|
|
|
title_multilines = true,
|
|
|
|
title_multilines = true,
|
|
|
|
justified = false,
|
|
|
|
|
|
|
|
text = file_content,
|
|
|
|
text = file_content,
|
|
|
|
|
|
|
|
text_type = "file_content",
|
|
|
|
})
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local attr = lfs.attributes(file)
|
|
|
|
local attr = lfs.attributes(file)
|
|
|
|