mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #187 from chrox/scroll_text
fix long definition not shown properly in dictionary window
This commit is contained in:
@@ -39,6 +39,7 @@ function ReaderDictionary:showDict(results)
|
||||
results = results,
|
||||
dictionary = self.default_dictionary,
|
||||
width = Screen:getWidth() - scaleByDPI(120),
|
||||
height = Screen:getHeight()*0.43,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -131,7 +131,7 @@ function Screen:getDPI()
|
||||
end
|
||||
|
||||
function Screen:scaleByDPI(px)
|
||||
return (px * self:getDPI()/167)
|
||||
return math.floor(px * self:getDPI()/167)
|
||||
end
|
||||
|
||||
-- make a shortcut to Screen:scaleByDPI
|
||||
|
||||
@@ -14,35 +14,43 @@ DictQuickLookup = InputContainer:new{
|
||||
word_face = Font:getFace("tfont", 20),
|
||||
content_face = Font:getFace("cfont", 20),
|
||||
width = nil,
|
||||
height = nil,
|
||||
|
||||
title_padding = scaleByDPI(5),
|
||||
title_margin = scaleByDPI(2),
|
||||
word_padding = scaleByDPI(5),
|
||||
word_padding = scaleByDPI(2),
|
||||
word_margin = scaleByDPI(2),
|
||||
definition_padding = scaleByDPI(5),
|
||||
definition_padding = scaleByDPI(2),
|
||||
definition_margin = scaleByDPI(2),
|
||||
button_padding = scaleByDPI(14),
|
||||
}
|
||||
|
||||
function DictQuickLookup:init()
|
||||
if Device:hasKeyboard() then
|
||||
key_events = {
|
||||
AnyKeyPressed = { { Input.group.Any },
|
||||
seqtext = "any key", doc = _("close dialog") }
|
||||
}
|
||||
else
|
||||
self.ges_events.TapCloseDict = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
self:changeToDefaultDict()
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapCloseDict = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
},
|
||||
},
|
||||
Swipe = {
|
||||
GestureRange:new{
|
||||
ges = "swipe",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
self:changeToDefaultDict()
|
||||
end
|
||||
|
||||
function DictQuickLookup:update()
|
||||
@@ -73,10 +81,12 @@ function DictQuickLookup:update()
|
||||
padding = self.definition_padding,
|
||||
margin = self.definition_margin,
|
||||
bordersize = 0,
|
||||
TextBoxWidget:new{
|
||||
ScrollTextWidget:new{
|
||||
text = self.definition,
|
||||
face = self.content_face,
|
||||
font_face = self.content_face,
|
||||
width = self.width,
|
||||
height = self.height*0.8,
|
||||
dialog = self,
|
||||
},
|
||||
}
|
||||
local button_table = ButtonTable:new{
|
||||
@@ -138,9 +148,21 @@ function DictQuickLookup:update()
|
||||
self.dict_title,
|
||||
title_bar,
|
||||
-- word
|
||||
lookup_word,
|
||||
CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = title_bar:getSize().w,
|
||||
h = lookup_word:getSize().h,
|
||||
},
|
||||
lookup_word,
|
||||
},
|
||||
-- definition
|
||||
definition,
|
||||
CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = title_bar:getSize().w,
|
||||
h = definition:getSize().h,
|
||||
},
|
||||
definition,
|
||||
},
|
||||
-- buttons
|
||||
CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require "ui/widget/base"
|
||||
require "ui/rendertext"
|
||||
|
||||
require "ui/widget/base"
|
||||
require "ui/widget/scrollbar"
|
||||
|
||||
--[[
|
||||
A TextWidget puts a string on a single line
|
||||
@@ -65,12 +65,25 @@ TextBoxWidget = Widget:new{
|
||||
bgcolor = 0.0, -- [0.0, 1.0]
|
||||
fgcolor = 1.0, -- [0.0, 1.0]
|
||||
width = 400, -- in pixels
|
||||
height = nil,
|
||||
first_line = 1,
|
||||
virtual_line = 1, -- used by scroll bar
|
||||
line_height = 0.3, -- in em
|
||||
v_list = nil,
|
||||
_bb = nil,
|
||||
_length = 0,
|
||||
}
|
||||
|
||||
function TextBoxWidget:init()
|
||||
local v_list = nil
|
||||
if self.height then
|
||||
v_list = self:_getCurrentVerticalList()
|
||||
else
|
||||
v_list = self:_getVerticalList()
|
||||
end
|
||||
self:_render(v_list)
|
||||
end
|
||||
|
||||
function TextBoxWidget:_wrapGreedyAlg(h_list)
|
||||
local cur_line_width = 0
|
||||
local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x
|
||||
@@ -98,10 +111,13 @@ function TextBoxWidget:_wrapGreedyAlg(h_list)
|
||||
end
|
||||
|
||||
function TextBoxWidget:_getVerticalList(alg)
|
||||
if self.vertical_list then
|
||||
return self.vertical_list
|
||||
end
|
||||
-- build horizontal list
|
||||
h_list = {}
|
||||
local h_list = {}
|
||||
for w in self.text:gmatch("[\33-\127\192-\255]+[\128-\191]*") do
|
||||
word_box = {}
|
||||
local word_box = {}
|
||||
word_box.word = w
|
||||
word_box.width = sizeUtf8Text(0, Screen:getWidth(), self.face, w, true).x
|
||||
table.insert(h_list, word_box)
|
||||
@@ -109,12 +125,84 @@ function TextBoxWidget:_getVerticalList(alg)
|
||||
|
||||
-- @TODO check alg here 25.04 2012 (houqp)
|
||||
-- @TODO replace greedy algorithm with K&P algorithm 25.04 2012 (houqp)
|
||||
return self:_wrapGreedyAlg(h_list)
|
||||
self.vertical_list = self:_wrapGreedyAlg(h_list)
|
||||
return self.vertical_list
|
||||
end
|
||||
|
||||
function TextBoxWidget:_render()
|
||||
self.v_list = self:_getVerticalList()
|
||||
local v_list = self.v_list
|
||||
function TextBoxWidget:_getCurrentVerticalList()
|
||||
local line_height = (1 + self.line_height) * self.face.size
|
||||
local v_list = self:_getVerticalList()
|
||||
local current_v_list = {}
|
||||
local height = 0
|
||||
for i = self.first_line, #v_list do
|
||||
if height < self.height - line_height then
|
||||
table.insert(current_v_list, v_list[i])
|
||||
height = height + line_height
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return current_v_list
|
||||
end
|
||||
|
||||
function TextBoxWidget:_getPreviousVerticalList()
|
||||
local line_height = (1 + self.line_height) * self.face.size
|
||||
local v_list = self:_getVerticalList()
|
||||
local previous_v_list = {}
|
||||
local height = 0
|
||||
if self.first_line == 1 then
|
||||
return self:_getCurrentVerticalList()
|
||||
end
|
||||
self.virtual_line = self.first_line
|
||||
for i = self.first_line - 1, 1, -1 do
|
||||
if height < self.height - line_height then
|
||||
table.insert(previous_v_list, 1, v_list[i])
|
||||
height = height + line_height
|
||||
self.virtual_line = self.virtual_line - 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
for i = self.first_line, #v_list do
|
||||
if height < self.height - line_height then
|
||||
table.insert(previous_v_list, v_list[i])
|
||||
height = height + line_height
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if self.first_line > #previous_v_list then
|
||||
self.first_line = self.first_line - #previous_v_list
|
||||
else
|
||||
self.first_line = 1
|
||||
end
|
||||
return previous_v_list
|
||||
end
|
||||
|
||||
function TextBoxWidget:_getNextVerticalList()
|
||||
local line_height = (1 + self.line_height) * self.face.size
|
||||
local v_list = self:_getVerticalList()
|
||||
local current_v_list = self:_getCurrentVerticalList()
|
||||
local next_v_list = {}
|
||||
local height = 0
|
||||
if self.first_line + #current_v_list > #v_list then
|
||||
return current_v_list
|
||||
end
|
||||
self.virtual_line = self.first_line
|
||||
for i = self.first_line + #current_v_list, #v_list do
|
||||
if height < self.height - line_height then
|
||||
table.insert(next_v_list, v_list[i])
|
||||
height = height + line_height
|
||||
self.virtual_line = self.virtual_line + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
self.first_line = self.first_line + #current_v_list
|
||||
return next_v_list
|
||||
end
|
||||
|
||||
function TextBoxWidget:_render(v_list)
|
||||
local font_height = self.face.size
|
||||
local line_height_px = self.line_height * font_height
|
||||
local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x
|
||||
@@ -134,23 +222,47 @@ function TextBoxWidget:_render()
|
||||
end
|
||||
y = y + line_height_px + font_height
|
||||
end
|
||||
-- if text is shorter than one line, shrink to text's width
|
||||
if #v_list == 1 then
|
||||
self.width = pen_x
|
||||
end
|
||||
-- -- if text is shorter than one line, shrink to text's width
|
||||
-- if #v_list == 1 then
|
||||
-- self.width = pen_x
|
||||
-- end
|
||||
end
|
||||
|
||||
function TextBoxWidget:getVirtualLineNum()
|
||||
return self.virtual_line
|
||||
end
|
||||
|
||||
function TextBoxWidget:getAllLineCount()
|
||||
local v_list = self:_getVerticalList()
|
||||
return #v_list
|
||||
end
|
||||
|
||||
function TextBoxWidget:getVisLineCount()
|
||||
local line_height = (1 + self.line_height) * self.face.size
|
||||
return math.floor(self.height / line_height)
|
||||
end
|
||||
|
||||
function TextBoxWidget:scrollDown()
|
||||
local next_v_list = self:_getNextVerticalList()
|
||||
self:free()
|
||||
self:_render(next_v_list)
|
||||
end
|
||||
|
||||
function TextBoxWidget:scrollUp()
|
||||
local previous_v_list = self:_getPreviousVerticalList()
|
||||
self:free()
|
||||
self:_render(previous_v_list)
|
||||
end
|
||||
|
||||
function TextBoxWidget:getSize()
|
||||
if not self._bb then
|
||||
self:_render()
|
||||
if self.width and self.height then
|
||||
return Geom:new{ w = self.width, h = self.height}
|
||||
else
|
||||
return Geom:new{ w = self.width, h = self._bb:getHeight()}
|
||||
end
|
||||
return { w = self.width, h = self._bb:getHeight() }
|
||||
end
|
||||
|
||||
function TextBoxWidget:paintTo(bb, x, y)
|
||||
if not self._bb then
|
||||
self:_render()
|
||||
end
|
||||
bb:blitFrom(self._bb, x, y, 0, 0, self.width, self._bb:getHeight())
|
||||
end
|
||||
|
||||
@@ -161,7 +273,6 @@ function TextBoxWidget:free()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
FixedTextWidget
|
||||
--]]
|
||||
@@ -183,3 +294,72 @@ function FixedTextWidget:paintTo(bb, x, y)
|
||||
renderUtf8Text(bb, x, y+self._height, self.face, self.text,
|
||||
true, self.bgcolor, self.fgcolor)
|
||||
end
|
||||
|
||||
--[[
|
||||
Text widget with vertical scroll bar
|
||||
--]]
|
||||
ScrollTextWidget = InputContainer:new{
|
||||
text = nil,
|
||||
font_face = nil,
|
||||
width = 400,
|
||||
height = 300,
|
||||
scroll_bar_width = scaleByDPI(6),
|
||||
text_scroll_span = scaleByDPI(6),
|
||||
dialog = nil,
|
||||
}
|
||||
|
||||
function ScrollTextWidget:init()
|
||||
self.text_widget = TextBoxWidget:new{
|
||||
text = self.text,
|
||||
face = self.font_face,
|
||||
width = self.width - self.scroll_bar_width - self.text_scroll_span,
|
||||
height = self.height
|
||||
}
|
||||
local visible_line_count = self.text_widget:getVisLineCount()
|
||||
local total_line_count = self.text_widget:getAllLineCount()
|
||||
self.v_scroll_bar = VerticalScrollBar:new{
|
||||
enable = visible_line_count < total_line_count,
|
||||
low = 0,
|
||||
high = visible_line_count/total_line_count,
|
||||
width = scaleByDPI(6),
|
||||
height = self.height,
|
||||
}
|
||||
local horizontal_group = HorizontalGroup:new{}
|
||||
table.insert(horizontal_group, self.text_widget)
|
||||
table.insert(horizontal_group, HorizontalSpan:new{width = scaleByDPI(6)})
|
||||
table.insert(horizontal_group, self.v_scroll_bar)
|
||||
self[1] = horizontal_group
|
||||
self.dimen = Geom:new(self[1]:getSize())
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
Swipe = {
|
||||
GestureRange:new{
|
||||
ges = "swipe",
|
||||
range = self.dimen,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function ScrollTextWidget:updateScrollBar(text)
|
||||
local virtual_line_num = text:getVirtualLineNum()
|
||||
local visible_line_count = text:getVisLineCount()
|
||||
local all_line_count = text:getAllLineCount()
|
||||
self.v_scroll_bar:set(
|
||||
(virtual_line_num - 1) / all_line_count,
|
||||
(virtual_line_num - 1 + visible_line_count) / all_line_count
|
||||
)
|
||||
end
|
||||
|
||||
function ScrollTextWidget:onSwipe(arg, ges)
|
||||
if ges.direction == "north" then
|
||||
self.text_widget:scrollDown()
|
||||
self:updateScrollBar(self.text_widget)
|
||||
elseif ges.direction == "south" then
|
||||
self.text_widget:scrollUp()
|
||||
self:updateScrollBar(self.text_widget)
|
||||
end
|
||||
UIManager:setDirty(self.dialog, "partial")
|
||||
return true
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user