Merge pull request #164 from chrox/multi-dict

add multi-dictionary support
This commit is contained in:
{Qingping,Dave} Hou
2013-07-21 01:39:17 -07:00
7 changed files with 310 additions and 146 deletions

View File

@@ -4,12 +4,6 @@ require "ui/widget/dict"
ReaderDictionary = EventListener:new{}
function ReaderDictionary:init()
local dev_mod = Device:getModel()
if dev_mod == "KindlePaperWhite" or dev_mod == "KindleTouch" then
require("liblipclua")
DEBUG("init lipc handler com.github.koreader.dictionary")
self.lipc_handle = lipc.init("com.github.koreader.dictionary")
end
JSON = require("JSON")
end
@@ -17,25 +11,6 @@ function ReaderDictionary:onLookupWord(word)
self:stardictLookup(word)
end
function ReaderDictionary:nativeDictLookup(word)
DEBUG("lookup word:", word)
--self:quickLookup()
if self.lipc_handle and word then
self.lipc_handle:set_string_property(
"com.github.koreader.kpvbooklet.dict", "lookup", word)
local results_str = self.lipc_handle:get_string_property(
"com.github.koreader.kpvbooklet.word", word)
if results_str then
--DEBUG("result str:", word, results_str)
local ok, results_tab = pcall(JSON.decode, JSON, results_str)
--DEBUG("lookup result table:", word, results_tab)
if results_tab and results_tab[1] then
self:showDict(results_tab[1])
end
end
end
end
function ReaderDictionary:stardictLookup(word)
DEBUG("lookup word:", word)
if word then
@@ -48,34 +23,35 @@ function ReaderDictionary:stardictLookup(word)
local results_str = std_out:read("*all")
if results_str then
--DEBUG("result str:", word, results_str)
local ok, results_tab = pcall(JSON.decode, JSON, results_str)
--DEBUG("lookup result table:", word, results_tab)
if results_tab and results_tab[1] then
self:showDict(results_tab[1])
end
local ok, results = pcall(JSON.decode, JSON, results_str)
--DEBUG("lookup result table:", word, results)
self:showDict(results)
end
end
end
function ReaderDictionary:showDict(result)
-- UIManager:show(DictQuickLookup:new{
-- dict = "Oxford Dictionary of English",
-- definition = "coordination n. [mass noun] 1 the organization of the different elements of a \
-- complex body or activity so as to enable them to work together effectively: an important managerial \
-- task is the control and coordination of activities. cooperative effort resulting in an effective \
-- relationship: action groups work in coordination with local groups to end rainforest destruction. \
-- the ability to use different parts of the body together smoothly and efficiently: changing from \
-- one foot position to another requires coordination and balance.",
-- id = "/mnt/us/documents/dictionaries/Oxford_Dictionary_of_English.azw",
-- lang = "en",
-- })
if result then
function ReaderDictionary:showDict(results)
if results and results[1] then
DEBUG("showing quick lookup dictionary window")
UIManager:show(DictQuickLookup:new{
ui = self.ui,
dict = result.dict,
definition = result.definition,
id = result.ID,
lang = result.lang,
dialog = self.dialog,
results = results,
dictionary = self.default_dictionary,
width = Screen:getWidth() - scaleByDPI(120),
})
end
end
function ReaderDictionary:onUpdateDefaultDict(dict)
DEBUG("make default dictionary:", dict)
self.default_dictionary = dict
end
function ReaderDictionary:onReadSettings(config)
self.default_dictionary = config:readSetting("default_dictionary")
end
function ReaderDictionary:onCloseDocument()
self.ui.doc_settings:saveSetting("default_dictionary", self.default_dictionary)
end

View File

