mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
9b7aba3fba
Also fix touch zone dependency graph generation code. ReaderHighlight has now been migrated to use touch zone Inputcontainer's touch event handling logic changed to only stop propagation when handler returns `true`. Previously, it stops propagation when a handler is found. This is needed to support both readerhighlight_tap and tap_forward touch zones.
107 lines
3.1 KiB
Lua
107 lines
3.1 KiB
Lua
--[[--
|
|
DepGraph module.
|
|
Library for constructing dependency graphs.
|
|
|
|
Example:
|
|
|
|
local dg = DepGraph:new{}
|
|
dg:addNode('a1', {'a2', 'b1'})
|
|
dg:addNode('b1', {'a2', 'c1'})
|
|
dg:addNode('c1')
|
|
-- The return value of dg:serialize() will be:
|
|
-- {'a2', 'c1', 'b1', 'a1'}
|
|
|
|
]]
|
|
|
|
local DepGraph = {}
|
|
|
|
function DepGraph:new(new_o)
|
|
local o = new_o or {}
|
|
o.nodes = {}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end
|
|
|
|
function DepGraph:addNode(node_key, deps)
|
|
if not self.nodes[node_key] then
|
|
self.nodes[node_key] = {}
|
|
end
|
|
if not deps then return end
|
|
|
|
local node_deps = {}
|
|
for _,dep_node_key in ipairs(deps) do
|
|
if not self.nodes[dep_node_key] then
|
|
self.nodes[dep_node_key] = {}
|
|
end
|
|
table.insert(node_deps, dep_node_key)
|
|
end
|
|
self.nodes[node_key].deps = node_deps
|
|
end
|
|
|
|
function DepGraph:removeNode(node_key)
|
|
self.nodes[node_key] = nil
|
|
for curr_node_key, curr_node in pairs(self.nodes) do
|
|
if curr_node.deps then
|
|
local remove_idx
|
|
for idx, dep_node_key in ipairs(self.nodes) do
|
|
if dep_node_key == node_key then
|
|
remove_idx = idx
|
|
break
|
|
end
|
|
end
|
|
if remove_idx then table.remove(curr_node.deps, remove_idx) end
|
|
end
|
|
end
|
|
end
|
|
|
|
function DepGraph:addNodeDep(node_key, dep_node_key)
|
|
local node = self.nodes[node_key]
|
|
if not node then
|
|
node = {}
|
|
self.nodes[node_key] = node
|
|
end
|
|
if not node.deps then node.deps = {} end
|
|
table.insert(node.deps, dep_node_key)
|
|
end
|
|
|
|
function DepGraph:serialize()
|
|
local visited = {}
|
|
local ordered_nodes = {}
|
|
for node_key,_ in pairs(self.nodes) do
|
|
if not visited[node_key] then
|
|
local queue = {node_key}
|
|
while #queue > 0 do
|
|
local pos = #queue
|
|
local curr_node_key = queue[pos]
|
|
local curr_node = self.nodes[curr_node_key]
|
|
local all_deps_visited = true
|
|
if curr_node.deps then
|
|
for _, dep_node_key in ipairs(curr_node.deps) do
|
|
if not visited[dep_node_key] then
|
|
-- only insert to queue for later process if node
|
|
-- has dependencies
|
|
if self.nodes[dep_node_key].deps then
|
|
table.insert(queue, dep_node_key)
|
|
else
|
|
table.insert(ordered_nodes, dep_node_key)
|
|
end
|
|
visited[dep_node_key] = true
|
|
all_deps_visited = false
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if all_deps_visited then
|
|
visited[curr_node_key] = true
|
|
table.remove(queue, pos)
|
|
table.insert(ordered_nodes, curr_node_key)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return ordered_nodes
|
|
end
|
|
|
|
return DepGraph
|