mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
* Adds a generic HTML widget modeled after the text widget, and HTML dictionary support. HTML dictionaries can have their own CSS (for X.ifo it must be X.css). The base CSS just resets the margin and sets the font. Note that the widget doesn't handle links, that wasn't needed for the dictionary. Closes <https://github.com/koreader/koreader/issues/1776>. * Show tag stripped HTML if the dictionary entry isn't valid HTML * Simulate the normal <br/> behavior * Bump base
788 lines
29 KiB
Lua
788 lines
29 KiB
Lua
local Blitbuffer = require("ffi/blitbuffer")
|
|
local Button = require("ui/widget/button")
|
|
local ButtonTable = require("ui/widget/buttontable")
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
local CloseButton = require("ui/widget/closebutton")
|
|
local Device = require("device")
|
|
local Geom = require("ui/geometry")
|
|
local Event = require("ui/event")
|
|
local Font = require("ui/font")
|
|
local FrameContainer = require("ui/widget/container/framecontainer")
|
|
local GestureRange = require("ui/gesturerange")
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
local InputDialog = require("ui/widget/inputdialog")
|
|
local LeftContainer = require("ui/widget/container/leftcontainer")
|
|
local LineWidget = require("ui/widget/linewidget")
|
|
local OverlapGroup = require("ui/widget/overlapgroup")
|
|
local ScrollHtmlWidget = require("ui/widget/scrollhtmlwidget")
|
|
local ScrollTextWidget = require("ui/widget/scrolltextwidget")
|
|
local Size = require("ui/size")
|
|
local TextWidget = require("ui/widget/textwidget")
|
|
local UIManager = require("ui/uimanager")
|
|
local VerticalGroup = require("ui/widget/verticalgroup")
|
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|
local logger = require("logger")
|
|
local util = require("util")
|
|
local _ = require("gettext")
|
|
local Screen = Device.screen
|
|
local T = require("ffi/util").template
|
|
|
|
--[[
|
|
Display quick lookup word definition
|
|
]]
|
|
local DictQuickLookup = InputContainer:new{
|
|
results = nil,
|
|
lookupword = nil,
|
|
dictionary = nil,
|
|
definition = nil,
|
|
displayword = nil,
|
|
is_wiki = false,
|
|
is_fullpage = false,
|
|
is_html = false,
|
|
dict_index = 1,
|
|
title_face = Font:getFace("x_smalltfont"),
|
|
content_face = Font:getFace("cfont", DDICT_FONT_SIZE),
|
|
width = nil,
|
|
height = nil,
|
|
-- box of highlighted word, quick lookup window tries to not hide the word
|
|
word_box = nil,
|
|
|
|
title_padding = Size.padding.default,
|
|
title_margin = Size.margin.title,
|
|
word_padding = Size.padding.default,
|
|
word_margin = Size.margin.default,
|
|
-- alt padding/margin for wiki to compensate for reduced font size
|
|
wiki_word_padding = Screen:scaleBySize(7),
|
|
wiki_word_margin = Screen:scaleBySize(3),
|
|
definition_padding = Screen:scaleBySize(2),
|
|
definition_margin = Screen:scaleBySize(2),
|
|
button_padding = Screen:scaleBySize(14),
|
|
-- refresh_callback will be called before we trigger full refresh in onSwipe
|
|
refresh_callback = nil,
|
|
}
|
|
|
|
local highlight_strings = {
|
|
highlight =_("Highlight"),
|
|
unhighlight = _("Unhighlight"),
|
|
}
|
|
|
|
function DictQuickLookup:init()
|
|
self:changeToDefaultDict()
|
|
if Device:hasKeys() then
|
|
self.key_events = {
|
|
Close = { {"Back"}, doc = "close quick lookup" }
|
|
}
|
|
end
|
|
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(),
|
|
}
|
|
},
|
|
},
|
|
-- This was for selection of a single word with simple hold
|
|
-- HoldWord = {
|
|
-- GestureRange:new{
|
|
-- ges = "hold",
|
|
-- range = function()
|
|
-- return self.region
|
|
-- end,
|
|
-- },
|
|
-- -- callback function when HoldWord is handled as args
|
|
-- args = function(word)
|
|
-- self.ui:handleEvent(
|
|
-- -- don't pass self.highlight to subsequent lookup, we want
|
|
-- -- the first to be the only one to unhighlight selection
|
|
-- -- when closed
|
|
-- Event:new("LookupWord", word, self.word_box))
|
|
-- end
|
|
-- },
|
|
-- Allow selection of one or more words (see textboxwidget.lua) :
|
|
HoldStartText = {
|
|
GestureRange:new{
|
|
ges = "hold",
|
|
range = function()
|
|
return self.region
|
|
end,
|
|
},
|
|
},
|
|
HoldReleaseText = {
|
|
GestureRange:new{
|
|
ges = "hold_release",
|
|
range = function()
|
|
return self.region
|
|
end,
|
|
},
|
|
-- callback function when HoldReleaseText is handled as args
|
|
args = function(text, hold_duration)
|
|
local lookup_target
|
|
if hold_duration < 2.0 then
|
|
-- do this lookup in the same domain (dict/wikipedia)
|
|
lookup_target = self.is_wiki and "LookupWikipedia" or "LookupWord"
|
|
else
|
|
-- but allow switching domain with a long hold
|
|
lookup_target = self.is_wiki and "LookupWord" or "LookupWikipedia"
|
|
end
|
|
if lookup_target == "LookupWikipedia" then
|
|
self:resyncWikiLanguages()
|
|
end
|
|
self.ui:handleEvent(
|
|
-- don't pass self.highlight to subsequent lookup, we want
|
|
-- the first to be the only one to unhighlight selection
|
|
-- when closed
|
|
Event:new(lookup_target, text)
|
|
)
|
|
end
|
|
},
|
|
}
|
|
end
|
|
end
|
|
|
|
-- Whether currently DictQuickLookup is working without a document.
|
|
function DictQuickLookup:isDocless()
|
|
return self.ui == nil or self.ui.highlight == nil
|
|
end
|
|
|
|
function DictQuickLookup:getHtmlDictionaryCss()
|
|
-- Using Noto Sans because Nimbus doesn't contain the IPA symbols.
|
|
local css = [[
|
|
@page {
|
|
margin: 0;
|
|
font-family: 'Noto Sans';
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
}
|
|
]]
|
|
|
|
if self.css then
|
|
return css .. self.css
|
|
end
|
|
return css
|
|
end
|
|
|
|
function DictQuickLookup:update()
|
|
local orig_dimen = self.dict_frame and self.dict_frame.dimen or Geom:new{}
|
|
-- calculate window dimension
|
|
self.align = "center"
|
|
self.region = Geom:new{
|
|
x = 0, y = 0,
|
|
w = Screen:getWidth(),
|
|
h = Screen:getHeight(),
|
|
}
|
|
if self.is_fullpage or G_reader_settings:isTrue("dict_largewindow") then
|
|
-- bigger window if fullpage being shown - this will let
|
|
-- some room anyway for footer display (time, battery...)
|
|
self.height = Screen:getHeight()
|
|
self.width = Screen:getWidth() - Screen:scaleBySize(40)
|
|
else
|
|
-- smaller window otherwise
|
|
-- try to not hide highlighted word
|
|
if self.word_box then
|
|
local box = self.word_box
|
|
if box.y + box.h/2 < Screen:getHeight()*0.3 then
|
|
self.region.y = box.y + box.h
|
|
self.region.h = Screen:getHeight() - box.y - box.h
|
|
self.align = "top"
|
|
elseif box.y + box.h/2 > Screen:getHeight()*0.7 then
|
|
self.region.y = 0
|
|
self.region.h = box.y
|
|
self.align = "bottom"
|
|
end
|
|
end
|
|
self.height = math.min(self.region.h*0.7, Screen:getHeight()*0.5)
|
|
end
|
|
-- dictionary title
|
|
local close_button = CloseButton:new{ window = self, padding_top = self.title_margin, }
|
|
local dict_title_text = TextWidget:new{
|
|
text = self.dictionary,
|
|
face = self.title_face,
|
|
bold = true,
|
|
width = self.width,
|
|
}
|
|
-- Some different UI tweaks for dict or wiki
|
|
local lookup_word_font_size, lookup_word_padding, lookup_word_margin
|
|
if self.is_wiki then
|
|
-- visual hint : dictionary title left adjusted, Wikipedia title centered
|
|
dict_title_text = CenterContainer:new{
|
|
dimen = Geom:new{
|
|
w = self.width,
|
|
h = dict_title_text:getSize().h,
|
|
},
|
|
dict_title_text
|
|
}
|
|
-- Wikipedia has longer titles, so use a smaller font
|
|
lookup_word_font_size = 18
|
|
lookup_word_padding = self.wiki_word_padding
|
|
lookup_word_margin = self.wiki_word_margin
|
|
-- Keep a copy of self.wiki_languages for use
|
|
-- by DictQuickLookup:resyncWikiLanguages()
|
|
self.wiki_languages_copy = self.wiki_languages and {unpack(self.wiki_languages)} or nil
|
|
else
|
|
-- Usual font size for dictionary
|
|
lookup_word_font_size = 22
|
|
lookup_word_padding = self.word_padding
|
|
lookup_word_margin = self.word_margin
|
|
end
|
|
self.dict_title = FrameContainer:new{
|
|
padding = self.title_padding,
|
|
margin = self.title_margin,
|
|
bordersize = 0,
|
|
dict_title_text
|
|
}
|
|
-- lookup word
|
|
local lookup_word = Button:new{
|
|
padding = lookup_word_padding,
|
|
margin = lookup_word_margin,
|
|
bordersize = 0,
|
|
max_width = self.width,
|
|
text = self.displayword,
|
|
text_font_face = "tfont",
|
|
text_font_size = lookup_word_font_size,
|
|
hold_callback = function() self:lookupInputWord(self.lookupword) end,
|
|
}
|
|
|
|
local text_widget
|
|
|
|
if self.is_html then
|
|
text_widget = ScrollHtmlWidget:new{
|
|
html_body = self.definition,
|
|
css = self:getHtmlDictionaryCss(),
|
|
default_font_size = DDICT_FONT_SIZE,
|
|
width = self.width,
|
|
height = self.is_fullpage and self.height*0.75 or self.height*0.7,
|
|
dialog = self,
|
|
}
|
|
else
|
|
text_widget = ScrollTextWidget:new{
|
|
text = self.definition,
|
|
face = self.content_face,
|
|
width = self.width,
|
|
-- get a bit more height for definition as wiki has one less button raw
|
|
height = self.is_fullpage and self.height*0.75 or self.height*0.7,
|
|
dialog = self,
|
|
-- allow for disabling justification
|
|
justified = G_reader_settings:nilOrTrue("dict_justify"),
|
|
}
|
|
end
|
|
|
|
-- word definition
|
|
local definition = FrameContainer:new{
|
|
padding = self.definition_padding,
|
|
margin = self.definition_margin,
|
|
bordersize = 0,
|
|
text_widget,
|
|
}
|
|
-- Different sets of buttons if fullpage or not
|
|
local buttons
|
|
if self.is_fullpage then
|
|
-- A save and a close button
|
|
buttons = {
|
|
{
|
|
{
|
|
text = _("Save as EPUB"),
|
|
callback = function()
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
local ConfirmBox = require("ui/widget/confirmbox")
|
|
-- if forced_lang was specified, it may not be in our wiki_languages,
|
|
-- but ReaderWikipedia will have put it in result.lang
|
|
local lang = self.lang or self.wiki_languages_copy[1]
|
|
-- Just to be safe (none of the invalid chars, except ':' for uninteresting
|
|
-- Portal: or File: wikipedia pages, should be in lookup_word)
|
|
local cleaned_lookupword = util.replaceInvalidChars(self.lookupword)
|
|
local filename = cleaned_lookupword .. "."..string.upper(lang)..".epub"
|
|
-- Find a directory to save file into
|
|
local dir = G_reader_settings:readSetting("wikipedia_save_dir")
|
|
if not dir then dir = G_reader_settings:readSetting("home_dir") end
|
|
if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end
|
|
if not dir then
|
|
UIManager:show(InfoMessage:new{
|
|
text = _("No directory to save the page to could be found."),
|
|
})
|
|
return
|
|
end
|
|
local epub_path = dir .. "/" .. filename
|
|
UIManager:show(ConfirmBox:new{
|
|
text = T(_("Save as %1?"), filename),
|
|
ok_callback = function()
|
|
UIManager:scheduleIn(0.1, function()
|
|
local Wikipedia = require("ui/wikipedia")
|
|
Wikipedia:createEpubWithUI(epub_path, self.lookupword, lang, function(success)
|
|
if success then
|
|
UIManager:show(ConfirmBox:new{
|
|
text = T(_("Page saved to:\n%1\n\nWould you like to read the downloaded page now?"), epub_path),
|
|
ok_callback = function()
|
|
-- close all dict/wiki windows, without scheduleIn(highlight.clear())
|
|
self:onHoldClose(true)
|
|
-- close current ReaderUI in 1 sec, and create a new one
|
|
UIManager:scheduleIn(1.0, function()
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
local reader = ReaderUI:_getRunningInstance()
|
|
if reader then
|
|
-- close Highlight menu if any still shown
|
|
if reader.highlight then
|
|
reader.highlight:onClose()
|
|
end
|
|
reader:onClose()
|
|
end
|
|
ReaderUI:showReader(epub_path)
|
|
end)
|
|
end,
|
|
})
|
|
else
|
|
UIManager:show(InfoMessage:new{
|
|
text = _("Saving Wikipedia page failed or canceled."),
|
|
})
|
|
end
|
|
end)
|
|
end)
|
|
end
|
|
})
|
|
end,
|
|
},
|
|
{
|
|
text = _("Close"),
|
|
callback = function()
|
|
UIManager:close(self)
|
|
end,
|
|
},
|
|
},
|
|
}
|
|
else
|
|
buttons = {
|
|
{
|
|
{
|
|
text = "◁◁",
|
|
enabled = self:isPrevDictAvaiable(),
|
|
callback = function()
|
|
self:changeToPrevDict()
|
|
end,
|
|
},
|
|
{
|
|
text = self:getHighlightText(),
|
|
enabled = self.highlight ~= nil,
|
|
callback = function()
|
|
if self:getHighlightText() == highlight_strings.highlight then
|
|
self.ui:handleEvent(Event:new("Highlight"))
|
|
else
|
|
self.ui:handleEvent(Event:new("Unhighlight"))
|
|
end
|
|
self:update()
|
|
end,
|
|
},
|
|
{
|
|
text = "▷▷",
|
|
enabled = self:isNextDictAvaiable(),
|
|
callback = function()
|
|
self:changeToNextDict()
|
|
end,
|
|
},
|
|
},
|
|
{
|
|
{
|
|
-- if dictionary result, do the same search on wikipedia
|
|
-- if already wiki, get the full page for the current result
|
|
text = self.is_wiki and _("Wikipedia full") or _("Wikipedia"),
|
|
callback = function()
|
|
UIManager:scheduleIn(0.1, function()
|
|
self:lookupWikipedia(self.is_wiki) -- will get_fullpage if is_wiki
|
|
end)
|
|
end,
|
|
},
|
|
-- Rotate thru available wikipedia languages (disabled if dictionary window)
|
|
-- (replace previous unimplemented "Add Note")
|
|
{
|
|
-- if more than one language, enable it and display "current lang > next lang"
|
|
-- otherwise, just display current lang
|
|
text = self.is_wiki and ( #self.wiki_languages > 1 and self.wiki_languages[1].." > "..self.wiki_languages[2] or self.wiki_languages[1] ) or _("Follow Link"),
|
|
enabled = (self.is_wiki and #self.wiki_languages > 1) or self.selected_link ~= nil,
|
|
callback = function()
|
|
if self.is_wiki then
|
|
self:resyncWikiLanguages(true) -- rotate & resync them
|
|
UIManager:close(self)
|
|
self:lookupWikipedia()
|
|
else
|
|
self:onClose()
|
|
self.ui.link:onGotoLink(self.selected_link)
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
text = (self.is_wiki or self:isDocless()) and _("Close") or _("Search"),
|
|
callback = function()
|
|
if not self.is_wiki then
|
|
self.ui:handleEvent(Event:new("HighlightSearch"))
|
|
end
|
|
UIManager:close(self)
|
|
end,
|
|
},
|
|
},
|
|
}
|
|
end
|
|
|
|
local button_table = ButtonTable:new{
|
|
width = math.max(self.width, definition:getSize().w),
|
|
button_font_face = "cfont",
|
|
button_font_size = 20,
|
|
buttons = buttons,
|
|
zero_sep = true,
|
|
show_parent = self,
|
|
}
|
|
local title_bar = LineWidget:new{
|
|
dimen = Geom:new{
|
|
w = button_table:getSize().w + self.button_padding,
|
|
h = Size.line.thick,
|
|
}
|
|
}
|
|
|
|
self.dict_bar = OverlapGroup:new{
|
|
dimen = {
|
|
w = button_table:getSize().w + self.button_padding,
|
|
h = self.dict_title:getSize().h
|
|
},
|
|
self.dict_title,
|
|
close_button,
|
|
}
|
|
-- Fix dict title max width now that we know the final width
|
|
dict_title_text.width = self.dict_bar.dimen.w - close_button:getSize().w
|
|
|
|
self.dict_frame = FrameContainer:new{
|
|
radius = Size.radius.window,
|
|
bordersize = Size.border.window,
|
|
padding = 0,
|
|
margin = 0,
|
|
background = Blitbuffer.COLOR_WHITE,
|
|
VerticalGroup:new{
|
|
align = "left",
|
|
self.dict_bar,
|
|
title_bar,
|
|
-- word
|
|
LeftContainer:new{
|
|
dimen = Geom:new{
|
|
w = title_bar:getSize().w,
|
|
h = lookup_word:getSize().h,
|
|
},
|
|
lookup_word,
|
|
},
|
|
-- definition
|
|
CenterContainer:new{
|
|
dimen = Geom:new{
|
|
w = title_bar:getSize().w,
|
|
h = definition:getSize().h,
|
|
},
|
|
definition,
|
|
},
|
|
-- buttons
|
|
CenterContainer:new{
|
|
dimen = Geom:new{
|
|
w = title_bar:getSize().w,
|
|
h = button_table:getSize().h,
|
|
},
|
|
button_table,
|
|
}
|
|
}
|
|
}
|
|
self[1] = WidgetContainer:new{
|
|
align = self.align,
|
|
dimen = self.region,
|
|
FrameContainer:new{
|
|
bordersize = 0,
|
|
padding = Size.padding.default,
|
|
self.dict_frame,
|
|
}
|
|
}
|
|
UIManager:setDirty("all", function()
|
|
local update_region = self.dict_frame.dimen:combine(orig_dimen)
|
|
logger.dbg("update dict region", update_region)
|
|
return "ui", update_region
|
|
end)
|
|
end
|
|
|
|
function DictQuickLookup:onCloseWidget()
|
|
UIManager:setDirty(nil, function()
|
|
return "partial", self.dict_frame.dimen
|
|
end)
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:onShow()
|
|
UIManager:setDirty(self, function()
|
|
return "ui", self.dict_frame.dimen
|
|
end)
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:getHighlightedItem()
|
|
if self:isDocless() then return end
|
|
return self.ui.highlight:getHighlightBookmarkItem()
|
|
end
|
|
|
|
function DictQuickLookup:getHighlightText()
|
|
local item = self:getHighlightedItem()
|
|
if not item then
|
|
return highlight_strings.highlight, false
|
|
elseif self.ui.bookmark:isBookmarkAdded(item) then
|
|
return highlight_strings.unhighlight, false
|
|
else
|
|
return highlight_strings.highlight, true
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:isPrevDictAvaiable()
|
|
return self.dict_index > 1
|
|
end
|
|
|
|
function DictQuickLookup:isNextDictAvaiable()
|
|
return self.dict_index < #self.results
|
|
end
|
|
|
|
function DictQuickLookup:changeToPrevDict()
|
|
if self:isPrevDictAvaiable() then
|
|
self:changeDictionary(self.dict_index - 1)
|
|
elseif #self.results > 1 then -- restart at end if first reached
|
|
self:changeDictionary(#self.results)
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:changeToNextDict()
|
|
if self:isNextDictAvaiable() then
|
|
self:changeDictionary(self.dict_index + 1)
|
|
elseif #self.results > 1 then -- restart at first if end reached
|
|
self:changeDictionary(1)
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:changeDictionary(index)
|
|
if not self.results[index] then return end
|
|
self.dict_index = index
|
|
self.dictionary = self.results[index].dict
|
|
self.lookupword = self.results[index].word
|
|
self.definition = self.results[index].definition
|
|
self.is_fullpage = self.results[index].is_fullpage
|
|
self.is_html = self.results[index].is_html
|
|
self.css = self.results[index].css
|
|
self.lang = self.results[index].lang
|
|
if self.is_fullpage then
|
|
self.displayword = self.lookupword
|
|
else
|
|
-- add "dict_index / nbresults" to displayword, so we know where
|
|
-- we're at and what's yet to see
|
|
self.displayword = self.lookupword.." "..index.." / "..#self.results
|
|
-- add queried word to 1st result's definition, so we can see
|
|
-- what was the selected text and if we selected wrong
|
|
if index == 1 then
|
|
self.definition = self.definition.."\n_______\n"..T(_("(query : %1)"), self.word)
|
|
end
|
|
end
|
|
|
|
self:update()
|
|
end
|
|
|
|
function DictQuickLookup:changeToDefaultDict()
|
|
if self.dictionary then
|
|
-- dictionaries that have definition of the first word(accurate word)
|
|
-- excluding Fuzzy queries.
|
|
local n_accurate_dicts = nil
|
|
local default_word = self.results[1].word
|
|
for i=1, #self.results do
|
|
if self.results[i].word == default_word then
|
|
n_accurate_dicts = i
|
|
else
|
|
break
|
|
end
|
|
end
|
|
-- change to dictionary specified by self.dictionary
|
|
for i=1, n_accurate_dicts do
|
|
if self.results[i].dict == self.dictionary then
|
|
self:changeDictionary(i)
|
|
break
|
|
end
|
|
-- cannot find definition in default dictionary
|
|
if i == n_accurate_dicts then
|
|
self:changeDictionary(1)
|
|
end
|
|
end
|
|
else
|
|
self:changeDictionary(1)
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:onAnyKeyPressed()
|
|
-- triggered by our defined key events
|
|
UIManager:close(self)
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:onTapCloseDict(arg, ges_ev)
|
|
if ges_ev.pos:notIntersectWith(self.dict_frame.dimen) then
|
|
self:onClose()
|
|
return true
|
|
elseif not ges_ev.pos:notIntersectWith(self.dict_title.dimen) and not self.is_wiki then
|
|
self.ui:handleEvent(Event:new("UpdateDefaultDict", self.dictionary))
|
|
return true
|
|
end
|
|
-- Allow for changing dict with tap (tap event will be first
|
|
-- processed for scrolling definition by ScrollTextWidget, which
|
|
-- will pop it up for us here when it can't scroll anymore).
|
|
-- This allow for continuous reading of results' definitions with tap.
|
|
if ges_ev.pos.x < Screen:getWidth()/2 then
|
|
self:changeToPrevDict()
|
|
else
|
|
self:changeToNextDict()
|
|
end
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:onClose()
|
|
UIManager:close(self)
|
|
for i = #self.window_list, 1, -1 do
|
|
local window = self.window_list[i]
|
|
if window == self then
|
|
table.remove(self.window_list, i)
|
|
end
|
|
end
|
|
if self.highlight then
|
|
-- delay unhighlight of selection, so we can see where we stopped when
|
|
-- back from our journey into dictionary or wikipedia
|
|
local clear_id = self.highlight:getClearId()
|
|
UIManager:scheduleIn(0.5, function()
|
|
self.highlight:clear(clear_id)
|
|
end)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:onHoldClose(no_clear)
|
|
self:onClose()
|
|
for i = #self.window_list, 1, -1 do
|
|
local window = self.window_list[i]
|
|
-- if one holds a highlight, let's clear it like in onClose()
|
|
if window.highlight and not no_clear then
|
|
local clear_id = window.highlight:getClearId()
|
|
UIManager:scheduleIn(0.5, function()
|
|
window.highlight:clear(clear_id)
|
|
end)
|
|
end
|
|
UIManager:close(window)
|
|
table.remove(self.window_list, i)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:onSwipe(arg, ges)
|
|
if ges.direction == "west" then
|
|
self:changeToNextDict()
|
|
elseif ges.direction == "east" then
|
|
self:changeToPrevDict()
|
|
else
|
|
if self.refresh_callback then self.refresh_callback() end
|
|
-- trigger full refresh
|
|
UIManager:setDirty(nil, "full")
|
|
-- a long diagonal swipe may also be used for taking a screenshot,
|
|
-- so let it propagate
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
function DictQuickLookup:lookupInputWord(hint)
|
|
self:onClose()
|
|
self.input_dialog = InputDialog:new{
|
|
title = _("Input lookup word"),
|
|
input = hint,
|
|
input_hint = hint or "",
|
|
input_type = "text",
|
|
buttons = {
|
|
{
|
|
{
|
|
text = _("Cancel"),
|
|
callback = function()
|
|
self:closeInputDialog()
|
|
end,
|
|
},
|
|
{
|
|
text = _("Lookup"),
|
|
is_enter_default = true,
|
|
callback = function()
|
|
self:closeInputDialog()
|
|
self:inputLookup()
|
|
end,
|
|
},
|
|
}
|
|
},
|
|
}
|
|
self.input_dialog:onShowKeyboard()
|
|
UIManager:show(self.input_dialog)
|
|
end
|
|
|
|
function DictQuickLookup:inputLookup()
|
|
local word = self.input_dialog:getInputText()
|
|
if word and word ~= "" then
|
|
local event
|
|
if self.is_wiki then
|
|
event = "LookupWikipedia"
|
|
self:resyncWikiLanguages()
|
|
else
|
|
event = "LookupWord"
|
|
end
|
|
self.ui:handleEvent(Event:new(event, word))
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:closeInputDialog()
|
|
UIManager:close(self.input_dialog)
|
|
end
|
|
|
|
function DictQuickLookup:resyncWikiLanguages(rotate)
|
|
-- Resync the current language or rotate it from its state when
|
|
-- this window was created (we may have rotated it later in other
|
|
-- wikipedia windows that we closed and went back here, and its
|
|
-- state would not be what the wikipedia language button is showing.
|
|
if not self.wiki_languages_copy then
|
|
return
|
|
end
|
|
if rotate then
|
|
-- rotate our saved wiki_languages copy
|
|
local current_lang = table.remove(self.wiki_languages_copy, 1)
|
|
table.insert(self.wiki_languages_copy, current_lang)
|
|
end
|
|
-- re-set self.wiki_languages with original (possibly rotated) items
|
|
for i, lang in ipairs(self.wiki_languages_copy) do
|
|
self.wiki_languages[i] = lang
|
|
end
|
|
end
|
|
|
|
function DictQuickLookup:lookupWikipedia(get_fullpage)
|
|
local word
|
|
if get_fullpage then
|
|
-- we use the word of the displayed result's definition, which
|
|
-- is the exact title of the full wikipedia page
|
|
word = self.lookupword
|
|
else
|
|
-- we use the original word that was querried
|
|
word = self.word
|
|
end
|
|
self:resyncWikiLanguages()
|
|
-- strange : we need to pass false instead of nil if word_box is nil,
|
|
-- otherwise get_fullpage is not passed
|
|
self.ui:handleEvent(Event:new("LookupWikipedia", word, self.word_box and self.word_box or false, get_fullpage))
|
|
end
|
|
|
|
return DictQuickLookup
|