@@ -90,7 +90,7 @@ function ReaderHighlight:onTap(arg, ges)
for j = 1, #items[i].boxes do
if inside_box(ges, items[i].boxes[j]) then
DEBUG("Tap on hightlight")
self.edit_highlight_dialog = ButtonTable:new{
self.edit_highlight_dialog = HighlightDialog:new{
buttons = {
{
{
@@ -198,13 +198,59 @@ function ReaderHighlight:translate(selected_text)
end
end
HighlightDialog = InputContainer:new{
buttons = nil,
tap_close_callback = nil,
}
function HighlightDialog:init()
if Device:hasKeyboard() then
key_events = {
AnyKeyPressed = { { Input.group.Any },
seqtext = "any key", doc = _("close dialog") }
}
else
self.ges_events.TapClose = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
}
}
end
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
FrameContainer:new{
ButtonTable:new{
width = Screen:getWidth()*0.9,
buttons = self.buttons,
},
background = 0,
bordersize = 2,
radius = 7,
padding = 2,
}
}
end
function HighlightDialog:onTapClose()
UIManager:close(self)
if self.tap_close_callback then
self.tap_close_callback()
end
return true
end
function ReaderHighlight:onHoldRelease(arg, ges)
if self.selected_word then
self:lookup(self.selected_word)
self.selected_word = nil
elseif self.selected_text then
DEBUG("show highlight dialog")
self.highlight_dialog = ButtonTable:new{
self.highlight_dialog = HighlightDialog:new{
buttons = {
{
{
@@ -439,3 +485,4 @@ function ReaderHighlight:getTextFromPositions(boxes, pos0, pos1)
boxes = line_boxes,
}
end

View File

@@ -36,10 +36,12 @@ function Button:init()
background = self.background,
radius = self.radius,
padding = self.padding,
HorizontalGroup:new{
HorizontalSpan:new{ width = (self.width - text_size.w)/2 },
CenterContainer:new{
dimen = Geom:new{
w = self.width,
h = text_size.h
},
self.text_widget,
HorizontalSpan:new{ width = (self.width - text_size.w)/2 },
}
}
if self.preselect then

View File

@@ -1,60 +1,46 @@
require "ui/widget/base"
require "ui/widget/line"
ButtonTable = InputContainer:new{
ButtonTable = VerticalGroup:new{
width = Screen:getWidth(),
buttons = {
{
{text="OK", enabled=true, callback=nil},
{text="Cancel", enabled=false, callback=nil},
},
},
tap_close_callback = nil,
sep_width = scaleByDPI(1),
padding = scaleByDPI(2),
zero_sep = false,
}
function ButtonTable:init()
if Device:hasKeyboard() then
key_events = {
AnyKeyPressed = { { Input.group.Any },
seqtext = "any key", doc = _("close dialog") }
}
else
self.ges_events.TapClose = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
}
}
--local vertical_group = VerticalGroup:new{}
if self.zero_sep then
self:addHorizontalSep()
end
local vertical_group = VerticalGroup:new{}
local horizontal_sep = LineWidget:new{
background = 8,
dimen = Geom:new{
w = Screen:getWidth()*0.9,
h = 1,
}
}
for i = 1, #self.buttons do
local horizontal_group = HorizontalGroup:new{}
local line = self.buttons[i]
local sizer_space = self.sep_width * (#line - 1) + 2
for j = 1, #line do
local button = Button:new{
text = line[j].text,
enabled = line[j].enabled,
callback = line[j].callback,
width = Screen:getWidth()*0.9/#line,
width = (self.width - sizer_space)/#line,
bordersize = 0,
margin = 0,
padding = 0,
text_font_face = "cfont",
text_font_size = scaleByDPI(18),
text_font_size = 18,
}
local button_dim = button:getSize()
local vertical_sep = LineWidget:new{
background = 8,
dimen = Geom:new{
w = scaleByDPI(1),
w = self.sep_width,
h = button_dim.h,
}
}
@@ -63,29 +49,21 @@ function ButtonTable:init()
table.insert(horizontal_group, vertical_sep)
end
end -- end for each button
table.insert(vertical_group, horizontal_group)
table.insert(self, horizontal_group)
if i < #self.buttons then
table.insert(vertical_group, VerticalSpan:new{ width = scaleByDPI(2) })
table.insert(vertical_group, horizontal_sep)
table.insert(vertical_group, VerticalSpan:new{ width = scaleByDPI(2) })
self:addHorizontalSep()
end
end -- end for each button line
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
FrameContainer:new{
vertical_group,
background = 0,
bordersize = 2,
radius = 7,
padding = 2,
},
}
end
function ButtonTable:onTapClose()
UIManager:close(self)
if self.tap_close_callback then
self.tap_close_callback()
end
return true
function ButtonTable:addHorizontalSep()
table.insert(self, VerticalSpan:new{ width = scaleByDPI(2) })
table.insert(self, LineWidget:new{
background = 8,
dimen = Geom:new{
w = self.width,
h = self.sep_width,
}
})
table.insert(self, VerticalSpan:new{ width = scaleByDPI(2) })
end

View File

@@ -462,27 +462,17 @@ function ConfigDialog:updateConfigPanel(index)
end
function ConfigDialog:makeDialog()
local dialog = VerticalGroup:new{
self.config_panel,
self.config_menubar,
self.dialog_frame = FrameContainer:new{
background = 0,
VerticalGroup:new{
self.config_panel,
self.config_menubar,
},
}
local dialog_size = dialog:getSize()
self[1] = BottomContainer:new{
dimen = Screen:getSize(),
FrameContainer:new{
dimen = dialog_size,
background = 0,
dialog,
}
}
self.dialog_dimen = Geom:new{
x = (Screen:getWidth() - dialog_size.w)/2,
y = Screen:getHeight() - dialog_size.h,
w = dialog_size.w,
h = dialog_size.h,
self.dialog_frame,
}
end
@@ -514,7 +504,7 @@ function ConfigDialog:closeDialog()
end
function ConfigDialog:onTapCloseMenu(arg, ges_ev)
if ges_ev.pos:notIntersectWith(self.dialog_dimen) then
if ges_ev.pos:notIntersectWith(self.dialog_frame.dimen) then
self:closeDialog()
return true
end

View File

@@ -5,6 +5,12 @@ WidgetContainer is a container for another Widget
--]]
WidgetContainer = Widget:new()
function WidgetContainer:init()
if not self.dimen then
self.dimen = Geom:new{}
end
end
function WidgetContainer:getSize()
if self.dimen then
-- fixed size
@@ -155,6 +161,11 @@ end
function FrameContainer:paintTo(bb, x, y)
local my_size = self:getSize()
self.dimen = Geom:new{
x = x, y = y,
w = my_size.w,
h = my_size.h
}
local container_width = self.width or my_size.w
local container_height = self.height or my_size.h

View File

@@ -1,16 +1,27 @@
require "ui/widget/container"
require "ui/widget/buttontable"
--[[
Display quick lookup word definition
]]
DictQuickLookup = InputContainer:new{
dict = nil,
results = nil,
lookupword = nil,
dictionary = nil,
definition = nil,
id = nil,
lang = nil,
dict_index = 1,
title_face = Font:getFace("tfont", 20),
word_face = Font:getFace("tfont", 18),
content_face = Font:getFace("cfont", 18),
width = nil,
title_padding = scaleByDPI(5),
title_margin = scaleByDPI(2),
word_padding = scaleByDPI(5),
word_margin = scaleByDPI(2),
definition_padding = scaleByDPI(5),
definition_margin = scaleByDPI(2),
button_padding = scaleByDPI(14),
}
function DictQuickLookup:init()
@@ -20,7 +31,7 @@ function DictQuickLookup:init()
seqtext = "any key", doc = _("close dialog") }
}
else
self.ges_events.TapClose = {
self.ges_events.TapCloseDict = {
GestureRange:new{
ges = "tap",
range = Geom:new{
@@ -31,29 +42,172 @@ function DictQuickLookup:init()
}
}
end
-- we construct the actual content here because self.text is only available now
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
FrameContainer:new{
margin = 2,
background = 0,
VerticalGroup:new{
align = "center",
-- title bar
TextBoxWidget:new{
text = self.dict,
face = self.title_face,
width = Screen:getWidth() - 100,
self:changeToDefaultDict()
end
function DictQuickLookup:update()
-- dictionary title
self.dict_title = FrameContainer:new{
padding = self.title_padding,
margin = self.title_margin,
bordersize = 0,
TextWidget:new{
text = self.dictionary,
face = self.title_face,
width = self.width,
}
}
-- lookup word
local lookup_word = FrameContainer:new{
padding = self.word_padding,
margin = self.word_margin,
bordersize = 0,
TextBoxWidget:new{
text = self.lookupword,
face = self.word_face,
width = self.width,
},
}
-- word definition
local definition = FrameContainer:new{
padding = self.definition_padding,
margin = self.definition_margin,
bordersize = 0,
TextBoxWidget:new{
text = self.definition,
face = self.content_face,
width = self.width,
},
}
local button_table = ButtonTable:new{
width = math.max(self.width, definition:getSize().w),
buttons = {
{
{
text = _("<<"),
enabled = self:isPrevDictAvaiable(),
callback = function()
self:changeToPrevDict()
end,
},
VerticalSpan:new{ width = 20 },
TextBoxWidget:new{
text = self.definition,
face = self.content_face,
width = Screen:getWidth() - 100,
}
{
text = _(">>"),
enabled = self:isNextDictAvaiable(),
callback = function()
self:changeToNextDict()
end,
},
},
{
{
text = _("Highlight"),
enabled = false,
callback = function()
self.ui:handleEvent(Event:new("Highlight"))
end,
},
{
text = _("Add Note"),
enabled = false,
callback = function()
self.ui:handleEvent(Event:new("AddNote"))
end,
},
},
},
zero_sep = true,
}
local title_bar = LineWidget:new{
--background = 8,
dimen = Geom:new{
w = button_table:getSize().w + self.button_padding,
h = scaleByDPI(2),
}
}
self.dict_frame = FrameContainer:new{
radius = 8,
bordersize = 3,
padding = 0,
margin = 0,
background = 0,
VerticalGroup:new{
align = "left",
self.dict_title,
title_bar,
-- word
lookup_word,
-- definition
definition,
-- buttons
CenterContainer:new{
dimen = Geom:new{
w = title_bar:getSize().w,
h = button_table:getSize().h,
},
button_table,
}
}
}
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
self.dict_frame,
}
end
function DictQuickLookup:isPrevDictAvaiable()
return self.dict_index > 1
end
function DictQuickLookup:isNextDictAvaiable()
return self.dict_index < #self.results
end
function DictQuickLookup:changeToPrevDict()
self:changeDictionary(self.dict_index - 1)
end
function DictQuickLookup:changeToNextDict()
self:changeDictionary(self.dict_index + 1)
end
function DictQuickLookup:changeDictionary(index)
self.dict_index = index
self.dictionary = self.results[index].dict
self.lookupword = self.results[index].word
self.definition = self.results[index].definition
self:update()
UIManager.repaint_all = true
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()
@@ -62,8 +216,14 @@ function DictQuickLookup:onAnyKeyPressed()
return true
end
function DictQuickLookup:onTapClose()
UIManager:close(self)
self.ui:handleEvent(Event:new("Tap"))
function DictQuickLookup:onTapCloseDict(arg, ges_ev)
if ges_ev.pos:notIntersectWith(self.dict_frame.dimen) then
UIManager:close(self)
self.ui:handleEvent(Event:new("Tap"))
return true
elseif not ges_ev.pos:notIntersectWith(self.dict_title.dimen) then
self.ui:handleEvent(Event:new("UpdateDefaultDict", self.dictionary))
return true
end
return true
end