mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
doc: event propagation for widgets
This commit is contained in:
@@ -1,20 +1,17 @@
|
|||||||
Data Store
|
Data Store
|
||||||
==========
|
==========
|
||||||
|
|
||||||
LuaSettings
|
## LuaSettings ##
|
||||||
-----------
|
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
|
|
||||||
DocSettings
|
## DocSettings ##
|
||||||
-----------
|
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
|
|
||||||
SQLite3
|
## SQLite3 ##
|
||||||
-------
|
|
||||||
|
|
||||||
KOReader ships with the SQLite3 library, which is a great embedded database for
|
KOReader ships with the SQLite3 library, which is a great embedded database for
|
||||||
desktop and mobile applications.
|
desktop and mobile applications.
|
||||||
|
|||||||
@@ -1,10 +1,45 @@
|
|||||||
Builtin Events
|
Events
|
||||||
==============
|
======
|
||||||
|
|
||||||
Reader Events
|
## Overview ##
|
||||||
-------------
|
|
||||||
|
All widgets is a subclass of @{ui.widget.eventlistener}, therefore inherit
|
||||||
|
the @{ui.widget.eventlistener:handleEvent|handleEvent} method. To send an event
|
||||||
|
to a widget, you can simply invoke the handleEvent method like the following:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
widget_foo:handleEvent(Event:new("Timeout"))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Builtin events ##
|
||||||
|
|
||||||
|
### Reader events ###
|
||||||
|
|
||||||
* UpdatePos: emitted by typesetting related modules to notify other modules to
|
* UpdatePos: emitted by typesetting related modules to notify other modules to
|
||||||
recalculate the view based on the new typesetting.
|
recalculate the view based on the new typesetting.
|
||||||
|
|
||||||
* PosUpdate: emitted by readerrolling module to signal a change in pos.
|
* PosUpdate: emitted by readerrolling module to signal a change in pos.
|
||||||
|
|
||||||
|
|
||||||
|
## Event propagation ##
|
||||||
|
|
||||||
|
Most of the UI components is a subclass of
|
||||||
|
@{ui.widget.container.widgetcontainer|WidgetContainer}. A WidgetContainer is an array that
|
||||||
|
stores a list of children widgets.
|
||||||
|
|
||||||
|
When @{ui.widget.container.widgetcontainer:handleEvent|WidgetContainer:handleEvent} is called with a new
|
||||||
|
event, it will run roughly the following code:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- First propagate event to its children
|
||||||
|
for _, widget in ipairs(self) do
|
||||||
|
if widget:handleEvent(event) then
|
||||||
|
-- stop propagating when an event handler returns true
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- If not consumed by children, try consume by itself
|
||||||
|
return self["on"..event.name](self, unpack(event.args))
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
Hacking
|
Hacking
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Developing UI Widgets
|
## Developing UI widgets ##
|
||||||
---------------------
|
|
||||||
|
|
||||||
`tools/wbuilder.lua` is your friend, if you need to create new UI widgets. It
|
`tools/wbuilder.lua` is your friend, if you need to create new UI widgets. It
|
||||||
sets up a minimal environment to bootstrap KOReader's UI framework to avoid
|
sets up a minimal environment to bootstrap KOReader's UI framework to avoid
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ widgets event-aware see the implementation in @{ui.widget.container.widgetcontai
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
@field handler name for the handler method
|
@field handler name for the handler method: `"on"..Event.name`
|
||||||
@field args array of arguments for the event
|
@field args array of arguments for the event
|
||||||
@table Event
|
@table Event
|
||||||
]]
|
]]
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
--[[--
|
--[[--
|
||||||
WidgetContainer is a container for another Widget. Base class for all the widget containers.
|
WidgetContainer is a container for one or multiple Widgets. It is the base
|
||||||
|
class for all the container widgets.
|
||||||
|
|
||||||
It handles event propagation and paiting (with different alignments) for its children.
|
Child widgets are stored in WidgetContainer as conventional array items:
|
||||||
|
|
||||||
|
WidgetContainer:new{
|
||||||
|
ChildWidgetFoo:new{},
|
||||||
|
ChildWidgetBar:new{},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
It handles event propagation and painting (with different alignments) for its children.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local Geom = require("ui/geometry")
|
local Geom = require("ui/geometry")
|
||||||
@@ -85,8 +94,8 @@ end
|
|||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
WidgetContainer will pass event to its children by calling their handleEvent
|
WidgetContainer will pass event to its children by calling their handleEvent
|
||||||
methods. If no child responded to the event (by returning true), it will call its own
|
methods. If no child consumes the event (by returning true), it will try
|
||||||
handleEvent method.
|
to react to the event by itself.
|
||||||
|
|
||||||
@tparam ui.event.Event event
|
@tparam ui.event.Event event
|
||||||
@treturn bool true if event is consumed, othewise false. A consumed event will
|
@treturn bool true if event is consumed, othewise false. A consumed event will
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
--[[
|
--[[--
|
||||||
The EventListener is an interface that handles events
|
The EventListener is an interface that handles events. This is the base class
|
||||||
|
for @{ui.widget.widget}
|
||||||
|
|
||||||
EventListeners have a rudimentary event handler/dispatcher that
|
EventListeners have a rudimentary event handler/dispatcher that
|
||||||
will call a method "onEventName" for an event with name
|
will call a method "onEventName" for an event with name
|
||||||
"EventName"
|
"EventName"
|
||||||
--]]
|
]]
|
||||||
|
|
||||||
local EventListener = {}
|
local EventListener = {}
|
||||||
local DEBUG = require("dbg")
|
local DEBUG = require("dbg")
|
||||||
|
|
||||||
@@ -16,6 +18,15 @@ function EventListener:new(new_o)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Invoke handler method for an event.
|
||||||
|
|
||||||
|
Handler method name is determined by @{ui.event.Event}'s handler field.
|
||||||
|
By default, it's `"on"..Event.name`.
|
||||||
|
|
||||||
|
@tparam ui.event.Event event
|
||||||
|
@treturn bool return true if event is consumed successfully.
|
||||||
|
]]
|
||||||
function EventListener:handleEvent(event)
|
function EventListener:handleEvent(event)
|
||||||
if self[event.handler] then
|
if self[event.handler] then
|
||||||
if self.id or self.name then
|
if self.id or self.name then
|
||||||
|
|||||||
@@ -1,34 +1,40 @@
|
|||||||
local EventListener = require("ui/widget/eventlistener")
|
--[[--
|
||||||
|
This is a generic Widget interface, which is the base class for all other widgets.
|
||||||
|
|
||||||
--[[
|
Widgets can be queried about their size and can be painted on screen.
|
||||||
This is a generic Widget interface
|
|
||||||
|
|
||||||
widgets can be queried about their size and can be paint.
|
|
||||||
that's it for now. Probably we need something more elaborate
|
that's it for now. Probably we need something more elaborate
|
||||||
later.
|
later.
|
||||||
|
|
||||||
if the table that was given to us as parameter has an "init"
|
If the table that was given to us as parameter has an "init"
|
||||||
method, it will be called. use this to set _instance_ variables
|
method, it will be called. use this to set _instance_ variables
|
||||||
rather than class variables.
|
rather than class variables.
|
||||||
--]]
|
]]
|
||||||
|
|
||||||
|
local EventListener = require("ui/widget/eventlistener")
|
||||||
local Widget = EventListener:new()
|
local Widget = EventListener:new()
|
||||||
|
|
||||||
--[[
|
--[[--
|
||||||
Use this method to define a class that's inherited from current class.
|
Use this method to define a subclass widget class that's inherited from a
|
||||||
It only setup the metabale (or prototype chain) and will not initiatie
|
base class widget. It only setups the metabale (or prototype chain) and will
|
||||||
a real instance, i.e. call self:init()
|
not initiate a real instance, i.e. call self:init().
|
||||||
--]]
|
|
||||||
function Widget:extend(from_o)
|
@tparam Widget baseclass
|
||||||
local o = from_o or {}
|
@treturn Widget
|
||||||
|
]]
|
||||||
|
function Widget:extend(baseclass)
|
||||||
|
local o = baseclass or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[--
|
||||||
Use this method to initiatie a instance of a class, don't use it for class
|
Use this method to initiatie a instance of a class, don't use it for class
|
||||||
definition.
|
definition because it also calls self:init().
|
||||||
--]]
|
|
||||||
|
@tparam Widget o
|
||||||
|
@treturn Widget
|
||||||
|
]]
|
||||||
function Widget:new(o)
|
function Widget:new(o)
|
||||||
o = self:extend(o)
|
o = self:extend(o)
|
||||||
-- Both o._init and o.init are called on object creation. But o._init is
|
-- Both o._init and o.init are called on object creation. But o._init is
|
||||||
@@ -40,10 +46,26 @@ function Widget:new(o)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
FIXME: enable this doc section when we verified all self.dimen is a Geom so we
|
||||||
|
can return self.dime:copy().
|
||||||
|
|
||||||
|
Return size of the widget.
|
||||||
|
|
||||||
|
@treturn ui.geometry.Geom
|
||||||
|
--]]
|
||||||
function Widget:getSize()
|
function Widget:getSize()
|
||||||
return self.dimen
|
return self.dimen
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Paint widget to a BlitBuffer.
|
||||||
|
|
||||||
|
@tparam BlitBuffer BlitBuffer to paint to. If it's the screen BlitBuffer, then
|
||||||
|
widget will show up on screen refresh.
|
||||||
|
@int x x offset within the BlitBuffer
|
||||||
|
@int y y offset within the BlitBuffer
|
||||||
|
]]
|
||||||
function Widget:paintTo(bb, x, y)
|
function Widget:paintTo(bb, x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user