From fadee1f5dc5ffb6cd386a2fdadea4290e174069d Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Thu, 6 Oct 2022 02:14:48 +0200 Subject: [PATCH] Clarify our OOP semantics across the codebase (#9586) Basically: * Use `extend` for class definitions * Use `new` for object instantiations That includes some minor code cleanups along the way: * Updated `Widget`'s docs to make the semantics clearer. * Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283) * Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass). * Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events. * Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier. * Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references. * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak). * Terminal: Make sure the shell is killed on plugin teardown. * InputText: Fix Home/End/Del physical keys to behave sensibly. * InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...). * OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of. * ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed! * Kobo: Minor code cleanups. --- base | 2 +- frontend/apps/filemanager/filemanager.lua | 1 + .../apps/filemanager/filemanagerbookinfo.lua | 4 +- .../filemanager/filemanagercollection.lua | 4 +- .../filemanager/filemanagerfilesearcher.lua | 18 +- .../apps/filemanager/filemanagerhistory.lua | 4 +- frontend/apps/filemanager/filemanagermenu.lua | 32 ++- .../filemanager/filemanagersetdefaults.lua | 3 +- .../apps/filemanager/filemanagershortcuts.lua | 4 +- frontend/apps/reader/modules/readerback.lua | 4 +- .../apps/reader/modules/readerbookmark.lua | 2 +- frontend/apps/reader/modules/readerconfig.lua | 5 +- .../reader/modules/readercoptlistener.lua | 2 +- .../apps/reader/modules/readercropping.lua | 8 +- .../reader/modules/readerdevicestatus.lua | 4 +- .../apps/reader/modules/readerdictionary.lua | 9 +- frontend/apps/reader/modules/readerdogear.lua | 4 +- .../apps/reader/modules/readerflipping.lua | 4 +- frontend/apps/reader/modules/readerfont.lua | 2 +- frontend/apps/reader/modules/readerfooter.lua | 2 +- frontend/apps/reader/modules/readergoto.lua | 5 +- .../apps/reader/modules/readerhighlight.lua | 3 +- .../apps/reader/modules/readerhinting.lua | 8 +- .../reader/modules/readerkoptlistener.lua | 2 +- frontend/apps/reader/modules/readerlink.lua | 6 +- frontend/apps/reader/modules/readermenu.lua | 6 +- .../apps/reader/modules/readerpagemap.lua | 4 +- frontend/apps/reader/modules/readerpaging.lua | 4 +- .../apps/reader/modules/readerpanning.lua | 2 +- .../apps/reader/modules/readerrolling.lua | 4 +- .../apps/reader/modules/readerrotation.lua | 4 +- .../apps/reader/modules/readerscrolling.lua | 7 +- frontend/apps/reader/modules/readersearch.lua | 4 +- frontend/apps/reader/modules/readerstatus.lua | 12 +- .../apps/reader/modules/readerstyletweak.lua | 5 +- .../apps/reader/modules/readerthumbnail.lua | 4 +- frontend/apps/reader/modules/readertoc.lua | 6 +- .../apps/reader/modules/readertypeset.lua | 6 +- .../apps/reader/modules/readertypography.lua | 4 +- .../apps/reader/modules/readeruserhyph.lua | 2 +- frontend/apps/reader/modules/readerview.lua | 60 +++--- .../apps/reader/modules/readerwikipedia.lua | 2 +- .../apps/reader/modules/readerzooming.lua | 16 +- frontend/apps/reader/readerui.lua | 6 +- frontend/cache.lua | 5 - frontend/cacheitem.lua | 5 +- frontend/device/android/device.lua | 17 +- frontend/device/cervantes/device.lua | 12 +- frontend/device/devicelistener.lua | 4 +- frontend/device/dummy/device.lua | 2 +- frontend/device/generic/device.lua | 4 +- frontend/device/generic/powerd.lua | 7 - frontend/device/gesturedetector.lua | 3 +- frontend/device/kindle/device.lua | 38 ++-- frontend/device/kobo/device.lua | 102 ++++------ frontend/device/pocketbook/device.lua | 62 +++--- frontend/device/remarkable/device.lua | 6 +- frontend/device/sdl/device.lua | 10 +- frontend/device/sony-prstux/device.lua | 4 +- frontend/device/wakeupmgr.lua | 6 +- frontend/docsettings.lua | 188 +++--------------- frontend/document/canvascontext.lua | 3 - frontend/document/credocument.lua | 30 ++- frontend/document/djvudocument.lua | 2 +- frontend/document/doccache.lua | 1 + frontend/document/document.lua | 19 +- frontend/document/documentregistry.lua | 4 +- frontend/document/pdfdocument.lua | 2 +- frontend/document/picdocument.lua | 2 +- frontend/document/tilecacheitem.lua | 2 +- frontend/dump.lua | 15 +- frontend/languagesupport.lua | 6 +- frontend/luadata.lua | 30 ++- frontend/luadefaults.lua | 17 +- frontend/luasettings.lua | 26 +-- frontend/pluginloader.lua | 2 +- frontend/pluginshare.lua | 5 +- frontend/readhistory.lua | 23 +-- frontend/socketutil.lua | 3 - .../ui/data/keyboardlayouts/ko_KR_helper.lua | 2 +- frontend/ui/data/keyboardlayouts/zh_ime.lua | 4 +- frontend/ui/hook_container.lua | 3 - frontend/ui/message/filemessagequeue.lua | 2 +- frontend/ui/message/messagequeue.lua | 9 +- frontend/ui/message/streammessagequeue.lua | 2 +- frontend/ui/network/networklistener.lua | 4 +- frontend/ui/plugin/switch_plugin.lua | 2 +- frontend/ui/rendertext.lua | 5 - frontend/ui/screensaver.lua | 4 +- frontend/ui/uimanager.lua | 4 +- frontend/ui/widget/bboxwidget.lua | 2 +- frontend/ui/widget/bookmapwidget.lua | 9 +- frontend/ui/widget/bookstatuswidget.lua | 29 ++- frontend/ui/widget/button.lua | 2 +- frontend/ui/widget/buttondialog.lua | 2 +- frontend/ui/widget/buttondialogtitle.lua | 2 +- frontend/ui/widget/buttonprogresswidget.lua | 2 +- frontend/ui/widget/buttontable.lua | 2 +- frontend/ui/widget/checkbutton.lua | 2 +- frontend/ui/widget/checkmark.lua | 4 +- frontend/ui/widget/closebutton.lua | 2 +- frontend/ui/widget/configdialog.lua | 12 +- frontend/ui/widget/confirmbox.lua | 2 +- .../ui/widget/container/alphacontainer.lua | 2 +- .../ui/widget/container/bottomcontainer.lua | 2 +- .../ui/widget/container/centercontainer.lua | 2 +- .../ui/widget/container/framecontainer.lua | 2 +- .../ui/widget/container/inputcontainer.lua | 29 +-- .../ui/widget/container/leftcontainer.lua | 2 +- .../ui/widget/container/movablecontainer.lua | 4 +- .../ui/widget/container/rightcontainer.lua | 2 +- .../widget/container/scrollablecontainer.lua | 2 +- frontend/ui/widget/container/topcontainer.lua | 2 +- .../widget/container/underlinecontainer.lua | 2 +- .../ui/widget/container/widgetcontainer.lua | 77 +++---- frontend/ui/widget/dictquicklookup.lua | 2 +- frontend/ui/widget/doublespinwidget.lua | 2 +- frontend/ui/widget/eventlistener.lua | 9 +- frontend/ui/widget/filechooser.lua | 7 +- frontend/ui/widget/fixedtextwidget.lua | 2 +- frontend/ui/widget/focusmanager.lua | 39 ++-- frontend/ui/widget/footnotewidget.lua | 4 +- frontend/ui/widget/frontlightwidget.lua | 2 +- frontend/ui/widget/horizontalgroup.lua | 2 +- frontend/ui/widget/horizontalscrollbar.lua | 2 +- frontend/ui/widget/horizontalspan.lua | 2 +- frontend/ui/widget/htmlboxwidget.lua | 2 +- frontend/ui/widget/iconbutton.lua | 2 +- frontend/ui/widget/imageviewer.lua | 2 +- frontend/ui/widget/imagewidget.lua | 2 +- frontend/ui/widget/infomessage.lua | 2 +- frontend/ui/widget/inputdialog.lua | 2 +- frontend/ui/widget/inputtext.lua | 28 ++- frontend/ui/widget/keyboardlayoutdialog.lua | 2 +- frontend/ui/widget/keyvaluepage.lua | 8 +- frontend/ui/widget/linewidget.lua | 2 +- frontend/ui/widget/linkbox.lua | 2 +- frontend/ui/widget/listview.lua | 4 +- frontend/ui/widget/menu.lua | 11 +- frontend/ui/widget/multiconfirmbox.lua | 2 +- frontend/ui/widget/multiinputdialog.lua | 39 ++-- frontend/ui/widget/naturallightwidget.lua | 5 +- frontend/ui/widget/networksetting.lua | 8 +- frontend/ui/widget/notification.lua | 4 +- frontend/ui/widget/overlapgroup.lua | 26 ++- frontend/ui/widget/pagebrowserwidget.lua | 2 +- frontend/ui/widget/physicalkeyboard.lua | 8 +- frontend/ui/widget/progresswidget.lua | 2 +- frontend/ui/widget/qrmessage.lua | 2 +- frontend/ui/widget/radiobutton.lua | 2 +- frontend/ui/widget/radiobuttontable.lua | 2 +- frontend/ui/widget/radiobuttonwidget.lua | 2 +- frontend/ui/widget/radiomark.lua | 4 +- frontend/ui/widget/rectspan.lua | 2 +- frontend/ui/widget/screensaverwidget.lua | 2 +- frontend/ui/widget/screenshoter.lua | 2 +- frontend/ui/widget/scrollhtmlwidget.lua | 2 +- frontend/ui/widget/scrolltextwidget.lua | 12 +- frontend/ui/widget/skimtowidget.lua | 2 +- frontend/ui/widget/sortwidget.lua | 8 +- frontend/ui/widget/spinwidget.lua | 2 +- frontend/ui/widget/textboxwidget.lua | 18 +- frontend/ui/widget/textviewer.lua | 2 +- frontend/ui/widget/textwidget.lua | 2 +- frontend/ui/widget/titlebar.lua | 5 +- frontend/ui/widget/toggleswitch.lua | 4 +- frontend/ui/widget/touchmenu.lua | 10 +- frontend/ui/widget/trapwidget.lua | 2 +- frontend/ui/widget/verticalgroup.lua | 2 +- frontend/ui/widget/verticalscrollbar.lua | 2 +- frontend/ui/widget/verticalspan.lua | 2 +- frontend/ui/widget/virtualkeyboard.lua | 31 +-- frontend/ui/widget/widget.lua | 34 ++-- plugins/SSH.koplugin/main.lua | 2 +- plugins/autodim.koplugin/main.lua | 4 +- plugins/autofrontlight.koplugin/main.lua | 2 +- plugins/autostandby.koplugin/main.lua | 2 +- plugins/autosuspend.koplugin/main.lua | 2 +- plugins/autoturn.koplugin/main.lua | 2 +- plugins/autowarmth.koplugin/main.lua | 6 +- .../commandrunner.lua | 3 - plugins/backgroundrunner.koplugin/main.lua | 7 +- plugins/batterystat.koplugin/main.lua | 2 +- plugins/bookshortcuts.koplugin/main.lua | 2 +- plugins/calibre.koplugin/main.lua | 2 +- plugins/calibre.koplugin/search.lua | 5 +- plugins/calibre.koplugin/wireless.lua | 7 +- plugins/coverbrowser.koplugin/listmenu.lua | 6 +- plugins/coverbrowser.koplugin/main.lua | 4 +- plugins/coverbrowser.koplugin/mosaicmenu.lua | 8 +- plugins/coverimage.koplugin/main.lua | 2 +- plugins/docsettingtweak.koplugin/main.lua | 2 +- plugins/exporter.koplugin/main.lua | 4 +- plugins/gestures.koplugin/main.lua | 4 +- plugins/gestures.koplugin/migration.lua | 2 +- plugins/hello.koplugin/main.lua | 2 +- plugins/japanese.koplugin/main.lua | 6 +- plugins/keepalive.koplugin/main.lua | 2 +- plugins/kosync.koplugin/main.lua | 16 +- plugins/movetoarchive.koplugin/main.lua | 2 +- plugins/newsdownloader.koplugin/main.lua | 4 +- plugins/opds.koplugin/main.lua | 2 +- plugins/opds.koplugin/opdscatalog.lua | 4 +- plugins/profiles.koplugin/main.lua | 2 +- plugins/qrclipboard.koplugin/main.lua | 2 +- plugins/readtimer.koplugin/main.lua | 2 +- plugins/statistics.koplugin/calendarview.lua | 8 +- plugins/statistics.koplugin/main.lua | 29 +-- .../statistics.koplugin/readerprogress.lua | 3 +- plugins/systemstat.koplugin/main.lua | 2 +- plugins/terminal.koplugin/main.lua | 7 +- plugins/terminal.koplugin/terminputtext.lua | 10 +- plugins/texteditor.koplugin/main.lua | 2 +- plugins/timesync.koplugin/main.lua | 2 +- plugins/vocabbuilder.koplugin/db.lua | 2 +- plugins/vocabbuilder.koplugin/main.lua | 10 +- plugins/wallabag.koplugin/main.lua | 2 +- spec/unit/koptinterface_spec.lua | 4 +- spec/unit/mock_time.lua | 12 -- spec/unit/readerhighlight_spec.lua | 2 +- spec/unit/readerview_spec.lua | 1 - spec/unit/wakeupmgr_spec.lua | 2 +- tools/kobo_touch_probe.lua | 6 +- 223 files changed, 848 insertions(+), 984 deletions(-) diff --git a/base b/base index bdc6cb8fb..748466876 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit bdc6cb8fb0669094bc5c9da1b9326b39674bb4f2 +Subproject commit 7484668769f8e72d3be62762501aacf0a9b22870 diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 660133db8..ed97624cd 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -44,6 +44,7 @@ local T = BaseUtil.template local FileManager = InputContainer:extend{ title = _("KOReader"), + active_widgets = nil, -- array root_path = lfs.currentdir(), clipboard = nil, -- for single file operations diff --git a/frontend/apps/filemanager/filemanagerbookinfo.lua b/frontend/apps/filemanager/filemanagerbookinfo.lua index 2db5949fd..833292d51 100644 --- a/frontend/apps/filemanager/filemanagerbookinfo.lua +++ b/frontend/apps/filemanager/filemanagerbookinfo.lua @@ -7,15 +7,15 @@ local DocSettings = require("docsettings") local DocumentRegistry = require("document/documentregistry") local ImageViewer = require("ui/widget/imageviewer") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local KeyValuePage = require("ui/widget/keyvaluepage") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local filemanagerutil = require("apps/filemanager/filemanagerutil") local lfs = require("libs/libkoreader-lfs") local util = require("util") local _ = require("gettext") -local BookInfo = InputContainer:extend{ +local BookInfo = WidgetContainer:extend{ bookinfo_menu_title = _("Book information"), } diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index 235bc4552..8f3122af4 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -3,17 +3,17 @@ local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local Device = require("device") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local Menu = require("ui/widget/menu") local ReadCollection = require("readcollection") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = require("device").screen local BaseUtil = require("ffi/util") local util = require("util") local _ = require("gettext") local T = BaseUtil.template -local FileManagerCollection = InputContainer:extend{ +local FileManagerCollection = WidgetContainer:extend{ coll_menu_title = _("Favorites"), } diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index 7e6019750..152e66a30 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -4,23 +4,23 @@ local CenterContainer = require("ui/widget/container/centercontainer") local DocumentRegistry = require("document/documentregistry") local FileChooser = require("ui/widget/filechooser") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local Menu = require("ui/widget/menu") local Size = require("ui/size") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") +local BaseUtil = require("ffi/util") local Utf8Proc = require("ffi/utf8proc") local lfs = require("libs/libkoreader-lfs") -local BaseUtil = require("ffi/util") local util = require("util") local _ = require("gettext") local Screen = require("device").screen local T = require("ffi/util").template -local FileSearcher = InputContainer:new{ - dirs = {}, - files = {}, - results = {}, +local FileSearcher = WidgetContainer:extend{ + dirs = nil, -- table + files = nil, -- table + results = nil, -- table case_sensitive = false, include_subfolders = true, @@ -32,6 +32,12 @@ local sys_folders = { -- do not search in sys_folders ["/sys"] = true, } +function FileSearcher:init() + self.dirs = {} + self.files = {} + self.results = {} +end + function FileSearcher:readDir() local ReaderUI = require("apps/reader/readerui") local show_unsupported = G_reader_settings:isTrue("show_unsupported") diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index eabb67e98..936616e23 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -4,9 +4,9 @@ local ConfirmBox = require("ui/widget/confirmbox") local DocSettings = require("docsettings") local FFIUtil = require("ffi/util") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") -local InputContainer = require("ui/widget/container/inputcontainer") local Menu = require("ui/widget/menu") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = require("device").screen local filemanagerutil = require("apps/filemanager/filemanagerutil") local lfs = require("libs/libkoreader-lfs") @@ -14,7 +14,7 @@ local _ = require("gettext") local C_ = _.pgettext local T = FFIUtil.template -local FileManagerHistory = InputContainer:extend{ +local FileManagerHistory = WidgetContainer:extend{ hist_menu_title = _("History"), } diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 019278aa9..369b683af 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -19,7 +19,7 @@ local T = FFIUtil.template local FileManagerMenu = InputContainer:extend{ tab_item_table = nil, - menu_items = {}, + menu_items = nil, -- table, mandatory registered_widgets = nil, } @@ -522,22 +522,20 @@ To: end, }) end - if not Device.should_restrict_JIT then - local Blitbuffer = require("ffi/blitbuffer") - table.insert(self.menu_items.developer_options.sub_item_table, { - text = _("Disable C blitter"), - enabled_func = function() - return Blitbuffer.has_cblitbuffer - end, - checked_func = function() - return G_reader_settings:isTrue("dev_no_c_blitter") - end, - callback = function() - G_reader_settings:flipNilOrFalse("dev_no_c_blitter") - Blitbuffer:enableCBB(G_reader_settings:nilOrFalse("dev_no_c_blitter")) - end, - }) - end + local Blitbuffer = require("ffi/blitbuffer") + table.insert(self.menu_items.developer_options.sub_item_table, { + text = _("Disable C blitter"), + enabled_func = function() + return Blitbuffer.has_cblitbuffer + end, + checked_func = function() + return G_reader_settings:isTrue("dev_no_c_blitter") + end, + callback = function() + G_reader_settings:flipNilOrFalse("dev_no_c_blitter") + Blitbuffer:enableCBB(G_reader_settings:nilOrFalse("dev_no_c_blitter")) + end, + }) if Device:hasEinkScreen() and Device:canHWDither() then table.insert(self.menu_items.developer_options.sub_item_table, { text = _("Disable HW dithering"), diff --git a/frontend/apps/filemanager/filemanagersetdefaults.lua b/frontend/apps/filemanager/filemanagersetdefaults.lua index 49817ac14..7ecdfbb58 100644 --- a/frontend/apps/filemanager/filemanagersetdefaults.lua +++ b/frontend/apps/filemanager/filemanagersetdefaults.lua @@ -21,11 +21,10 @@ local SetDefaultsWidget = CenterContainer:extend{ } function SetDefaultsWidget:init() - -- We're a CenterContainer, so handle our own stuff first + -- This would usually be passed to the constructor, as CenterContainer's paintTo does *NOT* set/update self.dimen... self.dimen = Screen:getSize() -- Don't refresh the FM behind us. May leave stray bits of overflowed InputDialog behind in the popout border space. self.covers_fullscreen = true - CenterContainer.init(self) -- Then deal with our child widgets and our internal variables self.screen_width = Screen:getWidth() diff --git a/frontend/apps/filemanager/filemanagershortcuts.lua b/frontend/apps/filemanager/filemanagershortcuts.lua index ca218acd7..f8057f9b7 100644 --- a/frontend/apps/filemanager/filemanagershortcuts.lua +++ b/frontend/apps/filemanager/filemanagershortcuts.lua @@ -1,17 +1,17 @@ local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local Menu = require("ui/widget/menu") local Screen = require("device").screen local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local util = require("ffi/util") local _ = require("gettext") local T = util.template -local FileManagerShortcuts = InputContainer:extend{ +local FileManagerShortcuts = WidgetContainer:extend{ folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts", {}), } diff --git a/frontend/apps/reader/modules/readerback.lua b/frontend/apps/reader/modules/readerback.lua index ef29cd7ff..8f69bdc6b 100644 --- a/frontend/apps/reader/modules/readerback.lua +++ b/frontend/apps/reader/modules/readerback.lua @@ -13,8 +13,8 @@ local _ = require("gettext") -- additionally handles a location stack for each visited page or -- page view change (when scrolling in a same page) -local ReaderBack = EventListener:new{ - location_stack = {}, +local ReaderBack = EventListener:extend{ + location_stack = nil, -- array -- a limit not intended to be a practical limit but just a failsafe max_stack = 5000, } diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index e3a09c143..bf647459c 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -31,7 +31,7 @@ local DISPLAY_PREFIX = { bookmark = "\u{F097}\u{2002}", -- "empty bookmark" } -local ReaderBookmark = InputContainer:new{ +local ReaderBookmark = InputContainer:extend{ bookmarks_items_per_page_default = 14, bookmarks = nil, } diff --git a/frontend/apps/reader/modules/readerconfig.lua b/frontend/apps/reader/modules/readerconfig.lua index 68456e2c9..6b36a02e2 100644 --- a/frontend/apps/reader/modules/readerconfig.lua +++ b/frontend/apps/reader/modules/readerconfig.lua @@ -1,14 +1,13 @@ local ConfigDialog = require("ui/widget/configdialog") local Device = require("device") local Event = require("ui/event") -local Geom = require("ui/geometry") local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") local CreOptions = require("ui/data/creoptions") local KoptOptions = require("ui/data/koptoptions") local _ = require("gettext") -local ReaderConfig = InputContainer:new{ +local ReaderConfig = InputContainer:extend{ last_panel_index = 1, } @@ -20,7 +19,6 @@ function ReaderConfig:init() end self.configurable:loadDefaults(self.options) - if not self.dimen then self.dimen = Geom:new{} end if Device:hasKeys() then self.key_events = { ShowConfigMenu = { {{"Press","AA"}}, doc = "show config dialog" }, @@ -120,7 +118,6 @@ end function ReaderConfig:onShowConfigMenu() self.config_dialog = ConfigDialog:new{ - dimen = self.dimen:copy(), document = self.document, ui = self.ui, configurable = self.configurable, diff --git a/frontend/apps/reader/modules/readercoptlistener.lua b/frontend/apps/reader/modules/readercoptlistener.lua index 1213ee673..4226baebd 100644 --- a/frontend/apps/reader/modules/readercoptlistener.lua +++ b/frontend/apps/reader/modules/readercoptlistener.lua @@ -8,7 +8,7 @@ local logger = require("logger") local T = require("ffi/util").template local _ = require("gettext") -local ReaderCoptListener = EventListener:new{} +local ReaderCoptListener = EventListener:extend{} local CRE_HEADER_DEFAULT_SIZE = 20 diff --git a/frontend/apps/reader/modules/readercropping.lua b/frontend/apps/reader/modules/readercropping.lua index e8469ca28..626ab84bf 100644 --- a/frontend/apps/reader/modules/readercropping.lua +++ b/frontend/apps/reader/modules/readercropping.lua @@ -5,15 +5,15 @@ local CenterContainer = require("ui/widget/container/centercontainer") local Event = require("ui/event") local FrameContainer = require("ui/widget/container/framecontainer") local Geom = require("ui/geometry") -local InputContainer = require("ui/widget/container/inputcontainer") local Math = require("optmath") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local VerticalGroup = require("ui/widget/verticalgroup") local Device = require("device") local Screen = Device.screen local _ = require("gettext") -local ReaderCropping = InputContainer:new{} +local ReaderCropping = WidgetContainer:extend{} function ReaderCropping:onPageCrop(mode) self.ui:handleEvent(Event:new("CloseConfigMenu")) @@ -171,7 +171,9 @@ function ReaderCropping:setZoomMode(mode) end function ReaderCropping:onReadSettings(config) - self.document.bbox = config:readSetting("bbox") + if config:has("bbox") then + self.document.bbox = config:readSetting("bbox") + end end function ReaderCropping:onSaveSettings() diff --git a/frontend/apps/reader/modules/readerdevicestatus.lua b/frontend/apps/reader/modules/readerdevicestatus.lua index 930b88d8a..b5fa0da67 100644 --- a/frontend/apps/reader/modules/readerdevicestatus.lua +++ b/frontend/apps/reader/modules/readerdevicestatus.lua @@ -2,15 +2,15 @@ local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local SpinWidget = require("ui/widget/spinwidget") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local powerd = Device:getPowerDevice() local _ = require("gettext") local C_ = _.pgettext local T = require("ffi/util").template -local ReaderDeviceStatus = InputContainer:new{ +local ReaderDeviceStatus = WidgetContainer:extend{ battery_confirm_box = nil, memory_confirm_box = nil, } diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index 92dea8c56..e3f87e31e 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -6,7 +6,6 @@ local DictQuickLookup = require("ui/widget/dictquicklookup") local Event = require("ui/event") local Geom = require("ui/geometry") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local JSON = require("json") local KeyValuePage = require("ui/widget/keyvaluepage") @@ -16,6 +15,7 @@ local NetworkMgr = require("ui/network/manager") local SortWidget = require("ui/widget/sortwidget") local Trapper = require("ui/trapper") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local ffi = require("ffi") local C = ffi.C local ffiUtil = require("ffi/util") @@ -60,9 +60,9 @@ local function getIfosInDir(path) return ifos end -local ReaderDictionary = InputContainer:new{ +local ReaderDictionary = WidgetContainer:extend{ data_dir = nil, - dict_window_list = {}, + dict_window_list = nil, -- array lookup_msg = _("Searching dictionary for:\n%1"), } @@ -100,6 +100,7 @@ local function getDictionaryFixHtmlFunc(path) end function ReaderDictionary:init() + self.dict_window_list = {} self.disable_lookup_history = G_reader_settings:isTrue("disable_lookup_history") self.dicts_order = G_reader_settings:readSetting("dicts_order", {}) self.dicts_disabled = G_reader_settings:readSetting("dicts_disabled", {}) @@ -156,7 +157,7 @@ function ReaderDictionary:init() self:updateSdcvDictNamesOptions() if not lookup_history then - lookup_history = LuaData:open(DataStorage:getSettingsDir() .. "/lookup_history.lua", { name = "LookupHistory" }) + lookup_history = LuaData:open(DataStorage:getSettingsDir() .. "/lookup_history.lua", "LookupHistory") end end diff --git a/frontend/apps/reader/modules/readerdogear.lua b/frontend/apps/reader/modules/readerdogear.lua index f532d4fb7..7e0ef2883 100644 --- a/frontend/apps/reader/modules/readerdogear.lua +++ b/frontend/apps/reader/modules/readerdogear.lua @@ -2,13 +2,13 @@ local BD = require("ui/bidi") local Device = require("device") local Geom = require("ui/geometry") local IconWidget = require("ui/widget/iconwidget") -local InputContainer = require("ui/widget/container/inputcontainer") local RightContainer = require("ui/widget/container/rightcontainer") local VerticalGroup = require("ui/widget/verticalgroup") local VerticalSpan = require("ui/widget/verticalspan") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = Device.screen -local ReaderDogear = InputContainer:new{} +local ReaderDogear = WidgetContainer:extend{} function ReaderDogear:init() -- This image could be scaled for DPI (with scale_for_dpi=true, scale_factor=0.7), diff --git a/frontend/apps/reader/modules/readerflipping.lua b/frontend/apps/reader/modules/readerflipping.lua index 94c488d59..b6260ea18 100644 --- a/frontend/apps/reader/modules/readerflipping.lua +++ b/frontend/apps/reader/modules/readerflipping.lua @@ -1,10 +1,10 @@ local Geom = require("ui/geometry") local IconWidget = require("ui/widget/iconwidget") -local InputContainer = require("ui/widget/container/inputcontainer") local LeftContainer = require("ui/widget/container/leftcontainer") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = require("device").screen -local ReaderFlipping = InputContainer:new{ +local ReaderFlipping = WidgetContainer:extend{ orig_reflow_mode = 0, } diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index f91aba7af..c66d05cee 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -19,7 +19,7 @@ local _ = require("gettext") local C_ = _.pgettext local optionsutil = require("ui/data/optionsutil") -local ReaderFont = InputContainer:new{ +local ReaderFont = InputContainer:extend{ font_face = nil, font_size = nil, line_space_percent = nil, diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index ca617dc73..ccded517c 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -444,7 +444,7 @@ local ReaderFooter = WidgetContainer:extend{ height = Screen:scaleBySize(G_defaults:readSetting("DMINIBAR_CONTAINER_HEIGHT")), horizontal_margin = Size.span.horizontal_default, bottom_padding = Size.padding.tiny, - settings = {}, + settings = nil, -- table -- added to expose them to unit tests textGeneratorMap = footerTextGeneratorMap, } diff --git a/frontend/apps/reader/modules/readergoto.lua b/frontend/apps/reader/modules/readergoto.lua index 25d6ebc0e..d477a32d4 100644 --- a/frontend/apps/reader/modules/readergoto.lua +++ b/frontend/apps/reader/modules/readergoto.lua @@ -1,13 +1,12 @@ local Event = require("ui/event") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local SkimToWidget = require("ui/widget/skimtowidget") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") local T = require("ffi/util").template -local ReaderGoto = InputContainer:new{ -} +local ReaderGoto = WidgetContainer:extend{} function ReaderGoto:init() self.ui.menu:registerToMainMenu(self) diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 7c9a896d5..34c839ac2 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -20,8 +20,7 @@ local C_ = _.pgettext local T = require("ffi/util").template local Screen = Device.screen -local ReaderHighlight = InputContainer:new{ -} +local ReaderHighlight = InputContainer:extend{} local function inside_box(pos, box) if pos then diff --git a/frontend/apps/reader/modules/readerhinting.lua b/frontend/apps/reader/modules/readerhinting.lua index 5d18eef36..e1a24288d 100644 --- a/frontend/apps/reader/modules/readerhinting.lua +++ b/frontend/apps/reader/modules/readerhinting.lua @@ -2,10 +2,14 @@ local EventListener = require("ui/widget/eventlistener") local DHINTCOUNT = G_defaults:readSetting("DHINTCOUNT") -local ReaderHinting = EventListener:new{ - hinting_states = {} +local ReaderHinting = EventListener:extend{ + hinting_states = nil, -- array } +function ReaderHinting:init() + self.hinting_states = {} +end + function ReaderHinting:onHintPage() if not self.view.hinting then return true end for i=1, DHINTCOUNT do diff --git a/frontend/apps/reader/modules/readerkoptlistener.lua b/frontend/apps/reader/modules/readerkoptlistener.lua index 9e8782abf..d320c5b23 100644 --- a/frontend/apps/reader/modules/readerkoptlistener.lua +++ b/frontend/apps/reader/modules/readerkoptlistener.lua @@ -4,7 +4,7 @@ local ReaderZooming = require("apps/reader/modules/readerzooming") local UIManager = require("ui/uimanager") local util = require("util") -local ReaderKoptListener = EventListener:new{} +local ReaderKoptListener = EventListener:extend{} function ReaderKoptListener:setZoomMode(zoom_mode) if self.document.configurable.text_wrap == 1 then diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 39345ee86..77aa3bd4f 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -21,8 +21,8 @@ local _ = require("gettext") local Screen = Device.screen local T = ffiutil.template -local ReaderLink = InputContainer:new{ - location_stack = {} +local ReaderLink = InputContainer:extend{ + location_stack = nil, -- table, per-instance } function ReaderLink:init() @@ -154,7 +154,7 @@ function ReaderLink:addToMainMenu(menu_items) -- insert table to main reader menu menu_items.go_to_previous_location = { text = _("Go back to previous location"), - enabled_func = function() return #self.location_stack > 0 end, + enabled_func = function() return self.location_stack and #self.location_stack > 0 end, callback = function() self:onGoBackLink() end, hold_callback = function(touchmenu_instance) UIManager:show(ConfirmBox:new{ diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index d12d745ce..1d3139074 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -13,10 +13,10 @@ local Screen = Device.screen local _ = require("gettext") local T = require("ffi/util").template -local ReaderMenu = InputContainer:new{ +local ReaderMenu = InputContainer:extend{ tab_item_table = nil, - menu_items = {}, - registered_widgets = {}, + menu_items = nil, -- table, mandatory + registered_widgets = nil, -- array } function ReaderMenu:init() diff --git a/frontend/apps/reader/modules/readerpagemap.lua b/frontend/apps/reader/modules/readerpagemap.lua index e2e9844d6..53255a5d8 100644 --- a/frontend/apps/reader/modules/readerpagemap.lua +++ b/frontend/apps/reader/modules/readerpagemap.lua @@ -6,18 +6,18 @@ local Font = require("ui/font") local FrameContainer = require("ui/widget/container/framecontainer") local Geom = require("ui/geometry") local GestureRange = require("ui/gesturerange") -local InputContainer = require("ui/widget/container/inputcontainer") local Menu = require("ui/widget/menu") local MultiConfirmBox = require("ui/widget/multiconfirmbox") local OverlapGroup = require("ui/widget/overlapgroup") local TextBoxWidget = require("ui/widget/textboxwidget") local TextWidget = require("ui/widget/textwidget") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = Device.screen local T = require("ffi/util").template local _ = require("gettext") -local ReaderPageMap = InputContainer:new{ +local ReaderPageMap = WidgetContainer:extend{ label_font_face = "ffont", label_default_font_size = 14, -- Black so it's readable (and non-gray-flashing on GloHD) diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua index 685077849..022282bcd 100644 --- a/frontend/apps/reader/modules/readerpaging.lua +++ b/frontend/apps/reader/modules/readerpaging.lua @@ -27,7 +27,7 @@ local function copyPageState(page_state) end -local ReaderPaging = InputContainer:new{ +local ReaderPaging = InputContainer:extend{ pan_rate = 30, -- default 30 ops, will be adjusted in readerui current_page = 0, number_of_pages = 0, @@ -37,7 +37,7 @@ local ReaderPaging = InputContainer:new{ page_flipping_mode = false, bookmark_flipping_mode = false, - flip_steps = {0,1,2,5,10,20,50,100}, + flip_steps = {0, 1, 2, 5, 10, 20, 50, 100}, } function ReaderPaging:init() diff --git a/frontend/apps/reader/modules/readerpanning.lua b/frontend/apps/reader/modules/readerpanning.lua index 3410f5498..3deba99c3 100644 --- a/frontend/apps/reader/modules/readerpanning.lua +++ b/frontend/apps/reader/modules/readerpanning.lua @@ -2,7 +2,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local Device = require("device") local _ = require("gettext") -local ReaderPanning = InputContainer:new{ +local ReaderPanning = InputContainer:extend{ -- defaults panning_steps = { normal = 50, diff --git a/frontend/apps/reader/modules/readerrolling.lua b/frontend/apps/reader/modules/readerrolling.lua index 46deff1cf..32c25365e 100644 --- a/frontend/apps/reader/modules/readerrolling.lua +++ b/frontend/apps/reader/modules/readerrolling.lua @@ -39,12 +39,12 @@ local band = bit.band it in explicit page turning. And use that xpointer for non-page-turning rendering. --]] -local ReaderRolling = InputContainer:new{ +local ReaderRolling = InputContainer:extend{ pan_rate = 30, -- default 30 ops, will be adjusted in readerui rendering_hash = 0, current_pos = 0, -- only used for page view mode - current_page= nil, + current_page = nil, xpointer = nil, panning_steps = ReaderPanning.panning_steps, cre_top_bar_enabled = false, diff --git a/frontend/apps/reader/modules/readerrotation.lua b/frontend/apps/reader/modules/readerrotation.lua index e981457ba..96041fe5a 100644 --- a/frontend/apps/reader/modules/readerrotation.lua +++ b/frontend/apps/reader/modules/readerrotation.lua @@ -3,8 +3,8 @@ local Device = require("device") local Event = require("ui/event") local _ = require("gettext") -local ReaderRotation = InputContainer:new{ - current_rotation = 0 +local ReaderRotation = InputContainer:extend{ + current_rotation = 0, } function ReaderRotation:init() diff --git a/frontend/apps/reader/modules/readerscrolling.lua b/frontend/apps/reader/modules/readerscrolling.lua index 84e59fbf2..be8250019 100644 --- a/frontend/apps/reader/modules/readerscrolling.lua +++ b/frontend/apps/reader/modules/readerscrolling.lua @@ -1,7 +1,7 @@ local Device = require("device") local Event = require("ui/event") -local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local time = require("ui/time") local _ = require("gettext") @@ -16,7 +16,7 @@ local SCROLL_METHOD_CLASSIC = "classic" local SCROLL_METHOD_TURBO = "turbo" local SCROLL_METHOD_ON_RELEASE = "on_release" -local ReaderScrolling = InputContainer:new{ +local ReaderScrolling = WidgetContainer:extend{ -- Available scrolling methods (make them available to other reader modules) SCROLL_METHOD_CLASSIC = SCROLL_METHOD_CLASSIC, SCROLL_METHOD_TURBO = SCROLL_METHOD_TURBO, @@ -221,9 +221,6 @@ function ReaderScrolling:applyScrollSettings() end function ReaderScrolling:setupTouchZones() - self.ges_events = {} - self.onGesture = nil - local zones = { { id = "inertial_scrolling_touch", diff --git a/frontend/apps/reader/modules/readersearch.lua b/frontend/apps/reader/modules/readersearch.lua index bd8c69f58..67be190b6 100644 --- a/frontend/apps/reader/modules/readersearch.lua +++ b/frontend/apps/reader/modules/readersearch.lua @@ -3,10 +3,10 @@ local ButtonDialog = require("ui/widget/buttondialog") local CheckButton = require("ui/widget/checkbutton") local Device = require("device") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local Notification = require("ui/widget/notification") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local _ = require("gettext") local Screen = Device.screen @@ -14,7 +14,7 @@ local T = require("ffi/util").template local DGENERIC_ICON_SIZE = G_defaults:readSetting("DGENERIC_ICON_SIZE") -local ReaderSearch = InputContainer:new{ +local ReaderSearch = WidgetContainer:extend{ direction = 0, -- 0 for search forward, 1 for search backward case_insensitive = true, -- default to case insensitive diff --git a/frontend/apps/reader/modules/readerstatus.lua b/frontend/apps/reader/modules/readerstatus.lua index bc7e5361b..4bf7b9954 100644 --- a/frontend/apps/reader/modules/readerstatus.lua +++ b/frontend/apps/reader/modules/readerstatus.lua @@ -4,22 +4,16 @@ local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local Device = require("device") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local util = require("util") local _ = require("gettext") local T = require("ffi/util").template -local ReaderStatus = InputContainer:new { +local ReaderStatus = WidgetContainer:extend{ document = nil, - summary = { - rating = 0, - note = nil, - status = "", - modified = "", - }, enabled = true, - total_pages = 0 + total_pages = 0, } function ReaderStatus:init() diff --git a/frontend/apps/reader/modules/readerstyletweak.lua b/frontend/apps/reader/modules/readerstyletweak.lua index 51ceced29..099c2dbef 100644 --- a/frontend/apps/reader/modules/readerstyletweak.lua +++ b/frontend/apps/reader/modules/readerstyletweak.lua @@ -19,6 +19,7 @@ local TextBoxWidget = require("ui/widget/textboxwidget") local UIManager = require("ui/uimanager") local VerticalGroup = require("ui/widget/verticalgroup") local VerticalSpan = require("ui/widget/verticalspan") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local util = require("util") @@ -27,7 +28,7 @@ local Screen = Device.screen local T = require("ffi/util").template -- Simple widget for showing tweak info -local TweakInfoWidget = InputContainer:new{ +local TweakInfoWidget = InputContainer:extend{ tweak = nil, is_global_default = nil, toggle_global_default_callback = function() end, @@ -226,7 +227,7 @@ end -- Reader component for managing tweaks. The aggregated css_text -- is actually requested from us and applied by ReaderTypeset -local ReaderStyleTweak = InputContainer:new{ +local ReaderStyleTweak = WidgetContainer:extend{ tweaks_by_id = nil, tweaks_table = nil, -- sub-menu items nb_enabled_tweaks = 0, -- for use by main menu item diff --git a/frontend/apps/reader/modules/readerthumbnail.lua b/frontend/apps/reader/modules/readerthumbnail.lua index d57120766..2657e9554 100644 --- a/frontend/apps/reader/modules/readerthumbnail.lua +++ b/frontend/apps/reader/modules/readerthumbnail.lua @@ -2,11 +2,11 @@ local Blitbuffer = require("ffi/blitbuffer") local Cache = require("cache") local Device = require("device") local Geom = require("ui/geometry") -local InputContainer = require("ui/widget/container/inputcontainer") local Persist = require("persist") local RenderImage = require("ui/renderimage") local TileCacheItem = require("document/tilecacheitem") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Screen = Device.screen local ffiutil = require("ffi/util") local logger = require("logger") @@ -18,7 +18,7 @@ local _ = require("gettext") -- It handles launching via the menu or Dispatcher/Gestures two fullscreen -- widgets related to showing pages and thumbnails that will make use of -- its services: BookMap and PageBrowser. -local ReaderThumbnail = InputContainer:new{} +local ReaderThumbnail = WidgetContainer:extend{} function ReaderThumbnail:init() if not Device:isTouchDevice() then diff --git a/frontend/apps/reader/modules/readertoc.lua b/frontend/apps/reader/modules/readertoc.lua index ae38cc72d..c6d247523 100644 --- a/frontend/apps/reader/modules/readertoc.lua +++ b/frontend/apps/reader/modules/readertoc.lua @@ -20,15 +20,15 @@ local N_ = _.ngettext local Screen = Device.screen local T = require("ffi/util").template -local ReaderToc = InputContainer:new{ +local ReaderToc = InputContainer:extend{ toc = nil, toc_depth = nil, ticks = nil, ticks_flattened = nil, ticks_flattened_filtered = nil, - collapsed_toc = {}, + collapsed_toc = nil, -- table collapse_depth = 2, - expanded_nodes = {}, + expanded_nodes = nil, -- table toc_menu_title = _("Table of contents"), alt_toc_menu_title = _("Table of contents *"), toc_items_per_page_default = 14, diff --git a/frontend/apps/reader/modules/readertypeset.lua b/frontend/apps/reader/modules/readertypeset.lua index 128602d43..cd308dd05 100644 --- a/frontend/apps/reader/modules/readertypeset.lua +++ b/frontend/apps/reader/modules/readertypeset.lua @@ -2,10 +2,10 @@ local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") -local UIManager = require("ui/uimanager") local Math = require("optmath") local Notification = require("ui/widget/notification") +local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local optionsutil = require("ui/data/optionsutil") local _ = require("gettext") @@ -13,7 +13,7 @@ local C_ = _.pgettext local Screen = require("device").screen local T = require("ffi/util").template -local ReaderTypeset = InputContainer:new{ +local ReaderTypeset = WidgetContainer:extend{ -- @translators This is style in the sense meant by CSS (cascading style sheets), relating to the layout and presentation of the document. See for more information. css_menu_title = C_("CSS", "Style"), css = nil, diff --git a/frontend/apps/reader/modules/readertypography.lua b/frontend/apps/reader/modules/readertypography.lua index c49b62bd5..8a4cf7fd7 100644 --- a/frontend/apps/reader/modules/readertypography.lua +++ b/frontend/apps/reader/modules/readertypography.lua @@ -2,9 +2,9 @@ local BD = require("ui/bidi") local Device = require("device") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local MultiConfirmBox = require("ui/widget/multiconfirmbox") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local util = require("util") local _ = require("gettext") @@ -12,7 +12,7 @@ local C_ = _.pgettext local T = require("ffi/util").template local Screen = Device.screen -local ReaderTypography = InputContainer:new{} +local ReaderTypography = WidgetContainer:extend{} -- This is used to migrate old hyph settings, and to show the currently -- used hyph dict language in the hyphenation menu. diff --git a/frontend/apps/reader/modules/readeruserhyph.lua b/frontend/apps/reader/modules/readeruserhyph.lua index 3adec204d..29accf9c0 100644 --- a/frontend/apps/reader/modules/readeruserhyph.lua +++ b/frontend/apps/reader/modules/readeruserhyph.lua @@ -16,7 +16,7 @@ local T = require("ffi/util").template -- and some `if NORM then` branches can be simplified. local NORM = false -local ReaderUserHyph = WidgetContainer:new{ +local ReaderUserHyph = WidgetContainer:extend{ -- return values from setUserHyphenationDict (crengine's UserHyphDict::init()) USER_DICT_RELOAD = 0, USER_DICT_NOCHANGE = 1, diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index 55b72df03..ee8f5fe78 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -28,28 +28,13 @@ local T = require("ffi/util").template local ReaderView = OverlapGroup:extend{ document = nil, + view_modules = nil, -- array -- single page state - state = { - page = nil, - pos = 0, - zoom = 1.0, - rotation = 0, - gamma = 1.0, - offset = nil, - bbox = nil, - }, + state = nil, -- table outer_page_color = Blitbuffer.gray(G_defaults:readSetting("DOUTER_PAGE_COLOR") / 15), -- highlight with "lighten" or "underscore" or "strikeout" or "invert" - highlight = { - lighten_factor = G_reader_settings:readSetting("highlight_lighten_factor", 0.2), - note_mark = G_reader_settings:readSetting("highlight_note_marker"), - temp_drawer = "invert", - temp = {}, - saved_drawer = "lighten", - saved = {}, - indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50} - }, + highlight = nil, -- table highlight_visible = true, note_mark_line_w = 3, -- side line thickness note_mark_sign = nil, @@ -58,12 +43,9 @@ local ReaderView = OverlapGroup:extend{ -- PDF/DjVu continuous paging page_scroll = nil, page_bgcolor = Blitbuffer.gray(G_defaults:readSetting("DBACKGROUND_COLOR") / 15), - page_states = {}, + page_states = nil, -- table -- properties of the gap drawn between each page in scroll mode: - page_gap = { - -- color (0 = white, 8 = gray, 15 = black) - color = Blitbuffer.gray((G_reader_settings:readSetting("page_gap_color") or 8) / 15), - }, + page_gap = nil, -- table -- DjVu page rendering mode (used in djvu.c:drawPage()) render_mode = G_defaults:readSetting("DRENDER_MODE"), -- default to COLOR -- Crengine view mode @@ -91,10 +73,30 @@ local ReaderView = OverlapGroup:extend{ function ReaderView:init() self.view_modules = {} - -- fix recalculate from close document pageno - self.state.page = nil - -- Reset the various areas across documents + self.state = { + page = nil, + pos = 0, + zoom = 1.0, + rotation = 0, + gamma = 1.0, + offset = nil, + bbox = nil, + } + self.highlight = { + lighten_factor = G_reader_settings:readSetting("highlight_lighten_factor", 0.2), + note_mark = G_reader_settings:readSetting("highlight_note_marker"), + temp_drawer = "invert", + temp = {}, + saved_drawer = "lighten", + saved = {}, + indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50} + } + self.page_states = {} + self.page_gap = { + -- color (0 = white, 8 = gray, 15 = black) + color = Blitbuffer.gray((G_reader_settings:readSetting("page_gap_color") or 8) / 15), + } self.visible_area = Geom:new{x = 0, y = 0, w = 0, h = 0} self.page_area = Geom:new{x = 0, y = 0, w = 0, h = 0} self.dim_area = Geom:new{x = 0, y = 0, w = 0, h = 0} @@ -103,6 +105,9 @@ function ReaderView:init() self.emitHintPageEvent = function() self.ui:handleEvent(Event:new("HintPage", self.hinting)) end + + -- We've subclassed OverlapGroup, go through its init, because it does some funky stuff with self.dimen... + OverlapGroup.init(self) end function ReaderView:addWidgets() @@ -1071,8 +1076,7 @@ function ReaderView:getRenderModeMenuTable() end function ReaderView:onCloseDocument() - self.hinting = false - -- stop any in fly HintPage event + -- stop any pending HintPage event UIManager:unschedule(self.emitHintPageEvent) end diff --git a/frontend/apps/reader/modules/readerwikipedia.lua b/frontend/apps/reader/modules/readerwikipedia.lua index 6f36b7e14..4da4ba25d 100644 --- a/frontend/apps/reader/modules/readerwikipedia.lua +++ b/frontend/apps/reader/modules/readerwikipedia.lua @@ -31,7 +31,7 @@ function ReaderWikipedia:init() self.wiki_languages = {} self.ui.menu:registerToMainMenu(self) if not wikipedia_history then - wikipedia_history = LuaData:open(DataStorage:getSettingsDir() .. "/wikipedia_history.lua", { name = "WikipediaHistory" }) + wikipedia_history = LuaData:open(DataStorage:getSettingsDir() .. "/wikipedia_history.lua", "WikipediaHistory") end end diff --git a/frontend/apps/reader/modules/readerzooming.lua b/frontend/apps/reader/modules/readerzooming.lua index 0ce614a9d..59b99f0f4 100644 --- a/frontend/apps/reader/modules/readerzooming.lua +++ b/frontend/apps/reader/modules/readerzooming.lua @@ -14,9 +14,9 @@ local Input = Device.input local Screen = Device.screen local T = require("ffi/util").template -local ReaderZooming = InputContainer:new{ +local ReaderZooming = InputContainer:extend{ zoom = 1.0, - available_zoom_modes = { + available_zoom_modes = { -- const "page", "pagewidth", "pageheight", @@ -27,26 +27,26 @@ local ReaderZooming = InputContainer:new{ "rows", "manual", }, - zoom_genus_to_mode = { + zoom_genus_to_mode = { -- const [4] = "page", [3] = "content", [2] = "columns", [1] = "rows", [0] = "manual", }, - zoom_mode_to_genus = { + zoom_mode_to_genus = { -- const page = 4, content = 3, columns = 2, rows = 1, manual = 0, }, - zoom_type_to_mode = { + zoom_type_to_mode = { -- const [2] = "", [1] = "width", [0] = "height", }, - zoom_mode_to_type = { + zoom_mode_to_type = { -- const [""] = 2, width = 1, height = 0, @@ -58,7 +58,7 @@ local ReaderZooming = InputContainer:new{ -- with overlap of zoom_overlap_h % (horizontally) -- and zoom_overlap_v % (vertically). kopt_zoom_factor = 1.5, - zoom_pan_settings = { + zoom_pan_settings = { -- const "kopt_zoom_factor", "zoom_overlap_h", "zoom_overlap_v", @@ -71,7 +71,7 @@ local ReaderZooming = InputContainer:new{ zoom_direction_vertical = nil, -- true for column mode current_page = 1, rotation = 0, - paged_modes = { + paged_modes = { -- const page = _("Zoom to fit page works best with page view."), pageheight = _("Zoom to fit page height works best with page view."), contentheight = _("Zoom to fit content height works best with page view."), diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 1b21f1dcf..8360553f4 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -66,9 +66,9 @@ local _ = require("gettext") local Screen = require("device").screen local T = ffiUtil.template -local ReaderUI = InputContainer:new{ +local ReaderUI = InputContainer:extend{ name = "ReaderUI", - active_widgets = {}, + active_widgets = nil, -- array -- if we have a parent container, it must be referenced for now dialog = nil, @@ -104,6 +104,8 @@ function ReaderUI:registerPostReadyCallback(callback) end function ReaderUI:init() + self.active_widgets = {} + -- cap screen refresh on pan to 2 refreshes per second local pan_rate = Screen.low_pan_rate and 2.0 or 30.0 diff --git a/frontend/cache.lua b/frontend/cache.lua index bcb643292..2c611f9cf 100644 --- a/frontend/cache.lua +++ b/frontend/cache.lua @@ -8,11 +8,6 @@ local lru = require("ffi/lru") local md5 = require("ffi/sha2").md5 local util = require("util") -local CanvasContext = require("document/canvascontext") -if CanvasContext.should_restrict_JIT then - jit.off(true, true) -end - local Cache = { -- Cache configuration: -- Max storage space, in bytes... diff --git a/frontend/cacheitem.lua b/frontend/cacheitem.lua index 7f0927736..9b11cd2e4 100644 --- a/frontend/cacheitem.lua +++ b/frontend/cacheitem.lua @@ -9,12 +9,15 @@ local CacheItem = { --- and the most common items we cache are Geom-like tables (i.e., 4 key-value pairs). --- That's generally a low estimation, especially for larger tables, where memory allocation trickery may be happening. -function CacheItem:new(o) +function CacheItem:extend(o) o = o or {} setmetatable(o, self) self.__index = self return o end +-- NOTE: There's no object-specific initialization, the entirety of the new data *is* the table we pass to new. +-- We only keep the distinction as a matter of semantics, to differentiate class declarations from object instantiations. +CacheItem.new = CacheItem.extend -- Called on eviction. -- We generally use it to free C/FFI resources *immediately* (as opposed to relying on our Userdata/FFI finalizers to do it "later" on GC). diff --git a/frontend/device/android/device.lua b/frontend/device/android/device.lua index 01b5fa306..c7c23aee8 100644 --- a/frontend/device/android/device.lua +++ b/frontend/device/android/device.lua @@ -67,7 +67,7 @@ local external = require("device/thirdparty"):new{ end, } -local Device = Generic:new{ +local Device = Generic:extend{ isAndroid = yes, model = android.prop.product, hasKeys = yes, @@ -111,21 +111,6 @@ local Device = Generic:new{ android.dictLookup(text, app, action) end end, - - -- Android is very finicky, and the LuaJIT allocator has a tremendously hard time getting the system - -- to allocate memory for it in the very specific memory range it requires to store generated code (mcode). - -- Failure to do so at runtime (mcode_alloc) will *tank* performance - -- (much worse than if the JIT were simply disabled). - -- The first line of defense is left to android-luajit-launcher, - -- which will try to grab the full mcode region in one go right at startup. - -- The second line of defense is *this* flag, which disables the JIT in a few code-hungry modules, - -- but not necessarily performance critical ones, to hopefully limit the amount of mcode memory - -- required for those modules where it *really* matters (e.g., ffi/blitbuffer.lua). - -- This is also why we try to actually avoid entering actual loops in the Lua blitter on Android, - -- and instead attempt to do most of everything via the C implementation. - -- NOTE: Since https://github.com/koreader/android-luajit-launcher/pull/283, we've patched LuaJIT - -- to ensure that the initial mcode alloc works, and sticks around, which is why this is no longer enabled. - should_restrict_JIT = false, } function Device:init() diff --git a/frontend/device/cervantes/device.lua b/frontend/device/cervantes/device.lua index de2888038..81bc26f19 100644 --- a/frontend/device/cervantes/device.lua +++ b/frontend/device/cervantes/device.lua @@ -34,7 +34,7 @@ local function isMassStorageSupported() return true end -local Cervantes = Generic:new{ +local Cervantes = Generic:extend{ model = "Cervantes", isCervantes = yes, isAlwaysPortrait = yes, @@ -65,33 +65,33 @@ local Cervantes = Generic:new{ canHWInvert = yes, } -- Cervantes Touch -local CervantesTouch = Cervantes:new{ +local CervantesTouch = Cervantes:extend{ model = "CervantesTouch", display_dpi = 167, hasFrontlight = no, hasMultitouch = no, } -- Cervantes TouchLight / Fnac Touch Plus -local CervantesTouchLight = Cervantes:new{ +local CervantesTouchLight = Cervantes:extend{ model = "CervantesTouchLight", display_dpi = 167, hasMultitouch = no, } -- Cervantes 2013 / Fnac Touch Light -local Cervantes2013 = Cervantes:new{ +local Cervantes2013 = Cervantes:extend{ model = "Cervantes2013", display_dpi = 212, hasMultitouch = no, --- @fixme: Possibly requires canHWInvert = no, as it seems to be based on a similar board as the Kobo Aura... } -- Cervantes 3 / Fnac Touch Light 2 -local Cervantes3 = Cervantes:new{ +local Cervantes3 = Cervantes:extend{ model = "Cervantes3", display_dpi = 300, hasMultitouch = no, } -- Cervantes 4 -local Cervantes4 = Cervantes:new{ +local Cervantes4 = Cervantes:extend{ model = "Cervantes4", display_dpi = 300, hasNaturalLight = yes, diff --git a/frontend/device/devicelistener.lua b/frontend/device/devicelistener.lua index c2c623912..6ca10f648 100644 --- a/frontend/device/devicelistener.lua +++ b/frontend/device/devicelistener.lua @@ -1,6 +1,6 @@ local Device = require("device") local Event = require("ui/event") -local InputContainer = require("ui/widget/container/inputcontainer") +local EventListener = require("ui/widget/eventlistener") local Notification = require("ui/widget/notification") local Screen = Device.screen local UIManager = require("ui/uimanager") @@ -8,7 +8,7 @@ local bit = require("bit") local _ = require("gettext") local T = require("ffi/util").template -local DeviceListener = InputContainer:new{} +local DeviceListener = EventListener:extend{} local function _setSetting(name) G_reader_settings:makeTrue(name) diff --git a/frontend/device/dummy/device.lua b/frontend/device/dummy/device.lua index a10397d00..98e596c90 100644 --- a/frontend/device/dummy/device.lua +++ b/frontend/device/dummy/device.lua @@ -4,7 +4,7 @@ local logger = require("logger") local function yes() return true end local function no() return false end -local Device = Generic:new{ +local Device = Generic:extend{ model = "dummy", hasKeyboard = no, hasKeys = no, diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 0b98038a2..d4151426c 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -20,7 +20,6 @@ local Device = { charging_mode = false, survive_screen_saver = false, is_cover_closed = false, - should_restrict_JIT = false, model = nil, powerd = nil, screen = nil, @@ -130,7 +129,7 @@ local Device = { canExternalDictLookup = no, } -function Device:new(o) +function Device:extend(o) o = o or {} setmetatable(o, self) self.__index = self @@ -159,7 +158,6 @@ function Device:invertButtons() end function Device:init() - assert(self ~= nil) if not self.screen then error("screen/framebuffer must be implemented") end diff --git a/frontend/device/generic/powerd.lua b/frontend/device/generic/powerd.lua index 3fd72b621..5d52d1a7a 100644 --- a/frontend/device/generic/powerd.lua +++ b/frontend/device/generic/powerd.lua @@ -73,12 +73,10 @@ function BasePowerD:beforeSuspend() end function BasePowerD:afterResume() end function BasePowerD:isFrontlightOn() - assert(self ~= nil) return self.is_fl_on end function BasePowerD:_decideFrontlightState() - assert(self ~= nil) assert(self.device:hasFrontlight()) self.is_fl_on = self:isFrontlightOnHW() end @@ -88,7 +86,6 @@ function BasePowerD:isFrontlightOff() end function BasePowerD:frontlightIntensity() - assert(self ~= nil) if not self.device:hasFrontlight() then return 0 end if self:isFrontlightOff() then return 0 end --- @note: We assume that nothing other than us will set the frontlight level, @@ -98,7 +95,6 @@ function BasePowerD:frontlightIntensity() end function BasePowerD:toggleFrontlight() - assert(self ~= nil) if not self.device:hasFrontlight() then return false end if self:isFrontlightOn() then return self:turnOffFrontlight() @@ -108,7 +104,6 @@ function BasePowerD:toggleFrontlight() end function BasePowerD:turnOffFrontlight() - assert(self ~= nil) if not self.device:hasFrontlight() then return end if self:isFrontlightOff() then return false end self:turnOffFrontlightHW() @@ -118,7 +113,6 @@ function BasePowerD:turnOffFrontlight() end function BasePowerD:turnOnFrontlight() - assert(self ~= nil) if not self.device:hasFrontlight() then return end if self:isFrontlightOn() then return false end if self.fl_intensity == self.fl_min then return false end --- @fixme what the hell? @@ -129,7 +123,6 @@ function BasePowerD:turnOnFrontlight() end function BasePowerD:frontlightWarmth() - assert(self ~= nil) if not self.device:hasNaturalLight() then return 0 end diff --git a/frontend/device/gesturedetector.lua b/frontend/device/gesturedetector.lua index e7a2b189d..4fd6fb8f8 100644 --- a/frontend/device/gesturedetector.lua +++ b/frontend/device/gesturedetector.lua @@ -63,6 +63,7 @@ local TWO_FINGER_TAP_DURATION_MS = 300 local HOLD_INTERVAL_MS = 500 local SWIPE_INTERVAL_MS = 900 +-- This is used as a singleton by Input (itself used as a singleton). local GestureDetector = { -- must be initialized with the Input singleton class input = nil, @@ -73,7 +74,7 @@ local GestureDetector = { HOLD_INTERVAL_MS = HOLD_INTERVAL_MS, SWIPE_INTERVAL_MS = SWIPE_INTERVAL_MS, -- pinch/spread direction table - DIRECTION_TABLE = { + DIRECTION_TABLE = { -- const east = "horizontal", west = "horizontal", north = "vertical", diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 1fcf644a4..9adad6a40 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -141,7 +141,7 @@ local function frameworkStopped() end end -local Kindle = Generic:new{ +local Kindle = Generic:extend{ model = "Kindle", isKindle = yes, -- NOTE: We can cheat by adding a platform-specific entry here, because the only code that will check for this is here. @@ -411,7 +411,7 @@ function Kindle:ambientBrightnessLevel() return 4 end -local Kindle2 = Kindle:new{ +local Kindle2 = Kindle:extend{ model = "Kindle2", isREAGL = no, hasKeyboard = yes, @@ -424,7 +424,7 @@ local Kindle2 = Kindle:new{ supportsScreensaver = yes, -- The first ad-supported device was the K3 } -local KindleDXG = Kindle:new{ +local KindleDXG = Kindle:extend{ model = "KindleDXG", isREAGL = no, hasKeyboard = yes, @@ -437,7 +437,7 @@ local KindleDXG = Kindle:new{ supportsScreensaver = yes, -- The first ad-supported device was the K3 } -local Kindle3 = Kindle:new{ +local Kindle3 = Kindle:extend{ model = "Kindle3", isREAGL = no, hasKeyboard = yes, @@ -449,7 +449,7 @@ local Kindle3 = Kindle:new{ isSpecialOffers = hasSpecialOffers(), } -local Kindle4 = Kindle:new{ +local Kindle4 = Kindle:extend{ model = "Kindle4", isREAGL = no, hasKeys = yes, @@ -461,7 +461,7 @@ local Kindle4 = Kindle:new{ isSpecialOffers = hasSpecialOffers(), } -local KindleTouch = Kindle:new{ +local KindleTouch = Kindle:extend{ model = "KindleTouch", isREAGL = no, isTouchDevice = yes, @@ -469,7 +469,7 @@ local KindleTouch = Kindle:new{ touch_dev = "/dev/input/event3", } -local KindlePaperWhite = Kindle:new{ +local KindlePaperWhite = Kindle:extend{ model = "KindlePaperWhite", isREAGL = no, isTouchDevice = yes, @@ -479,7 +479,7 @@ local KindlePaperWhite = Kindle:new{ touch_dev = "/dev/input/event0", } -local KindlePaperWhite2 = Kindle:new{ +local KindlePaperWhite2 = Kindle:extend{ model = "KindlePaperWhite2", isTouchDevice = yes, hasFrontlight = yes, @@ -488,13 +488,13 @@ local KindlePaperWhite2 = Kindle:new{ touch_dev = "/dev/input/event1", } -local KindleBasic = Kindle:new{ +local KindleBasic = Kindle:extend{ model = "KindleBasic", isTouchDevice = yes, touch_dev = "/dev/input/event1", } -local KindleVoyage = Kindle:new{ +local KindleVoyage = Kindle:extend{ model = "KindleVoyage", isTouchDevice = yes, hasFrontlight = yes, @@ -504,7 +504,7 @@ local KindleVoyage = Kindle:new{ touch_dev = "/dev/input/event1", } -local KindlePaperWhite3 = Kindle:new{ +local KindlePaperWhite3 = Kindle:extend{ model = "KindlePaperWhite3", isTouchDevice = yes, hasFrontlight = yes, @@ -513,7 +513,7 @@ local KindlePaperWhite3 = Kindle:new{ touch_dev = "/dev/input/event1", } -local KindleOasis = Kindle:new{ +local KindleOasis = Kindle:extend{ model = "KindleOasis", isTouchDevice = yes, hasFrontlight = yes, @@ -529,7 +529,7 @@ local KindleOasis = Kindle:new{ touch_dev = "/dev/input/by-path/platform-imx-i2c.1-event", } -local KindleOasis2 = Kindle:new{ +local KindleOasis2 = Kindle:extend{ model = "KindleOasis2", isZelda = yes, isTouchDevice = yes, @@ -540,7 +540,7 @@ local KindleOasis2 = Kindle:new{ touch_dev = "/dev/input/by-path/platform-30a30000.i2c-event", } -local KindleOasis3 = Kindle:new{ +local KindleOasis3 = Kindle:extend{ model = "KindleOasis3", isZelda = yes, isTouchDevice = yes, @@ -553,13 +553,13 @@ local KindleOasis3 = Kindle:new{ touch_dev = "/dev/input/by-path/platform-30a30000.i2c-event", } -local KindleBasic2 = Kindle:new{ +local KindleBasic2 = Kindle:extend{ model = "KindleBasic2", isTouchDevice = yes, touch_dev = "/dev/input/event0", } -local KindlePaperWhite4 = Kindle:new{ +local KindlePaperWhite4 = Kindle:extend{ model = "KindlePaperWhite4", isRex = yes, isTouchDevice = yes, @@ -571,7 +571,7 @@ local KindlePaperWhite4 = Kindle:new{ touch_dev = "/dev/input/event2", } -local KindleBasic3 = Kindle:new{ +local KindleBasic3 = Kindle:extend{ model = "KindleBasic3", isRex = yes, -- NOTE: Apparently, the KT4 doesn't actually support the fancy nightmode waveforms, c.f., ko/#5076 @@ -582,7 +582,7 @@ local KindleBasic3 = Kindle:new{ touch_dev = "/dev/input/event2", } -local KindlePaperWhite5 = Kindle:new{ +local KindlePaperWhite5 = Kindle:extend{ model = "KindlePaperWhite5", isMTK = yes, isTouchDevice = yes, @@ -599,7 +599,7 @@ local KindlePaperWhite5 = Kindle:new{ canDoSwipeAnimation = yes, } -local KindleScribe = Kindle:new{ +local KindleScribe = Kindle:extend{ model = "KindleScribe", isMTK = yes, isTouchDevice = yes, diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index 414b0da92..7e8b63051 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -18,6 +18,7 @@ require("ffi/posix_h") local function yes() return true end local function no() return false end +local function NOP() return end local function koboEnableWifi(toggle) if toggle == true then @@ -131,7 +132,7 @@ local function getRTCName() end end -local Kobo = Generic:new{ +local Kobo = Generic:extend{ model = "Kobo", isKobo = yes, isTouchDevice = yes, -- all of them are @@ -192,21 +193,21 @@ local Kobo = Generic:new{ } -- Kobo Touch A/B: -local KoboTrilogyAB = Kobo:new{ +local KoboTrilogyAB = Kobo:extend{ model = "Kobo_trilogy_AB", touch_kobo_mk3_protocol = true, hasKeys = yes, hasMultitouch = no, } -- Kobo Touch C: -local KoboTrilogyC = Kobo:new{ +local KoboTrilogyC = Kobo:extend{ model = "Kobo_trilogy_C", hasKeys = yes, hasMultitouch = no, } -- Kobo Mini: -local KoboPixie = Kobo:new{ +local KoboPixie = Kobo:extend{ model = "Kobo_pixie", display_dpi = 200, hasMultitouch = no, @@ -215,7 +216,7 @@ local KoboPixie = Kobo:new{ } -- Kobo Aura One: -local KoboDaylight = Kobo:new{ +local KoboDaylight = Kobo:extend{ model = "Kobo_daylight", hasFrontlight = yes, touch_phoenix_protocol = true, @@ -229,8 +230,10 @@ local KoboDaylight = Kobo:new{ } -- Kobo Aura H2O: -local KoboDahlia = Kobo:new{ +local KoboDahlia = Kobo:extend{ model = "Kobo_dahlia", + canToggleChargingLED = no, -- Possibly weird interactions with Nickel + led_uses_channel_3 = true, hasFrontlight = yes, touch_phoenix_protocol = true, -- There's no slot 0, the first finger gets assigned slot 1, and the second slot 2. @@ -243,7 +246,7 @@ local KoboDahlia = Kobo:new{ } -- Kobo Aura HD: -local KoboDragon = Kobo:new{ +local KoboDragon = Kobo:extend{ model = "Kobo_dragon", hasFrontlight = yes, hasMultitouch = no, @@ -251,7 +254,7 @@ local KoboDragon = Kobo:new{ } -- Kobo Glo: -local KoboKraken = Kobo:new{ +local KoboKraken = Kobo:extend{ model = "Kobo_kraken", hasFrontlight = yes, hasMultitouch = no, @@ -259,7 +262,7 @@ local KoboKraken = Kobo:new{ } -- Kobo Aura: -local KoboPhoenix = Kobo:new{ +local KoboPhoenix = Kobo:extend{ model = "Kobo_phoenix", hasFrontlight = yes, touch_phoenix_protocol = true, @@ -273,7 +276,7 @@ local KoboPhoenix = Kobo:new{ } -- Kobo Aura H2O2: -local KoboSnow = Kobo:new{ +local KoboSnow = Kobo:extend{ model = "Kobo_snow", hasFrontlight = yes, touch_snow_protocol = true, @@ -289,7 +292,7 @@ local KoboSnow = Kobo:new{ -- Kobo Aura H2O2, Rev2: --- @fixme Check if the Clara fix actually helps here... (#4015) -local KoboSnowRev2 = Kobo:new{ +local KoboSnowRev2 = Kobo:extend{ model = "Kobo_snow_r2", isMk7 = yes, hasFrontlight = yes, @@ -303,7 +306,7 @@ local KoboSnowRev2 = Kobo:new{ } -- Kobo Aura second edition: -local KoboStar = Kobo:new{ +local KoboStar = Kobo:extend{ model = "Kobo_star", hasFrontlight = yes, touch_phoenix_protocol = true, @@ -311,7 +314,7 @@ local KoboStar = Kobo:new{ } -- Kobo Aura second edition, Rev 2: -local KoboStarRev2 = Kobo:new{ +local KoboStarRev2 = Kobo:extend{ model = "Kobo_star_r2", isMk7 = yes, hasFrontlight = yes, @@ -320,7 +323,7 @@ local KoboStarRev2 = Kobo:new{ } -- Kobo Glo HD: -local KoboAlyssum = Kobo:new{ +local KoboAlyssum = Kobo:extend{ model = "Kobo_alyssum", hasFrontlight = yes, touch_phoenix_protocol = true, @@ -329,14 +332,14 @@ local KoboAlyssum = Kobo:new{ } -- Kobo Touch 2.0: -local KoboPika = Kobo:new{ +local KoboPika = Kobo:extend{ model = "Kobo_pika", touch_phoenix_protocol = true, main_finger_slot = 1, } -- Kobo Clara HD: -local KoboNova = Kobo:new{ +local KoboNova = Kobo:extend{ model = "Kobo_nova", isMk7 = yes, canToggleChargingLED = yes, @@ -362,7 +365,7 @@ local KoboNova = Kobo:new{ -- i.e., this will affect KSM users. -- c.f., https://github.com/koreader/koreader/pull/4414#issuecomment-449652335 -- There's also a CM_ROTARY_ENABLE command, but which seems to do as much nothing as the STATUS one... -local KoboFrost = Kobo:new{ +local KoboFrost = Kobo:extend{ model = "Kobo_frost", isMk7 = yes, canToggleChargingLED = yes, @@ -387,7 +390,7 @@ local KoboFrost = Kobo:new{ -- Kobo Libra: -- NOTE: Assume the same quirks as the Forma apply. -local KoboStorm = Kobo:new{ +local KoboStorm = Kobo:extend{ model = "Kobo_storm", isMk7 = yes, canToggleChargingLED = yes, @@ -418,7 +421,7 @@ local KoboStorm = Kobo:new{ -- Kobo Nia: --- @fixme: Mostly untested, assume it's Clara-ish for now. -local KoboLuna = Kobo:new{ +local KoboLuna = Kobo:extend{ model = "Kobo_luna", isMk7 = yes, canToggleChargingLED = yes, @@ -428,7 +431,7 @@ local KoboLuna = Kobo:new{ } -- Kobo Elipsa -local KoboEuropa = Kobo:new{ +local KoboEuropa = Kobo:extend{ model = "Kobo_europa", isSunxi = yes, hasEclipseWfm = yes, @@ -448,7 +451,7 @@ local KoboEuropa = Kobo:new{ } -- Kobo Sage -local KoboCadmus = Kobo:new{ +local KoboCadmus = Kobo:extend{ model = "Kobo_cadmus", isSunxi = yes, hasEclipseWfm = yes, @@ -481,7 +484,7 @@ local KoboCadmus = Kobo:new{ } -- Kobo Libra 2: -local KoboIo = Kobo:new{ +local KoboIo = Kobo:extend{ model = "Kobo_io", isMk7 = yes, hasEclipseWfm = yes, @@ -513,7 +516,7 @@ local KoboIo = Kobo:new{ } -- Kobo Clara 2E: -local KoboGoldfinch = Kobo:new{ +local KoboGoldfinch = Kobo:extend{ model = "Kobo_goldfinch", isMk7 = yes, hasEclipseWfm = yes, @@ -682,15 +685,15 @@ function Kobo:init() self.default_cpu_governor = getCPUGovernor(self.cpu_governor_knob) -- NOP unsupported methods if not self.default_cpu_governor then - self.performanceCPUGovernor = function() end - self.defaultCPUGovernor = function() end + self.performanceCPUGovernor = NOP + self.defaultCPUGovernor = NOP end -- And while we're on CPU-related endeavors... self.cpu_count = self:isSMP() and getCPUCount() or 1 -- NOP unsupported methods if self.cpu_count == 1 then - self.enableCPUCores = function() end + self.enableCPUCores = NOP end -- Automagically set this so we never have to remember to do it manually ;p @@ -742,6 +745,7 @@ function Kobo:init() dodgy_rtc = dodgy_rtc, } + -- Let generic properly setup the standard stuff Generic.init(self) -- Various HW Buttons, Switches & Synthetic NTX events @@ -768,14 +772,14 @@ function Kobo:init() -- See if the device supports key repeat if not self:getKeyRepeat() then -- NOP unsupported methods - self.disableKeyRepeat = function() end - self.restoreKeyRepeat = function() end + self.disableKeyRepeat = NOP + self.restoreKeyRepeat = NOP end -- NOP unsupported methods if not self:canToggleChargingLED() then - self.toggleChargingLED = function() end - self.setupChargingLED = function() end + self.toggleChargingLED = NOP + self.setupChargingLED = NOP end -- We have no way of querying the current state of the charging LED, so, start from scratch. @@ -1233,12 +1237,15 @@ function Kobo:toggleChargingLED(toggle) -- In fact, Nickel itself doesn't provide this feature on said older devices -- (when it does, it's an option in the Energy saving settings), -- which is why we also limit ourselves to "true" on devices where this was tested. + -- FWIW, on older devices, the knob is at "/sys/devices/platform/pmic_light.1/lit". -- c.f., drivers/misc/ntx_misc_light.c local f = io.open("/sys/devices/platform/ntx_led/lit", "we") if not f then logger.err("cannot open /sys/devices/platform/ntx_led/lit for writing!") return false end + -- Relying on LFs is mildly more elegant than spamming f:flush() calls ;). + C.setlinebuf(f) -- c.f., strace -fittTvyy -e trace=ioctl,file,signal,ipc,desc -s 256 -o /tmp/nickel.log -p $(pidof -s nickel) & -- This was observed on a Forma, so I'm mildly hopeful that it's safe on other Mk. 7 devices ;). @@ -1247,38 +1254,13 @@ function Kobo:toggleChargingLED(toggle) -- NOTE: Technically, Nickel forces a toggle off before that, too. -- But since we do that on startup, it shouldn't be necessary here... if self.led_uses_channel_3 then - f:write("ch 3") - f:flush() - f:write("cur 1") - f:flush() - f:write("dc 63") - f:flush() + f:write("ch 3\n", "cur 1\n", "dc 63\n") end - f:write("ch 4") - f:flush() - f:write("cur 1") - f:flush() - f:write("dc 63") - f:flush() + f:write("ch 4\n", "cur 1\n", "dc 63\n") else - f:write("ch 3") - f:flush() - f:write("cur 1") - f:flush() - f:write("dc 0") - f:flush() - f:write("ch 4") - f:flush() - f:write("cur 1") - f:flush() - f:write("dc 0") - f:flush() - f:write("ch 5") - f:flush() - f:write("cur 1") - f:flush() - f:write("dc 0") - f:flush() + for ch = 3, 5 do + f:write("ch " .. tostring(ch) .. "\n", "cur 1\n", "dc 0\n") + end end f:close() diff --git a/frontend/device/pocketbook/device.lua b/frontend/device/pocketbook/device.lua index 7eb6043b2..00b756ab0 100644 --- a/frontend/device/pocketbook/device.lua +++ b/frontend/device/pocketbook/device.lua @@ -21,7 +21,7 @@ local function no() return false end local ext_path = "/mnt/ext1/system/config/extensions.cfg" local app_name = "koreader.app" -local PocketBook = Generic:new{ +local PocketBook = Generic:extend{ model = "PocketBook", isPocketBook = yes, hasOTAUpdates = yes, @@ -407,7 +407,7 @@ local function landscape_ccw() return { } end -- PocketBook Mini (515) -local PocketBook515 = PocketBook:new{ +local PocketBook515 = PocketBook:extend{ model = "PB515", display_dpi = 200, isTouchDevice = no, @@ -417,7 +417,7 @@ local PocketBook515 = PocketBook:new{ } -- PocketBook Basic 4 (606) -local PocketBook606 = PocketBook:new{ +local PocketBook606 = PocketBook:extend{ model = "PB606", display_dpi = 212, isTouchDevice = no, @@ -427,7 +427,7 @@ local PocketBook606 = PocketBook:new{ } -- PocketBook Basic (611) -local PocketBook611 = PocketBook:new{ +local PocketBook611 = PocketBook:extend{ model = "PB611", display_dpi = 167, isTouchDevice = no, @@ -437,7 +437,7 @@ local PocketBook611 = PocketBook:new{ } -- PocketBook Basic (613) -local PocketBook613 = PocketBook:new{ +local PocketBook613 = PocketBook:extend{ model = "PB613B", display_dpi = 167, isTouchDevice = no, @@ -448,7 +448,7 @@ local PocketBook613 = PocketBook:new{ } -- PocketBook Basic 2 / Basic 3 (614/614W) -local PocketBook614W = PocketBook:new{ +local PocketBook614W = PocketBook:extend{ model = "PB614W", display_dpi = 167, isTouchDevice = no, @@ -458,7 +458,7 @@ local PocketBook614W = PocketBook:new{ } -- PocketBook Basic Lux / 615 Plus (615/615W) -local PocketBook615 = PocketBook:new{ +local PocketBook615 = PocketBook:extend{ model = "PBBLux", display_dpi = 212, isTouchDevice = no, @@ -467,7 +467,7 @@ local PocketBook615 = PocketBook:new{ } -- PocketBook Basic Lux 2 (616/616W) -local PocketBook616 = PocketBook:new{ +local PocketBook616 = PocketBook:extend{ model = "PBBLux2", display_dpi = 212, isTouchDevice = no, @@ -476,7 +476,7 @@ local PocketBook616 = PocketBook:new{ } -- PocketBook Basic Lux 3 (617) -local PocketBook617 = PocketBook:new{ +local PocketBook617 = PocketBook:extend{ model = "PBBLux3", display_dpi = 212, isTouchDevice = no, @@ -486,47 +486,47 @@ local PocketBook617 = PocketBook:new{ } -- PocketBook Touch (622) -local PocketBook622 = PocketBook:new{ +local PocketBook622 = PocketBook:extend{ model = "PBTouch", display_dpi = 167, hasFrontlight = no, } -- PocketBook Touch Lux (623) -local PocketBook623 = PocketBook:new{ +local PocketBook623 = PocketBook:extend{ model = "PBTouchLux", display_dpi = 212, } -- PocketBook Basic Touch (624) -local PocketBook624 = PocketBook:new{ +local PocketBook624 = PocketBook:extend{ model = "PBBasicTouch", display_dpi = 167, hasFrontlight = no, } -- PocketBook Basic Touch 2 (625) -local PocketBook625 = PocketBook:new{ +local PocketBook625 = PocketBook:extend{ model = "PBBasicTouch2", display_dpi = 167, hasFrontlight = no, } -- PocketBook Touch Lux 2 / Touch Lux 3 (626) -local PocketBook626 = PocketBook:new{ +local PocketBook626 = PocketBook:extend{ model = "PBLux3", display_dpi = 212, } -- PocketBook Touch Lux 4 (627) -local PocketBook627 = PocketBook:new{ +local PocketBook627 = PocketBook:extend{ model = "PBLux4", display_dpi = 212, isAlwaysPortrait = yes, } -- PocketBook Touch Lux 5 (628) -local PocketBook628 = PocketBook:new{ +local PocketBook628 = PocketBook:extend{ model = "PBTouchLux5", display_dpi = 212, isAlwaysPortrait = yes, @@ -535,13 +535,13 @@ local PocketBook628 = PocketBook:new{ } -- PocketBook Sense / Sense 2 (630) -local PocketBook630 = PocketBook:new{ +local PocketBook630 = PocketBook:extend{ model = "PBSense", display_dpi = 212, } -- PocketBook Touch HD / Touch HD 2 (631) -local PocketBook631 = PocketBook:new{ +local PocketBook631 = PocketBook:extend{ model = "PBTouchHD", display_dpi = 300, -- see https://github.com/koreader/koreader/pull/6531#issuecomment-676629182 @@ -549,7 +549,7 @@ local PocketBook631 = PocketBook:new{ } -- PocketBook Touch HD Plus / Touch HD 3 (632) -local PocketBook632 = PocketBook:new{ +local PocketBook632 = PocketBook:extend{ model = "PBTouchHDPlus", display_dpi = 300, isAlwaysPortrait = yes, @@ -558,7 +558,7 @@ local PocketBook632 = PocketBook:new{ } -- PocketBook Color (633) -local PocketBook633 = PocketBook:new{ +local PocketBook633 = PocketBook:extend{ model = "PBColor", display_dpi = 300, hasColorScreen = yes, @@ -568,25 +568,25 @@ local PocketBook633 = PocketBook:new{ } -- PocketBook Aqua (640) -local PocketBook640 = PocketBook:new{ +local PocketBook640 = PocketBook:extend{ model = "PBAqua", display_dpi = 167, } -- PocketBook Aqua 2 (641) -local PocketBook641 = PocketBook:new{ +local PocketBook641 = PocketBook:extend{ model = "PBAqua2", display_dpi = 212, } -- PocketBook Ultra (650) -local PocketBook650 = PocketBook:new{ +local PocketBook650 = PocketBook:extend{ model = "PBUltra", display_dpi = 212, } -- PocketBook Era (700) -local PocketBook700 = PocketBook:new{ +local PocketBook700 = PocketBook:extend{ model = "PB700", display_dpi = 300, isAlwaysPortrait = yes, @@ -594,7 +594,7 @@ local PocketBook700 = PocketBook:new{ } -- PocketBook InkPad 3 (740) -local PocketBook740 = PocketBook:new{ +local PocketBook740 = PocketBook:extend{ model = "PBInkPad3", display_dpi = 300, isAlwaysPortrait = yes, @@ -603,7 +603,7 @@ local PocketBook740 = PocketBook:new{ } -- PocketBook InkPad 3 Pro (740_2) -local PocketBook740_2 = PocketBook:new{ +local PocketBook740_2 = PocketBook:extend{ model = "PBInkPad3Pro", display_dpi = 300, isAlwaysPortrait = yes, @@ -620,7 +620,7 @@ local PocketBook740_2 = PocketBook:new{ } -- PocketBook InkPad Color (741) -local PocketBook741 = PocketBook:new{ +local PocketBook741 = PocketBook:extend{ model = "PBInkPadColor", display_dpi = 300, hasColorScreen = yes, @@ -635,7 +635,7 @@ function PocketBook741._fb_init(fb, finfo, vinfo) end -- PocketBook Color Lux (801) -local PocketBookColorLux = PocketBook:new{ +local PocketBookColorLux = PocketBook:extend{ model = "PBColorLux", display_dpi = 125, hasColorScreen = yes, @@ -653,13 +653,13 @@ function PocketBookColorLux._fb_init(fb, finfo, vinfo) end -- PocketBook InkPad / InkPad 2 (840) -local PocketBook840 = PocketBook:new{ +local PocketBook840 = PocketBook:extend{ model = "PBInkPad", display_dpi = 250, } -- PocketBook InkPad Lite (970) -local PocketBook970 = PocketBook:new{ +local PocketBook970 = PocketBook:extend{ model = "PB970", display_dpi = 150, isAlwaysPortrait = yes, @@ -667,7 +667,7 @@ local PocketBook970 = PocketBook:new{ } -- PocketBook InkPad X (1040) -local PocketBook1040 = PocketBook:new{ +local PocketBook1040 = PocketBook:extend{ model = "PB1040", display_dpi = 227, isAlwaysPortrait = yes, diff --git a/frontend/device/remarkable/device.lua b/frontend/device/remarkable/device.lua index c37a753eb..dc00b8557 100644 --- a/frontend/device/remarkable/device.lua +++ b/frontend/device/remarkable/device.lua @@ -29,7 +29,7 @@ local wacom_scale_x = screen_width / wacom_width local wacom_scale_y = screen_height / wacom_height local isRm2, rm_model = getModel() -local Remarkable = Generic:new{ +local Remarkable = Generic:extend{ isRemarkable = yes, model = rm_model, hasKeys = yes, @@ -47,7 +47,7 @@ local Remarkable = Generic:new{ home_dir = "/home/root", } -local Remarkable1 = Remarkable:new{ +local Remarkable1 = Remarkable:extend{ mt_width = 767, -- unscaled_size_check: ignore mt_height = 1023, -- unscaled_size_check: ignore input_wacom = "/dev/input/event0", @@ -70,7 +70,7 @@ function Remarkable1:adjustTouchEvent(ev, by) end end -local Remarkable2 = Remarkable:new{ +local Remarkable2 = Remarkable:extend{ mt_width = 1403, -- unscaled_size_check: ignore mt_height = 1871, -- unscaled_size_check: ignore input_wacom = "/dev/input/event1", diff --git a/frontend/device/sdl/device.lua b/frontend/device/sdl/device.lua index 20fea0249..73677523c 100644 --- a/frontend/device/sdl/device.lua +++ b/frontend/device/sdl/device.lua @@ -60,7 +60,7 @@ local external = require("device/thirdparty"):new{ end, } -local Device = Generic:new{ +local Device = Generic:extend{ model = "SDL", isSDL = yes, home_dir = os.getenv("XDG_DOCUMENTS_DIR") or os.getenv("HOME"), @@ -105,21 +105,21 @@ local Device = Generic:new{ window = G_reader_settings:readSetting("sdl_window", {}), } -local AppImage = Device:new{ +local AppImage = Device:extend{ model = "AppImage", hasMultitouch = no, hasOTAUpdates = yes, isDesktop = yes, } -local Desktop = Device:new{ +local Desktop = Device:extend{ model = SDL.getPlatform(), isDesktop = yes, canRestart = notOSX, hasExitOptions = notOSX, } -local Emulator = Device:new{ +local Emulator = Device:extend{ model = "Emulator", isEmulator = yes, hasBattery = yes, @@ -137,7 +137,7 @@ local Emulator = Device:new{ canStandby = no, } -local UbuntuTouch = Device:new{ +local UbuntuTouch = Device:extend{ model = "UbuntuTouch", hasFrontlight = yes, isDefaultFullscreen = yes, diff --git a/frontend/device/sony-prstux/device.lua b/frontend/device/sony-prstux/device.lua index dcf055127..e6534db0f 100644 --- a/frontend/device/sony-prstux/device.lua +++ b/frontend/device/sony-prstux/device.lua @@ -9,7 +9,7 @@ require("ffi/linux_input_h") local function yes() return true end local function no() return false end -local SonyPRSTUX = Generic:new{ +local SonyPRSTUX = Generic:extend{ model = "Sony PRSTUX", isSonyPRSTUX = yes, hasKeys = yes, @@ -239,7 +239,7 @@ function SonyPRSTUX:setEventHandlers(UIManager) end -- For Sony PRS-T2 -local SonyPRSTUX_T2 = SonyPRSTUX:new{ +local SonyPRSTUX_T2 = SonyPRSTUX:extend{ isTouchDevice = yes, hasKeys = yes, hasFrontlight = no, diff --git a/frontend/device/wakeupmgr.lua b/frontend/device/wakeupmgr.lua index 30a0d6bd0..37daffecc 100644 --- a/frontend/device/wakeupmgr.lua +++ b/frontend/device/wakeupmgr.lua @@ -21,7 +21,7 @@ WakeupMgr base class. --]] local WakeupMgr = { dev_rtc = "/dev/rtc0", -- RTC device - _task_queue = {}, -- Table with epoch at which to schedule the task and the function to be scheduled. + _task_queue = nil, -- Table with epoch at which to schedule the task and the function to be scheduled. rtc = RTC, -- The RTC implementation to use, defaults to the RTC module. dodgy_rtc = false, -- If the RTC has trouble with timers further away than UINT16_MAX (e.g., on i.MX5). } @@ -45,6 +45,10 @@ function WakeupMgr:new(o) return o end +function WakeupMgr:init() + self._task_queue = {} +end + -- This is a dummy task we use when working around i.MX5 RTC issues. -- We need to be able to recognize it so that we can deal with it in removeTasks... function WakeupMgr.DummyTaskCallback() diff --git a/frontend/docsettings.lua b/frontend/docsettings.lua index 5d68cbb81..d4a777277 100644 --- a/frontend/docsettings.lua +++ b/frontend/docsettings.lua @@ -5,13 +5,14 @@ in the so-called sidecar directory ]] local DataStorage = require("datastorage") +local LuaSettings = require("luasettings") local dump = require("dump") local ffiutil = require("ffi/util") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local util = require("util") -local DocSettings = {} +local DocSettings = LuaSettings:extend{} local HISTORY_DIR = DataStorage:getHistoryDir() @@ -102,18 +103,20 @@ end -- @treturn DocSettings object function DocSettings:open(docfile) --- @todo (zijiehe): Remove history_path, use only sidecar. - local new = {} - new.history_file = self:getHistoryPath(docfile) - local sidecar = self:getSidecarDir(docfile) + -- NOTE: Beware, our new instance is new, but self is still DocSettings! + local new = DocSettings:extend{} + new.history_file = new:getHistoryPath(docfile) + + local sidecar = new:getSidecarDir(docfile) new.sidecar = sidecar DocSettings:ensureSidecar(sidecar) - -- If there is a file which has a same name as the sidecar directory, or - -- the file system is read-only, we should not waste time to read it. + -- If there is a file which has a same name as the sidecar directory, + -- or the file system is read-only, we should not waste time to read it. if lfs.attributes(sidecar, "mode") == "directory" then - -- New sidecar file name is metadata.{file last suffix}.lua. So we - -- can handle two files with only different suffixes. - new.sidecar_file = self:getSidecarFile(docfile) + -- New sidecar file name is metadata.{file last suffix}.lua. + -- So we can handle two files with only different suffixes. + new.sidecar_file = new:getSidecarFile(docfile) new.legacy_sidecar_file = sidecar.."/".. ffiutil.basename(docfile)..".lua" end @@ -163,139 +166,7 @@ function DocSettings:open(docfile) new.data = {} end - return setmetatable(new, {__index = DocSettings}) -end - ---[[-- Reads a setting, optionally initializing it to a default. - -If default is provided, and the key doesn't exist yet, it is initialized to default first. -This ensures both that the defaults are actually set if necessary, -and that the returned reference actually belongs to the DocSettings object straight away, -without requiring further interaction (e.g., saveSetting) from the caller. - -This is mainly useful if the data type you want to retrieve/store is assigned/returned/passed by reference (e.g., a table), -and you never actually break that reference by assigning another one to the same variable, (by e.g., assigning it a new object). -c.f., https://www.lua.org/manual/5.1/manual.html#2.2 - -@param key The setting's key -@param default Initialization data (Optional) -]] -function DocSettings:readSetting(key, default) - -- No initialization data: legacy behavior - if not default then - return self.data[key] - end - - if not self:has(key) then - self.data[key] = default - end - return self.data[key] -end - ---- Saves a setting. -function DocSettings:saveSetting(key, value) - self.data[key] = value - return self -end - ---- Deletes a setting. -function DocSettings:delSetting(key) - self.data[key] = nil - return self -end - ---- Checks if setting exists. -function DocSettings:has(key) - return self.data[key] ~= nil -end - ---- Checks if setting does not exist. -function DocSettings:hasNot(key) - return self.data[key] == nil -end - ---- Checks if setting is `true` (boolean). -function DocSettings:isTrue(key) - return self.data[key] == true -end - ---- Checks if setting is `false` (boolean). -function DocSettings:isFalse(key) - return self.data[key] == false -end - ---- Checks if setting is `nil` or `true`. -function DocSettings:nilOrTrue(key) - return self:hasNot(key) or self:isTrue(key) -end - ---- Checks if setting is `nil` or `false`. -function DocSettings:nilOrFalse(key) - return self:hasNot(key) or self:isFalse(key) -end - ---- Flips `nil` or `true` to `false`, and `false` to `nil`. ---- e.g., a setting that defaults to true. -function DocSettings:flipNilOrTrue(key) - if self:nilOrTrue(key) then - self:saveSetting(key, false) - else - self:delSetting(key) - end - return self -end - ---- Flips `nil` or `false` to `true`, and `true` to `nil`. ---- e.g., a setting that defaults to false. -function DocSettings:flipNilOrFalse(key) - if self:nilOrFalse(key) then - self:saveSetting(key, true) - else - self:delSetting(key) - end - return self -end - ---- Flips a setting between `true` and `nil`. -function DocSettings:flipTrue(key) - if self:isTrue(key) then - self:delSetting(key) - else - self:saveSetting(key, true) - end - return self -end - ---- Flips a setting between `false` and `nil`. -function DocSettings:flipFalse(key) - if self:isFalse(key) then - self:delSetting(key) - else - self:saveSetting(key, false) - end - return self -end - --- Unconditionally makes a boolean setting `true`. -function DocSettings:makeTrue(key) - self:saveSetting(key, true) - return self -end - --- Unconditionally makes a boolean setting `false`. -function DocSettings:makeFalse(key) - self:saveSetting(key, false) - return self -end - ---- Toggles a boolean setting -function DocSettings:toggle(key) - if self:nilOrFalse(key) then - self:saveSetting(key, true) - else - self:saveSetting(key, false) - end - return self + return new end --- Serializes settings and writes them to `metadata.lua`. @@ -307,8 +178,7 @@ function DocSettings:flush() return end - -- If we can write to sidecar_file, we do not need to write to history_file - -- anymore. + -- If we can write to sidecar_file, we do not need to write to history_file anymore. local serials = {} if self.sidecar_file then table.insert(serials, self.sidecar_file) @@ -322,11 +192,10 @@ function DocSettings:flush() for _, f in ipairs(serials) do local directory_updated = false if lfs.attributes(f, "mode") == "file" then - -- As an additional safety measure (to the ffiutil.fsync* calls - -- used below), we only backup the file to .old when it has - -- not been modified in the last 60 seconds. This should ensure - -- in the case the fsync calls are not supported that the OS - -- may have itself sync'ed that file content in the meantime. + -- As an additional safety measure (to the ffiutil.fsync* calls used below), + -- we only backup the file to .old when it has not been modified in the last 60 seconds. + -- This should ensure in the case the fsync calls are not supported + -- that the OS may have itself sync'ed that file content in the meantime. local mtime = lfs.attributes(f, "modification") if mtime < os.time() - 60 then logger.dbg("Rename ", f, " to ", f .. ".old") @@ -364,18 +233,13 @@ function DocSettings:flush() end end -function DocSettings:close() - self:flush() -end - function DocSettings:getFilePath() return self.filepath end --- Purges (removes) sidecar directory. function DocSettings:purge(full) - -- Remove any of the old ones we may consider as candidates - -- in DocSettings:open() + -- Remove any of the old ones we may consider as candidates in DocSettings:open() if self.history_file then os.remove(self.history_file) os.remove(self.history_file .. ".old") @@ -385,12 +249,10 @@ function DocSettings:purge(full) end if lfs.attributes(self.sidecar, "mode") == "directory" then if full then - -- Asked to remove all the content of this .sdr directory, - -- whether it's ours or not + -- Asked to remove all the content of this .sdr directory, whether it's ours or not ffiutil.purgeDir(self.sidecar) else - -- Only remove the files we know we may have created - -- with our usual names. + -- Only remove the files we know we may have created with our usual names. for f in lfs.dir(self.sidecar) do local fullpath = self.sidecar.."/"..f local to_remove = false @@ -398,8 +260,8 @@ function DocSettings:purge(full) -- Currently, we only create a single file in there, -- named metadata.suffix.lua (ie. metadata.epub.lua), -- with possibly backups named metadata.epub.lua.old and - -- metadata.epub.lua.old_dom20180528, so all sharing the - -- same base: self.sidecar_file + -- metadata.epub.lua.old_dom20180528, + -- so all sharing the same base: self.sidecar_file if util.stringStartsWith(fullpath, self.sidecar_file) then to_remove = true end @@ -414,8 +276,8 @@ function DocSettings:purge(full) os.remove(self.sidecar) end end - -- We should have meet the candidate we used and remove it above. But in - -- case we didn't, remove it + -- We should have meet the candidate we used and remove it above. + -- But in case we didn't, remove it. if self.filepath and lfs.attributes(self.filepath, "mode") == "file" then os.remove(self.filepath) end diff --git a/frontend/document/canvascontext.lua b/frontend/document/canvascontext.lua index 1b96f8f1e..9871bc1a1 100644 --- a/frontend/document/canvascontext.lua +++ b/frontend/document/canvascontext.lua @@ -14,7 +14,6 @@ Note: CanvasContext is a singleton and it is not thread safe. local Mupdf = require("ffi/mupdf") local CanvasContext = { - should_restrict_JIT = false, is_color_rendering_enabled = false, is_bgr = false, } @@ -24,7 +23,6 @@ Initialize CanvasContext with settings from device. The following key is required for a device object: -* should_restrict_JIT: bool * hasBGRFrameBuffer: function() -> boolean * screen: object with following methods: * getWidth() -> int @@ -51,7 +49,6 @@ function CanvasContext:init(device) self.isEmulator = device.isEmulator self.isKindle = device.isKindle self.isPocketBook = device.isPocketBook - self.should_restrict_JIT = device.should_restrict_JIT self.hasSystemFonts = device.hasSystemFonts self:setColorRenderingEnabled(device.screen:isColorEnabled()) diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index b4063c354..de21e888c 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -18,7 +18,7 @@ local time = require("ui/time") -- engine can be initialized only once, on first document opened local engine_initialized = false -local CreDocument = Document:new{ +local CreDocument = Document:extend{ -- this is defined in kpvcrlib/crengine/crengine/include/lvdocview.h SCROLL_VIEW_MODE = 0, PAGE_VIEW_MODE = 1, @@ -49,7 +49,7 @@ local CreDocument = Document:new{ -- require one to set FreeSans as fallback to get its nicer glyphes, which -- would override Noto Sans CJK good symbol glyphs with smaller ones -- (Noto Sans & Serif do not have these symbol glyphs). - fallback_fonts = { + fallback_fonts = { -- const "Noto Sans CJK SC", "Noto Naskh Arabic", "Noto Sans Devanagari UI", @@ -65,8 +65,8 @@ local CreDocument = Document:new{ provider_name = "Cool Reader Engine", hide_nonlinear_flows = false, - flows = {}, - page_in_flow = {}, + flows = nil, -- table + page_in_flow = nil, -- table last_linear_page = nil, } @@ -147,6 +147,9 @@ function CreDocument:init() self:updateColorRendering() self:engineInit() + self.flows = {} + self.page_in_flow = {} + local file_type = string.lower(string.match(self.file, ".+%.([^.]+)")) if file_type == "zip" then -- NuPogodi, 20.05.12: read the content of zip-file @@ -331,9 +334,11 @@ function CreDocument:close() end -- Only exists if the call cache is enabled + --[[ if self._callCacheDestroy then self._callCacheDestroy() end + --]] end end @@ -1510,14 +1515,27 @@ function CreDocument:setupCallCache() -- Stores the key for said current tag self._current_call_cache_tag = nil end + --[[ + --- @note: If explicitly destroying the references to the caches is necessary to get their content collected by the GC, + --- then you have a ref leak to this Document instance somewhere, + --- c.f., https://github.com/koreader/koreader/pull/7634#discussion_r627820424 + --- Keep in mind that a *lot* of ReaderUI modules keep a ref to document, so it may be fairly remote! + --- A good contender for issues like these would be references being stored in the class object instead + --- of in instance objects because of inheritance rules. c.f., https://github.com/koreader/koreader/pull/9586, + --- which got rid of a giant leak of every ReaderUI module via the active_widgets array... + --- A simple testing methodology is to create a dummy buffer alongside self.buffer in drawCurrentView, + --- push it to the global cache via _callCacheSet, and trace the BlitBuffer gc method in ffi/blitbuffer.lua. + --- You'll probably want to stick a pair of collectgarbage() calls somewhere in the UI loop + --- (e.g., at the coda of UIManager:close) to trip a GC pass earlier than the one in DocumentRegistry:openDocument. + --- (Keep in mind that, in UIManager:close, widget is still in scope inside the function, + --- so you'll have to close another widget to truly collect it (here, ReaderUI)). self._callCacheDestroy = function() - --- @note: Explicitly destroying the references to the caches is apparently necessary to get their content collected by the GC... - --- c.f., https://github.com/koreader/koreader/pull/7634#discussion_r627820424 self._global_call_cache = nil self._tag_list_call_cache = nil self._tag_call_cache = nil self._current_call_cache_tag = nil end + --]] -- global cache self._callCacheGet = function(key) return self._global_call_cache[key] diff --git a/frontend/document/djvudocument.lua b/frontend/document/djvudocument.lua index 4403c9602..122ed53f9 100644 --- a/frontend/document/djvudocument.lua +++ b/frontend/document/djvudocument.lua @@ -2,7 +2,7 @@ local Blitbuffer = require("ffi/blitbuffer") local Document = require("document/document") local DrawContext = require("ffi/drawcontext") -local DjvuDocument = Document:new{ +local DjvuDocument = Document:extend{ _document = false, -- libdjvulibre manages its own additional cache, default value is hard written in c module. is_djvu = true, diff --git a/frontend/document/doccache.lua b/frontend/document/doccache.lua index 95b9961b6..cb7c66774 100644 --- a/frontend/document/doccache.lua +++ b/frontend/document/doccache.lua @@ -45,6 +45,7 @@ local function computeCacheSlots() end end +-- NOTE: This is a singleton! local DocCache = Cache:new{ slots = computeCacheSlots(), size = computeCacheSize(), diff --git a/frontend/document/document.lua b/frontend/document/document.lua index d1f8bca5e..785ded438 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -16,13 +16,15 @@ This is an abstract interface to a document local Document = { -- file name file = nil, + -- engine instance + _document = nil, - links = {}, + links = nil, -- table GAMMA_NO_GAMMA = 1.0, -- override bbox from orignal page's getUsedBBox - bbox = {}, + bbox = nil, -- table -- flag to show whether the document was opened successfully is_open = false, @@ -40,10 +42,15 @@ local Document = { } -function Document:new(from_o) - local o = from_o or {} +function Document:extend(subclass_prototype) + local o = subclass_prototype or {} setmetatable(o, self) self.__index = self + return o +end + +function Document:new(o) + o = self:extend(o) if o._init then o:_init() end if o.init then o:init() end return o @@ -51,7 +58,9 @@ end -- base document initialization should be called on each document init function Document:_init() - self.configurable = Configurable:new() + self.links = {} + self.bbox = {} + self.configurable = Configurable:new{} self.info = { -- whether the document is pageable has_pages = false, diff --git a/frontend/document/documentregistry.lua b/frontend/document/documentregistry.lua index 36e4720fa..7310d73eb 100644 --- a/frontend/document/documentregistry.lua +++ b/frontend/document/documentregistry.lua @@ -23,8 +23,8 @@ function DocumentRegistry:addProvider(extension, mimetype, provider, weight) }) self.filetype_provider[extension] = true -- We regard the first extension registered for a mimetype as canonical. - -- Provided we order the calls to addProvider() correctly, that means - -- epub instead of epub3, etc. + -- Provided we order the calls to addProvider() correctly, + -- that means epub instead of epub3, etc. self.mimetype_ext[mimetype] = self.mimetype_ext[mimetype] or extension end diff --git a/frontend/document/pdfdocument.lua b/frontend/document/pdfdocument.lua index 8aded7e9a..174f13998 100644 --- a/frontend/document/pdfdocument.lua +++ b/frontend/document/pdfdocument.lua @@ -10,7 +10,7 @@ local ffi = require("ffi") local C = ffi.C local pdf = nil -local PdfDocument = Document:new{ +local PdfDocument = Document:extend{ _document = false, is_pdf = true, dc_null = DrawContext.new(), diff --git a/frontend/document/picdocument.lua b/frontend/document/picdocument.lua index 39685d8e6..a55c25901 100644 --- a/frontend/document/picdocument.lua +++ b/frontend/document/picdocument.lua @@ -3,7 +3,7 @@ local DrawContext = require("ffi/drawcontext") local CanvasContext = require("document/canvascontext") local pic = nil -local PicDocument = Document:new{ +local PicDocument = Document:extend{ _document = false, is_pic = true, dc_null = DrawContext.new(), diff --git a/frontend/document/tilecacheitem.lua b/frontend/document/tilecacheitem.lua index 3e849f9ca..2ec4ff344 100644 --- a/frontend/document/tilecacheitem.lua +++ b/frontend/document/tilecacheitem.lua @@ -3,7 +3,7 @@ local CacheItem = require("cacheitem") local Persist = require("persist") local logger = require("logger") -local TileCacheItem = CacheItem:new{} +local TileCacheItem = CacheItem:extend{} function TileCacheItem:onFree() logger.dbg("TileCacheItem: free blitbuffer", self.bb) diff --git a/frontend/dump.lua b/frontend/dump.lua index 06528bb47..515e0a8c3 100644 --- a/frontend/dump.lua +++ b/frontend/dump.lua @@ -1,5 +1,7 @@ --[[-- A simple serialization function which won't do uservalues, functions, or loops. + +If we ever need a more full-featured variant, the consensus seems to be https://github.com/pkulchenko/serpent ;). ]] local isUbuntuTouch = os.getenv("UBUNTU_APPLICATION_ISOLATION") ~= nil @@ -15,7 +17,8 @@ local function _serialize(what, outt, indent, max_lv, history, pairs_func) return end - if type(what) == "table" then + local datatype = type(what) + if datatype == "table" then history = history or {} for up, item in ipairs(history) do if item == what then @@ -43,9 +46,9 @@ local function _serialize(what, outt, indent, max_lv, history, pairs_func) insert(outt, string.rep(indent_prefix, indent)) end insert(outt, "}") - elseif type(what) == "string" then + elseif datatype == "string" then insert(outt, string.format("%q", what)) - elseif type(what) == "number" then + elseif datatype == "number" then if isUbuntuTouch then --- @fixme The `SDL_CreateRenderer` function in Ubuntu touch somehow -- use a strange locale that formats number like this: 1.10000000000000g+02 @@ -55,11 +58,11 @@ local function _serialize(what, outt, indent, max_lv, history, pairs_func) else insert(outt, tostring(what)) end - elseif type(what) == "boolean" then + elseif datatype == "boolean" then insert(outt, tostring(what)) - elseif type(what) == "function" then + elseif datatype == "function" then insert(outt, tostring(what)) - elseif type(what) == "nil" then + elseif datatype == "nil" then insert(outt, "nil") end end diff --git a/frontend/languagesupport.lua b/frontend/languagesupport.lua index 38d732a1c..ce237905a 100644 --- a/frontend/languagesupport.lua +++ b/frontend/languagesupport.lua @@ -2,7 +2,7 @@ Language-specific handling module. This module defines a somewhat generic system by which language-specific -plugins can improve KoReader's support for languages that are not close enough +plugins can improve KOReader's support for languages that are not close enough to European languages to "just work". This was originally designed to improve KoReader's Japanese support through the @@ -29,10 +29,10 @@ local _ = require("gettext") -- plugins when reloading different viewers. local PluginListSingleton = {} -local LanguageSupport = WidgetContainer:new({ +local LanguageSupport = WidgetContainer:extend{ name = "language_support", plugins = PluginListSingleton, -}) +} --[[-- Registers a new language-specific plugin with given language_code. diff --git a/frontend/luadata.lua b/frontend/luadata.lua index 689b4720e..d9c3561ab 100644 --- a/frontend/luadata.lua +++ b/frontend/luadata.lua @@ -3,31 +3,29 @@ Handles append-mostly data such as KOReader's bookmarks and dictionary search hi ]] local LuaSettings = require("luasettings") -local dbg = require("dbg") local dump = require("dump") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local util = require("util") -local LuaData = LuaSettings:new{ +local LuaData = LuaSettings:extend{ name = "", max_backups = 9, } --- Creates a new LuaData instance. -function LuaData:open(file_path, o) -- luacheck: ignore 312 - if o and type(o) ~= "table" then - if dbg.is_on then - error("LuaData: got "..type(o)..", table expected") - else - o = {} - end +function LuaData:open(file_path, name) + -- Backwards compat, just in case... + if type(name) == "table" then + name = name.name end - -- always initiate a new instance - -- careful, `o` is already a table so we use parentheses - self = LuaData:new(o) - local new = {file=file_path, data={}} + -- NOTE: Beware, our new instance is new, but self is still LuaData! + local new = LuaData:extend{ + name = name, + file = file_path, + data = {}, + } -- Some magic to allow for self-describing function names: -- We'll use data_env both as the environment when loading the data, *and* its metatable, @@ -40,7 +38,7 @@ function LuaData:open(file_path, o) -- luacheck: ignore 312 local data_env = {} data_env.__index = data_env setmetatable(data_env, data_env) - data_env[self.name.."Entry"] = function(table) + data_env[new.name.."Entry"] = function(table) if table.index then -- We've got a deleted setting, overwrite with nil and be done with it. if not table.data then @@ -81,7 +79,7 @@ function LuaData:open(file_path, o) -- luacheck: ignore 312 end end if not ok then - for i=1, self.max_backups, 1 do + for i=1, new.max_backups, 1 do local backup_file = new.file..".old."..i if lfs.attributes(backup_file, "mode") == "file" then ok, err = loadfile(backup_file, "t", data_env) @@ -97,7 +95,7 @@ function LuaData:open(file_path, o) -- luacheck: ignore 312 end end - return setmetatable(new, {__index = self}) + return new end --- Saves a setting. diff --git a/frontend/luadefaults.lua b/frontend/luadefaults.lua index 00997c026..08ae0fcf1 100644 --- a/frontend/luadefaults.lua +++ b/frontend/luadefaults.lua @@ -11,7 +11,7 @@ local isAndroid, android = pcall(require, "android") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") -local LuaDefaults = LuaSettings:new{ +local LuaDefaults = LuaSettings:extend{ ro = nil, -- will contain the defaults.lua k/v pairs (const) rw = nil, -- will only contain non-defaults user-modified k/v pairs } @@ -19,7 +19,9 @@ local LuaDefaults = LuaSettings:new{ --- Opens a settings file. function LuaDefaults:open(path) local file_path = path or DataStorage:getDataDir() .. "/defaults.custom.lua" - local new = {file = file_path} + local new = LuaDefaults:extend{ + file = file_path, + } local ok, stored -- File being absent and returning an empty table is a use case, @@ -57,7 +59,7 @@ function LuaDefaults:open(path) error("Failed reading " .. defaults_path) end - return setmetatable(new, {__index = LuaDefaults}) + return new end --- Reads a setting, optionally initializing it to a default. @@ -161,11 +163,10 @@ function LuaDefaults:flush() if not self.file then return end local directory_updated = false if lfs.attributes(self.file, "mode") == "file" then - -- As an additional safety measure (to the ffiutil.fsync* calls - -- used below), we only backup the file to .old when it has - -- not been modified in the last 60 seconds. This should ensure - -- in the case the fsync calls are not supported that the OS - -- may have itself sync'ed that file content in the meantime. + -- As an additional safety measure (to the ffiutil.fsync* calls used below), + -- we only backup the file to .old when it has not been modified in the last 60 seconds. + -- This should ensure in the case the fsync calls are not supported + -- that the OS may have itself sync'ed that file content in the meantime. local mtime = lfs.attributes(self.file, "modification") if mtime < os.time() - 60 then os.rename(self.file, self.file .. ".old") diff --git a/frontend/luasettings.lua b/frontend/luasettings.lua index 6391be385..f20d54962 100644 --- a/frontend/luasettings.lua +++ b/frontend/luasettings.lua @@ -9,16 +9,19 @@ local logger = require("logger") local LuaSettings = {} -function LuaSettings:new(o) +function LuaSettings:extend(o) o = o or {} setmetatable(o, self) self.__index = self return o end +-- NOTE: Instances are created via open, so we do *NOT* implement a new method, to avoid confusion. --- Opens a settings file. function LuaSettings:open(file_path) - local new = {file=file_path} + local new = LuaSettings:extend{ + file = file_path, + } local ok, stored -- File being absent and returning an empty table is a use case, @@ -41,13 +44,13 @@ function LuaSettings:open(file_path) end end - return setmetatable(new, {__index = LuaSettings}) + return new end ---- @todo DocSettings can return a LuaSettings to use following awesome features. function LuaSettings:wrap(data) - local new = {data = type(data) == "table" and data or {}} - return setmetatable(new, {__index = LuaSettings}) + return self:extend{ + data = type(data) == "table" and data or {}, + } end --[[--Reads child settings. @@ -66,7 +69,7 @@ end -- result "b" ]] function LuaSettings:child(key) - return LuaSettings:wrap(self:readSetting(key)) + return self:wrap(self:readSetting(key)) end --[[-- Reads a setting, optionally initializing it to a default. @@ -251,11 +254,10 @@ function LuaSettings:flush() if not self.file then return end local directory_updated = false if lfs.attributes(self.file, "mode") == "file" then - -- As an additional safety measure (to the ffiutil.fsync* calls - -- used below), we only backup the file to .old when it has - -- not been modified in the last 60 seconds. This should ensure - -- in the case the fsync calls are not supported that the OS - -- may have itself sync'ed that file content in the meantime. + -- As an additional safety measure (to the ffiutil.fsync* calls used below), + -- we only backup the file to .old when it has not been modified in the last 60 seconds. + -- This should ensure in the case the fsync calls are not supported + -- that the OS may have itself sync'ed that file content in the meantime. local mtime = lfs.attributes(self.file, "modification") if mtime < os.time() - 60 then os.rename(self.file, self.file .. ".old") diff --git a/frontend/pluginloader.lua b/frontend/pluginloader.lua index 2b7d26cd2..d242c3e74 100644 --- a/frontend/pluginloader.lua +++ b/frontend/pluginloader.lua @@ -89,7 +89,7 @@ function PluginLoader:loadPlugins() if type(plugins_disabled) ~= "table" then plugins_disabled = {} end - --disable obsolete plugins + -- disable obsolete plugins for element in pairs(OBSOLETE_PLUGINS) do plugins_disabled[element] = true end diff --git a/frontend/pluginshare.lua b/frontend/pluginshare.lua index a76eb3bac..ff5d44767 100644 --- a/frontend/pluginshare.lua +++ b/frontend/pluginshare.lua @@ -1,5 +1,6 @@ --- PluginShare is a table for plugins to exchange data between each other. Plugins should maintain --- their own protocols. +-- PluginShare is a table for plugins to exchange data between each other. +-- It is a singleton, which will persist across views (and, as such, across plugins lifecycle). +-- Plugins should maintain their own protocols. return { backgroundJobs = {}, } diff --git a/frontend/readhistory.lua b/frontend/readhistory.lua index bf3c8ab80..ea2df2aa9 100644 --- a/frontend/readhistory.lua +++ b/frontend/readhistory.lua @@ -9,6 +9,7 @@ local realpath = ffiutil.realpath local history_file = joinPath(DataStorage:getDataDir(), "history.lua") +-- This is a singleton local ReadHistory = { hist = {}, last_read_time = 0, @@ -70,7 +71,6 @@ local function timeFirstOrdering(l, r) end function ReadHistory:_indexing(start) - assert(self ~= nil) --- @todo (Hzj_jie): Use binary search to find an item when deleting it. for i = start, #self.hist, 1 do self.hist[i].index = i @@ -78,7 +78,6 @@ function ReadHistory:_indexing(start) end function ReadHistory:_sort() - assert(self ~= nil) local autoremove_deleted_items_from_history = not G_reader_settings:nilOrFalse("autoremove_deleted_items_from_history") if autoremove_deleted_items_from_history then @@ -98,7 +97,6 @@ end -- Reduces total count in hist list to a reasonable number by removing last -- several items. function ReadHistory:_reduce() - assert(self ~= nil) while #self.hist > 500 do table.remove(self.hist, #self.hist) end @@ -106,7 +104,6 @@ end -- Flushes current history table into file. function ReadHistory:_flush() - assert(self ~= nil) local content = {} for _, v in ipairs(self.hist) do table.insert(content, { @@ -115,15 +112,16 @@ function ReadHistory:_flush() }) end local f = io.open(history_file, "w") - f:write("return " .. dump(content) .. "\n") - ffiutil.fsyncOpenedFile(f) -- force flush to the storage device - f:close() + if f then + f:write("return " .. dump(content) .. "\n") + ffiutil.fsyncOpenedFile(f) -- force flush to the storage device + f:close() + end end --- Reads history table from file. -- @treturn boolean true if the history_file has been updated and reloaded. function ReadHistory:_read(force_read) - assert(self ~= nil) local history_file_modification_time = lfs.attributes(history_file, "modification") if history_file_modification_time == nil or (not force_read and (history_file_modification_time <= self.last_read_time)) then @@ -142,7 +140,6 @@ end -- Reads history from legacy history folder function ReadHistory:_readLegacyHistory() - assert(self ~= nil) local history_dir = DataStorage:getHistoryDir() for f in lfs.dir(history_dir) do local path = joinPath(history_dir, f) @@ -162,7 +159,6 @@ function ReadHistory:_readLegacyHistory() end function ReadHistory:_init() - assert(self ~= nil) self:reload() end @@ -199,7 +195,6 @@ function ReadHistory:getPreviousFile(current_file) end function ReadHistory:getFileByDirectory(directory, recursive) - assert(self ~= nil) local real_path = realpath(directory) for i=1, #self.hist do local ipath = realpath(ffiutil.dirname(self.hist[i].file)) @@ -232,7 +227,6 @@ function ReadHistory:fileSettingsPurged(path) end function ReadHistory:clearMissing() - assert(self ~= nil) for i = #self.hist, 1, -1 do if self.hist[i].file == nil or lfs.attributes(self.hist[i].file, "mode") ~= "file" then self:removeItem(self.hist[i], i) @@ -242,7 +236,6 @@ function ReadHistory:clearMissing() end function ReadHistory:removeItemByPath(path) - assert(self ~= nil) for i = #self.hist, 1, -1 do if self.hist[i].file == path then self:removeItem(self.hist[i]) @@ -253,7 +246,6 @@ function ReadHistory:removeItemByPath(path) end function ReadHistory:updateItemByPath(old_path, new_path) - assert(self ~= nil) for i = #self.hist, 1, -1 do if self.hist[i].file == old_path then self.hist[i].file = new_path @@ -273,7 +265,6 @@ function ReadHistory:updateItemByPath(old_path, new_path) end function ReadHistory:removeItem(item, idx) - assert(self ~= nil) table.remove(self.hist, item.index or idx) os.remove(DocSettings:getHistoryPath(item.file)) self:_indexing(item.index or idx) @@ -282,7 +273,6 @@ function ReadHistory:removeItem(item, idx) end function ReadHistory:addItem(file, ts) - assert(self ~= nil) if file ~= nil and lfs.attributes(file, "mode") == "file" then local now = ts or os.time() table.insert(self.hist, 1, buildEntry(now, file)) @@ -303,7 +293,6 @@ end --- Reloads history from history_file. -- @treturn boolean true if history_file has been updated and reload happened. function ReadHistory:reload(force_read) - assert(self ~= nil) if self:_read(force_read) then self:_readLegacyHistory() self:_sort() diff --git a/frontend/socketutil.lua b/frontend/socketutil.lua index 357180255..4a62985c3 100644 --- a/frontend/socketutil.lua +++ b/frontend/socketutil.lua @@ -90,9 +90,6 @@ socketutil.SINK_TIMEOUT_CODE = "sink timeout" -- from our own socketutil -- NOTE: Use os.time() for simplicity's sake (we don't really need subsecond precision). -- LuaSocket itself is already using gettimeofday anyway (although it does the maths, like ffi/util's getTimestamp). --- Proper etiquette would have everyone using clock_gettime(CLOCK_MONOTONIC) for this kind of stuff, --- but it's a tad more annoying to use because it's stuffed in librt in old glibc versions, --- and I have no idea what macOS & Android do with it (but it is POSIX). Plus, win32. --- Custom version of `ltn12.sink.table` that honors total_timeout function socketutil.table_sink(t) if socketutil.total_timeout < 0 then diff --git a/frontend/ui/data/keyboardlayouts/ko_KR_helper.lua b/frontend/ui/data/keyboardlayouts/ko_KR_helper.lua index 6a568ef0a..3abf1c460 100644 --- a/frontend/ui/data/keyboardlayouts/ko_KR_helper.lua +++ b/frontend/ui/data/keyboardlayouts/ko_KR_helper.lua @@ -213,7 +213,7 @@ local HgFSM = { final = nil, fsm_state = nil, - fsm_prev_states = {}, + fsm_prev_states = nil, -- array do_not_del_in_medial = false, diff --git a/frontend/ui/data/keyboardlayouts/zh_ime.lua b/frontend/ui/data/keyboardlayouts/zh_ime.lua index 10aa32871..3008d99bc 100644 --- a/frontend/ui/data/keyboardlayouts/zh_ime.lua +++ b/frontend/ui/data/keyboardlayouts/zh_ime.lua @@ -48,7 +48,7 @@ end local _stack local IME = { - code_map = {}, + code_map = nil, -- hash, mandatory key_map = nil, -- input key to code map keys_string = "abcdefghijklmnopqrstuvwxyz", iter_map = nil, -- next code when using wildcard @@ -351,4 +351,4 @@ function IME:wrappedAddChars(inputbox, char) end end -return IME \ No newline at end of file +return IME diff --git a/frontend/ui/hook_container.lua b/frontend/ui/hook_container.lua index 1ec3e019b..cf485197c 100644 --- a/frontend/ui/hook_container.lua +++ b/frontend/ui/hook_container.lua @@ -15,18 +15,15 @@ function HookContainer:new(o) end function HookContainer:_assertIsValidName(name) - assert(self ~= nil) assert(type(name) == "string") assert(string.len(name) > 0) end function HookContainer:_assertIsValidFunction(func) - assert(self ~= nil) assert(type(func) == "function" or type(func) == "table") end function HookContainer:_assertIsValidFunctionOrNil(func) - assert(self ~= nil) if func == nil then return end self:_assertIsValidFunction(func) end diff --git a/frontend/ui/message/filemessagequeue.lua b/frontend/ui/message/filemessagequeue.lua index 941524db8..de9c67f3f 100644 --- a/frontend/ui/message/filemessagequeue.lua +++ b/frontend/ui/message/filemessagequeue.lua @@ -5,7 +5,7 @@ local _ = require("ffi/zeromq_h") local czmq = ffi.load("libs/libczmq.so.1") local filemq = ffi.load("libs/libfmq.so.1") -local FileMessageQueue = MessageQueue:new{ +local FileMessageQueue = MessageQueue:extend{ client = nil, server = nil, } diff --git a/frontend/ui/message/messagequeue.lua b/frontend/ui/message/messagequeue.lua index 510f966c9..da06b87eb 100644 --- a/frontend/ui/message/messagequeue.lua +++ b/frontend/ui/message/messagequeue.lua @@ -7,10 +7,15 @@ local czmq = ffi.load("libs/libczmq.so.1") local MessageQueue = {} -function MessageQueue:new(o) - o = o or {} +function MessageQueue:extend(subclass_prototype) + local o = subclass_prototype or {} setmetatable(o, self) self.__index = self + return o +end + +function MessageQueue:new(o) + o = self:extend(o) if o.init then o:init() end self.messages = {} return o diff --git a/frontend/ui/message/streammessagequeue.lua b/frontend/ui/message/streammessagequeue.lua index 995b3d171..8058b5ce5 100644 --- a/frontend/ui/message/streammessagequeue.lua +++ b/frontend/ui/message/streammessagequeue.lua @@ -7,7 +7,7 @@ local zmq = ffi.load("libs/libzmq.so.4") local czmq = ffi.load("libs/libczmq.so.1") local C = ffi.C -local StreamMessageQueue = MessageQueue:new{ +local StreamMessageQueue = MessageQueue:extend{ host = nil, port = nil, } diff --git a/frontend/ui/network/networklistener.lua b/frontend/ui/network/networklistener.lua index f30813be2..3cf99623e 100644 --- a/frontend/ui/network/networklistener.lua +++ b/frontend/ui/network/networklistener.lua @@ -1,15 +1,15 @@ local BD = require("ui/bidi") local Device = require("device") local Event = require("ui/event") +local EventListener = require("ui/widget/eventlistener") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local NetworkMgr = require("ui/network/manager") local UIManager = require("ui/uimanager") local logger = require("logger") local _ = require("gettext") local T = require("ffi/util").template -local NetworkListener = InputContainer:new{} +local NetworkListener = EventListener:extend{} function NetworkListener:onToggleWifi() if not NetworkMgr:isWifiOn() then diff --git a/frontend/ui/plugin/switch_plugin.lua b/frontend/ui/plugin/switch_plugin.lua index ce8888b6b..20c7e5807 100644 --- a/frontend/ui/plugin/switch_plugin.lua +++ b/frontend/ui/plugin/switch_plugin.lua @@ -11,7 +11,7 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local _ = require("gettext") -local SwitchPlugin = WidgetContainer:new() +local SwitchPlugin = WidgetContainer:extend{} function SwitchPlugin:extend(o) o = o or {} diff --git a/frontend/ui/rendertext.lua b/frontend/ui/rendertext.lua index d9fc5c1f2..f232fda47 100644 --- a/frontend/ui/rendertext.lua +++ b/frontend/ui/rendertext.lua @@ -6,17 +6,12 @@ local bit = require("bit") local Font = require("ui/font") local Cache = require("cache") local Blitbuffer = require("ffi/blitbuffer") -local Device = require("device") local logger = require("logger") local band = bit.band local bor = bit.bor local lshift = bit.lshift -if Device.should_restrict_JIT then - jit.off(true, true) -end - --[[ @TODO: all these functions should probably be methods on Face objects ]]-- diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index 8d7b13b5a..1117cf5f9 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -54,12 +54,14 @@ end local Screensaver = { screensaver_provider = { + gif = true, jpg = true, jpeg = true, png = true, - gif = true, + svg = true, tif = true, tiff = true, + webp = true, }, default_screensaver_message = _("Sleeping"), } diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index bb4f15628..dd159f1ad 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -16,7 +16,7 @@ local Screen = Device.screen local DEFAULT_FULL_REFRESH_COUNT = 6 --- there is only one instance of this +-- This is a singleton local UIManager = { -- trigger a full refresh when counter reaches FULL_REFRESH_COUNT FULL_REFRESH_COUNT = @@ -60,6 +60,7 @@ function UIManager:init() } self.poweroff_action = function() self._entered_poweroff_stage = true + logger.info("Powering off the device...") Device.orig_rotation_mode = Device.screen:getRotationMode() self:broadcastEvent(Event:new("Close")) Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) @@ -74,6 +75,7 @@ function UIManager:init() end self.reboot_action = function() self._entered_poweroff_stage = true + logger.info("Rebooting the device...") Device.orig_rotation_mode = Device.screen:getRotationMode() self:broadcastEvent(Event:new("Close")) Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) diff --git a/frontend/ui/widget/bboxwidget.lua b/frontend/ui/widget/bboxwidget.lua index ef72e672b..d6a6a77cf 100644 --- a/frontend/ui/widget/bboxwidget.lua +++ b/frontend/ui/widget/bboxwidget.lua @@ -12,7 +12,7 @@ local Screen = Device.screen local Size = require("ui/size") local UIManager = require("ui/uimanager") -local BBoxWidget = InputContainer:new{ +local BBoxWidget = InputContainer:extend{ page_bbox = nil, screen_bbox = nil, linesize = Size.line.thick, diff --git a/frontend/ui/widget/bookmapwidget.lua b/frontend/ui/widget/bookmapwidget.lua index d65e4472a..6cd89be90 100644 --- a/frontend/ui/widget/bookmapwidget.lua +++ b/frontend/ui/widget/bookmapwidget.lua @@ -23,6 +23,7 @@ local UIManager = require("ui/uimanager") local VerticalGroup = require("ui/widget/verticalgroup") local VerticalSpan = require("ui/widget/verticalspan") local Widget = require("ui/widget/widget") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local Input = Device.input local Screen = Device.screen local logger = require("logger") @@ -30,7 +31,7 @@ local util = require("util") local _ = require("gettext") -- BookMapRow (reused by PageBrowserWidget) -local BookMapRow = InputContainer:new{ +local BookMapRow = WidgetContainer:extend{ width = nil, height = nil, pages_frame_border = Size.border.default, @@ -102,7 +103,7 @@ end function BookMapRow:init() local _mirroredUI = BD.mirroredUILayout() - self.dimen = Geom:new{ w = self.width, h = self.height } + self.dimen = Geom:new{ x = 0, y = 0, w = self.width, h = self.height } -- Keep one span_height under baseline (frame bottom border) for indicators (current page, bookmarks) self.pages_frame_height = self.height - self.span_height @@ -517,7 +518,7 @@ function BookMapRow:paintTo(bb, x, y) end -- BookMapWidget: shows a map of content, including TOC, boomarks, read pages, non-linear flows... -local BookMapWidget = InputContainer:new{ +local BookMapWidget = InputContainer:extend{ title = _("Book map"), -- Focus page: show the BookMapRow containing this page -- in the middle of screen @@ -538,6 +539,8 @@ function BookMapWidget:init() -- Compute non-settings-dependant sizes and options self.dimen = Geom:new{ + x = 0, + y = 0, w = Screen:getWidth(), h = Screen:getHeight(), } diff --git a/frontend/ui/widget/bookstatuswidget.lua b/frontend/ui/widget/bookstatuswidget.lua index 6aa7603d2..0364f4ad4 100644 --- a/frontend/ui/widget/bookstatuswidget.lua +++ b/frontend/ui/widget/bookstatuswidget.lua @@ -32,37 +32,32 @@ local T = require("ffi/util").template local stats_book = {} --[[ ---Save into sdr folder addtional section +-- Stored in the sidecar metadata, in a dedicated table: ["summary"] = { ["rating"] = 5, ["note"] = "Some text", ["status"] = "Reading" ["modified"] = "24.01.2016" },]] -local BookStatusWidget = FocusManager:new{ +local BookStatusWidget = FocusManager:extend{ padding = Size.padding.fullscreen, settings = nil, thumbnail = nil, props = nil, - star = {}, - summary = { - rating = nil, - note = nil, - status = "", - modified = "", - }, + star = nil, -- Button + summary = nil, -- hash } function BookStatusWidget:init() self.layout = {} + -- What a blank, full summary table should look like + local new_summary = { + rating = nil, + note = nil, + status = "", + modified = "", + } if self.settings then - -- What a blank, full summary table should look like - local new_summary = { - rating = nil, - note = nil, - status = "", - modified = "", - } local summary = self.settings:readSetting("summary") -- Check if the summary table we get is a full one, or a minimal one from CoverMenu... if summary then @@ -77,6 +72,8 @@ function BookStatusWidget:init() else self.summary = new_summary end + else + self.summary = new_summary end self.total_pages = self.ui.document:getPageCount() stats_book = self:getStats() diff --git a/frontend/ui/widget/button.lua b/frontend/ui/widget/button.lua index 353ccbdfd..ef9df5bc6 100644 --- a/frontend/ui/widget/button.lua +++ b/frontend/ui/widget/button.lua @@ -35,7 +35,7 @@ local logger = require("logger") local DGENERIC_ICON_SIZE = G_defaults:readSetting("DGENERIC_ICON_SIZE") -local Button = InputContainer:new{ +local Button = InputContainer:extend{ text = nil, -- mandatory (unless icon is provided) text_func = nil, icon = nil, diff --git a/frontend/ui/widget/buttondialog.lua b/frontend/ui/widget/buttondialog.lua index da0874f0b..32e989e10 100644 --- a/frontend/ui/widget/buttondialog.lua +++ b/frontend/ui/widget/buttondialog.lua @@ -12,7 +12,7 @@ local UIManager = require("ui/uimanager") local _ = require("gettext") local Screen = require("device").screen -local ButtonDialog = InputContainer:new{ +local ButtonDialog = InputContainer:extend{ buttons = nil, tap_close_callback = nil, alpha = nil, -- passed to MovableContainer diff --git a/frontend/ui/widget/buttondialogtitle.lua b/frontend/ui/widget/buttondialogtitle.lua index 81945a68b..48737bb42 100644 --- a/frontend/ui/widget/buttondialogtitle.lua +++ b/frontend/ui/widget/buttondialogtitle.lua @@ -16,7 +16,7 @@ local VerticalSpan = require("ui/widget/verticalspan") local _ = require("gettext") local Screen = Device.screen -local ButtonDialogTitle = InputContainer:new{ +local ButtonDialogTitle = InputContainer:extend{ title = nil, title_align = nil, title_face = Font:getFace("x_smalltfont"), diff --git a/frontend/ui/widget/buttonprogresswidget.lua b/frontend/ui/widget/buttonprogresswidget.lua index 0bc98c1b4..3b1c7aeb1 100644 --- a/frontend/ui/widget/buttonprogresswidget.lua +++ b/frontend/ui/widget/buttonprogresswidget.lua @@ -11,7 +11,7 @@ local UIManager = require("ui/uimanager") local _ = require("gettext") local Screen = Device.screen -local ButtonProgressWidget = FocusManager:new{ +local ButtonProgressWidget = FocusManager:extend{ width = Screen:scaleBySize(216), height = Size.item.height_default, padding = Size.padding.small, diff --git a/frontend/ui/widget/buttontable.lua b/frontend/ui/widget/buttontable.lua index ca7cba672..a48a5b8dc 100644 --- a/frontend/ui/widget/buttontable.lua +++ b/frontend/ui/widget/buttontable.lua @@ -10,7 +10,7 @@ local VerticalSpan = require("ui/widget/verticalspan") local Geom = require("ui/geometry") local Screen = Device.screen -local ButtonTable = FocusManager:new{ +local ButtonTable = FocusManager:extend{ width = nil, buttons = { { diff --git a/frontend/ui/widget/checkbutton.lua b/frontend/ui/widget/checkbutton.lua index de2cbd222..26b878551 100644 --- a/frontend/ui/widget/checkbutton.lua +++ b/frontend/ui/widget/checkbutton.lua @@ -27,7 +27,7 @@ local UIManager = require("ui/uimanager") local VerticalGroup = require("ui/widget/verticalgroup") local VerticalSpan = require("ui/widget/verticalspan") -local CheckButton = InputContainer:new{ +local CheckButton = InputContainer:extend{ callback = nil, hold_callback = nil, checkable = true, -- empty space when false diff --git a/frontend/ui/widget/checkmark.lua b/frontend/ui/widget/checkmark.lua index 4f9c44b1d..b2963a3b8 100644 --- a/frontend/ui/widget/checkmark.lua +++ b/frontend/ui/widget/checkmark.lua @@ -17,11 +17,11 @@ Example: local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Font = require("ui/font") -local InputContainer = require("ui/widget/container/inputcontainer") local OverlapGroup = require("ui/widget/overlapgroup") local TextWidget = require("ui/widget/textwidget") +local WidgetContainer = require("ui/widget/container/widgetcontainer") -local CheckMark = InputContainer:new{ +local CheckMark = WidgetContainer:extend{ checkable = true, checked = false, enabled = true, diff --git a/frontend/ui/widget/closebutton.lua b/frontend/ui/widget/closebutton.lua index 49887432a..aecfc8c90 100644 --- a/frontend/ui/widget/closebutton.lua +++ b/frontend/ui/widget/closebutton.lua @@ -19,7 +19,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local TextWidget = require("ui/widget/textwidget") local Screen = require("device").screen -local CloseButton = InputContainer:new{ +local CloseButton = InputContainer:extend{ overlap_align = "right", window = nil, padding_left = Screen:scaleBySize(14), -- for larger touch area diff --git a/frontend/ui/widget/configdialog.lua b/frontend/ui/widget/configdialog.lua index 7a650d612..dcc80743f 100644 --- a/frontend/ui/widget/configdialog.lua +++ b/frontend/ui/widget/configdialog.lua @@ -35,7 +35,7 @@ local T = require("ffi/util").template local DGENERIC_ICON_SIZE = G_defaults:readSetting("DGENERIC_ICON_SIZE") -local OptionTextItem = InputContainer:new{} +local OptionTextItem = InputContainer:extend{} function OptionTextItem:init() local text_widget = self[1] @@ -110,7 +110,7 @@ function OptionTextItem:onHoldSelect() return true end -local OptionIconItem = InputContainer:new{} +local OptionIconItem = InputContainer:extend{} function OptionIconItem:init() self.underline_container = UnderlineContainer:new{ @@ -185,7 +185,7 @@ function OptionIconItem:onHoldSelect() return true end -local ConfigOption = CenterContainer:new{} +local ConfigOption = CenterContainer:extend{} function ConfigOption:init() -- make default styles @@ -706,7 +706,7 @@ function ConfigOption:_itemGroupToLayoutLine(option_items_group) return layout_line end -local ConfigPanel = FrameContainer:new{ +local ConfigPanel = FrameContainer:extend{ background = Blitbuffer.COLOR_WHITE, bordersize = 0, } @@ -724,7 +724,7 @@ function ConfigPanel:init() table.insert(self, panel) end -local MenuBar = FrameContainer:new{ +local MenuBar = FrameContainer:extend{ bordersize = 0, padding = 0, background = Blitbuffer.COLOR_WHITE, @@ -860,7 +860,7 @@ Widget that displays config menubar and config panel --]] -local ConfigDialog = FocusManager:new{ +local ConfigDialog = FocusManager:extend{ --is_borderless = false, name = "ConfigDialog", panel_index = 1, diff --git a/frontend/ui/widget/confirmbox.lua b/frontend/ui/widget/confirmbox.lua index fd892031a..1ef9e22b3 100644 --- a/frontend/ui/widget/confirmbox.lua +++ b/frontend/ui/widget/confirmbox.lua @@ -39,7 +39,7 @@ local _ = require("gettext") local Input = Device.input local Screen = Device.screen -local ConfirmBox = InputContainer:new{ +local ConfirmBox = InputContainer:extend{ modal = true, keep_dialog_open = false, text = _("no text"), diff --git a/frontend/ui/widget/container/alphacontainer.lua b/frontend/ui/widget/container/alphacontainer.lua index 0d51c9284..3cd86969f 100644 --- a/frontend/ui/widget/container/alphacontainer.lua +++ b/frontend/ui/widget/container/alphacontainer.lua @@ -19,7 +19,7 @@ Example: local Blitbuffer = require("ffi/blitbuffer") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local AlphaContainer = WidgetContainer:new{ +local AlphaContainer = WidgetContainer:extend{ alpha = 1, -- we cache a blitbuffer object for re-use here: private_bb = nil, diff --git a/frontend/ui/widget/container/bottomcontainer.lua b/frontend/ui/widget/container/bottomcontainer.lua index 142541274..a0c29e662 100644 --- a/frontend/ui/widget/container/bottomcontainer.lua +++ b/frontend/ui/widget/container/bottomcontainer.lua @@ -6,7 +6,7 @@ dimensions local Geom = require("ui/geometry") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local BottomContainer = WidgetContainer:new() +local BottomContainer = WidgetContainer:extend{} function BottomContainer:paintTo(bb, x, y) local contentSize = self[1]:getSize() diff --git a/frontend/ui/widget/container/centercontainer.lua b/frontend/ui/widget/container/centercontainer.lua index 1836ef413..77d06ca36 100644 --- a/frontend/ui/widget/container/centercontainer.lua +++ b/frontend/ui/widget/container/centercontainer.lua @@ -4,7 +4,7 @@ CenterContainer centers its content (1 widget) within its own dimensions local WidgetContainer = require("ui/widget/container/widgetcontainer") -local CenterContainer = WidgetContainer:new() +local CenterContainer = WidgetContainer:extend{} function CenterContainer:paintTo(bb, x, y) local content_size = self[1]:getSize() diff --git a/frontend/ui/widget/container/framecontainer.lua b/frontend/ui/widget/container/framecontainer.lua index d11016382..4f57ab6e5 100644 --- a/frontend/ui/widget/container/framecontainer.lua +++ b/frontend/ui/widget/container/framecontainer.lua @@ -24,7 +24,7 @@ local Geom = require("ui/geometry") local Size = require("ui/size") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local FrameContainer = WidgetContainer:new{ +local FrameContainer = WidgetContainer:extend{ background = nil, color = Blitbuffer.COLOR_BLACK, margin = 0, diff --git a/frontend/ui/widget/container/inputcontainer.lua b/frontend/ui/widget/container/inputcontainer.lua index 5e8e65f18..7f5adf259 100644 --- a/frontend/ui/widget/container/inputcontainer.lua +++ b/frontend/ui/widget/container/inputcontainer.lua @@ -25,40 +25,27 @@ and to store that table as a configuration setting. ]] local DepGraph = require("depgraph") +local Device = require("device") local Event = require("ui/event") local Geom = require("ui/geometry") local GestureRange = require("ui/gesturerange") local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local Device = require("device") local Screen = Device.screen local _ = require("gettext") -if Device.should_restrict_JIT then - jit.off(true, true) -end - -local InputContainer = WidgetContainer:new{ +local InputContainer = WidgetContainer:extend{ vertical_align = "top", } function InputContainer:_init() - -- we need to do deep copy here - local new_key_events = {} - if self.key_events then - for k,v in pairs(self.key_events) do - new_key_events[k] = v - end + -- These should be instance-specific + if not self.key_events then + self.key_events = {} end - self.key_events = new_key_events - - local new_ges_events = {} - if self.ges_events then - for k,v in pairs(self.ges_events) do - new_ges_events[k] = v - end + if not self.ges_events then + self.ges_events = {} end - self.ges_events = new_ges_events self.touch_zone_dg = nil self._zones = {} self._ordered_touch_zones = {} @@ -74,7 +61,7 @@ function InputContainer:paintTo(bb, x, y) if not self.dimen then local content_size = self[1]:getSize() - self.dimen = Geom:new{w = content_size.w, h = content_size.h} + self.dimen = Geom:new{x = 0, y = 0, w = content_size.w, h = content_size.h} end self.dimen.x = x self.dimen.y = y diff --git a/frontend/ui/widget/container/leftcontainer.lua b/frontend/ui/widget/container/leftcontainer.lua index 1d6b7ff8e..e003825ed 100644 --- a/frontend/ui/widget/container/leftcontainer.lua +++ b/frontend/ui/widget/container/leftcontainer.lua @@ -5,7 +5,7 @@ LeftContainer aligns its content (1 widget) at the left of its own dimensions local BD = require("ui/bidi") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local LeftContainer = WidgetContainer:new{ +local LeftContainer = WidgetContainer:extend{ allow_mirroring = true, } diff --git a/frontend/ui/widget/container/movablecontainer.lua b/frontend/ui/widget/container/movablecontainer.lua index 383584526..931e7f01c 100644 --- a/frontend/ui/widget/container/movablecontainer.lua +++ b/frontend/ui/widget/container/movablecontainer.lua @@ -23,7 +23,7 @@ local UIManager = require("ui/uimanager") local Screen = Device.screen local logger = require("logger") -local MovableContainer = InputContainer:new{ +local MovableContainer = InputContainer:extend{ -- Alpha value for subwidget transparency -- 0 = fully invisible, 1 = fully opaque (0.6 / 0.7 / 0.8 are some interesting values) alpha = nil, @@ -106,7 +106,7 @@ function MovableContainer:paintTo(bb, x, y) local content_size = self[1]:getSize() if not self.dimen then - self.dimen = Geom:new{w = content_size.w, h = content_size.h} + self.dimen = Geom:new{x = 0, y = 0, w = content_size.w, h = content_size.h} end self._orig_x = x diff --git a/frontend/ui/widget/container/rightcontainer.lua b/frontend/ui/widget/container/rightcontainer.lua index a25b79376..29eef6245 100644 --- a/frontend/ui/widget/container/rightcontainer.lua +++ b/frontend/ui/widget/container/rightcontainer.lua @@ -5,7 +5,7 @@ RightContainer aligns its content (1 widget) at the right of its own dimensions local BD = require("ui/bidi") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local RightContainer = WidgetContainer:new{ +local RightContainer = WidgetContainer:extend{ allow_mirroring = true, } diff --git a/frontend/ui/widget/container/scrollablecontainer.lua b/frontend/ui/widget/container/scrollablecontainer.lua index fcf7a668f..48e8230b7 100644 --- a/frontend/ui/widget/container/scrollablecontainer.lua +++ b/frontend/ui/widget/container/scrollablecontainer.lua @@ -24,7 +24,7 @@ local VerticalScrollBar = require("ui/widget/verticalscrollbar") local Screen = Device.screen local logger = require("logger") -local ScrollableContainer = InputContainer:new{ +local ScrollableContainer = InputContainer:extend{ -- Events to ignore (ie: ignore_events={"hold", "hold_release"}) ignore_events = nil, scroll_bar_width = Screen:scaleBySize(6), diff --git a/frontend/ui/widget/container/topcontainer.lua b/frontend/ui/widget/container/topcontainer.lua index ce5eab51c..b85b0d1bb 100644 --- a/frontend/ui/widget/container/topcontainer.lua +++ b/frontend/ui/widget/container/topcontainer.lua @@ -4,6 +4,6 @@ TopContainer contains its content (1 widget) at the top of its own dimensions local WidgetContainer = require("ui/widget/container/widgetcontainer") -local TopContainer = WidgetContainer:new() +local TopContainer = WidgetContainer:extend{} return TopContainer diff --git a/frontend/ui/widget/container/underlinecontainer.lua b/frontend/ui/widget/container/underlinecontainer.lua index 2b808783a..f5a938a32 100644 --- a/frontend/ui/widget/container/underlinecontainer.lua +++ b/frontend/ui/widget/container/underlinecontainer.lua @@ -9,7 +9,7 @@ local Geom = require("ui/geometry") local Size = require("ui/size") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local UnderlineContainer = WidgetContainer:new{ +local UnderlineContainer = WidgetContainer:extend{ linesize = Size.line.thick, padding = Size.padding.tiny, --- @todo shouldn't this default to black instead? diff --git a/frontend/ui/widget/container/widgetcontainer.lua b/frontend/ui/widget/container/widgetcontainer.lua index 5ab7b06fe..0a66d1594 100644 --- a/frontend/ui/widget/container/widgetcontainer.lua +++ b/frontend/ui/widget/container/widgetcontainer.lua @@ -15,28 +15,8 @@ It handles event propagation and painting (with different alignments) for its ch local Geom = require("ui/geometry") local Widget = require("ui/widget/widget") -local Device = require("device") -if Device.should_restrict_JIT then - jit.off(true, true) -end - -local WidgetContainer = Widget:new() - -function WidgetContainer:init() - if self.dimen then - if self.initDimen then - self:initDimen() - else - if not self.dimen.w then - self.dimen.w = self[1]:getSize().w - end - if not self.dimen.h then - self.dimen.h = self[1]:getSize().h - end - end - end -end +local WidgetContainer = Widget:extend{} function WidgetContainer:getSize() if self.dimen then @@ -46,7 +26,7 @@ function WidgetContainer:getSize() -- return size of first child widget return self[1]:getSize() else - return Geom:new{ w = 0, h = 0 } + return Geom:new{ x= 0, y = 0, w = 0, h = 0 } end end @@ -65,35 +45,42 @@ function WidgetContainer:clear(skip_free) end function WidgetContainer:paintTo(bb, x, y) - -- default to pass request to first child widget - if self[1] then - x = x + (self.dimen.x or 0) - y = y + (self.dimen.y or 0) - if self.align == "top" then - local contentSize = self[1]:getSize() - self[1]:paintTo(bb, - x + math.floor((self.dimen.w - contentSize.w)/2), y) - elseif self.align == "bottom" then - local contentSize = self[1]:getSize() - self[1]:paintTo(bb, - x + math.floor((self.dimen.w - contentSize.w)/2), - y + (self.dimen.h - contentSize.h)) - elseif self.align == "center" then - local contentSize = self[1]:getSize() - self[1]:paintTo(bb, - x + math.floor((self.dimen.w - contentSize.w)/2), - y + math.floor((self.dimen.h - contentSize.h)/2)) - else - return self[1]:paintTo(bb, x, y) - end + -- Forward painting duties to our first child widget + if self[1] == nil then + return + end + + if not self.dimen then + local content_size = self[1]:getSize() + self.dimen = Geom:new{x = 0, y = 0, w = content_size.w, h = content_size.h} + end + + x = x + (self.dimen.x or 0) + y = y + (self.dimen.y or 0) + if self.align == "top" then + local contentSize = self[1]:getSize() + self[1]:paintTo(bb, + x + math.floor((self.dimen.w - contentSize.w)/2), y) + elseif self.align == "bottom" then + local contentSize = self[1]:getSize() + self[1]:paintTo(bb, + x + math.floor((self.dimen.w - contentSize.w)/2), + y + (self.dimen.h - contentSize.h)) + elseif self.align == "center" then + local contentSize = self[1]:getSize() + self[1]:paintTo(bb, + x + math.floor((self.dimen.w - contentSize.w)/2), + y + math.floor((self.dimen.h - contentSize.h)/2)) + else + return self[1]:paintTo(bb, x, y) end end function WidgetContainer:propagateEvent(event) - -- propagate to children + -- Propagate to children for _, widget in ipairs(self) do if widget:handleEvent(event) then - -- stop propagating when an event handler returns true + -- Stop propagating when an event handler returns true return true end end diff --git a/frontend/ui/widget/dictquicklookup.lua b/frontend/ui/widget/dictquicklookup.lua index f025ec214..a3a3b3cf3 100644 --- a/frontend/ui/widget/dictquicklookup.lua +++ b/frontend/ui/widget/dictquicklookup.lua @@ -36,7 +36,7 @@ local time = require("ui/time") --[[ Display quick lookup word definition ]] -local DictQuickLookup = InputContainer:new{ +local DictQuickLookup = InputContainer:extend{ results = nil, lookupword = nil, dictionary = nil, diff --git a/frontend/ui/widget/doublespinwidget.lua b/frontend/ui/widget/doublespinwidget.lua index 0dc10412a..3554ca86a 100644 --- a/frontend/ui/widget/doublespinwidget.lua +++ b/frontend/ui/widget/doublespinwidget.lua @@ -20,7 +20,7 @@ local _ = require("gettext") local Screen = Device.screen local T = require("ffi/util").template -local DoubleSpinWidget = FocusManager:new{ +local DoubleSpinWidget = FocusManager:extend{ title_text = "", title_face = Font:getFace("x_smalltfont"), info_text = nil, diff --git a/frontend/ui/widget/eventlistener.lua b/frontend/ui/widget/eventlistener.lua index 2f7fc0d30..f4cb768a3 100644 --- a/frontend/ui/widget/eventlistener.lua +++ b/frontend/ui/widget/eventlistener.lua @@ -9,10 +9,15 @@ will call a method "onEventName" for an event with name local EventListener = {} -function EventListener:new(new_o) - local o = new_o or {} +function EventListener:extend(subclass_prototype) + local o = subclass_prototype or {} setmetatable(o, self) self.__index = self + return o +end + +function EventListener:new(o) + o = self:extend(o) if o.init then o:init() end return o end diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua index b71222adf..fce4d72ba 100644 --- a/frontend/ui/widget/filechooser.lua +++ b/frontend/ui/widget/filechooser.lua @@ -25,7 +25,7 @@ local FileChooser = Menu:extend{ file_filter = nil, -- function defined in the caller, returns true for files to be shown show_unsupported = false, -- set to true to ignore file_filter -- NOTE: Input is *always* a relative entry name - exclude_dirs = { + exclude_dirs = { -- const -- KOReader / Kindle "%.sdr$", -- Kobo @@ -54,7 +54,7 @@ local FileChooser = Menu:extend{ "^%.thumbnail%-previews$", "^%.reading%-states$", }, - exclude_files = { + exclude_files = { -- const -- Kobo "^BookReader%.sqlite", "^KoboReader%.sqlite", @@ -74,7 +74,7 @@ local FileChooser = Menu:extend{ }, collate = "strcoll", -- or collate = "access", reverse_collate = false, - path_items = {}, -- store last browsed location (item index) for each path + path_items = nil, -- hash, store last browsed location (item index) for each path goto_letter = true, } @@ -98,6 +98,7 @@ function FileChooser:show_file(filename) end function FileChooser:init() + self.path_items = {} self.width = Screen:getWidth() self.list = function(path, dirs, files, count_only) -- lfs.dir directory without permission will give error diff --git a/frontend/ui/widget/fixedtextwidget.lua b/frontend/ui/widget/fixedtextwidget.lua index b4ba9d0dd..8c6bc8ddb 100644 --- a/frontend/ui/widget/fixedtextwidget.lua +++ b/frontend/ui/widget/fixedtextwidget.lua @@ -4,7 +4,7 @@ local Geom = require("ui/geometry") --[[ FixedTextWidget --]] -local FixedTextWidget = TextWidget:new{} +local FixedTextWidget = TextWidget:extend{} function FixedTextWidget:updateSize() TextWidget.updateSize(self) diff --git a/frontend/ui/widget/focusmanager.lua b/frontend/ui/widget/focusmanager.lua index 48e856cd8..947a7dc6d 100644 --- a/frontend/ui/widget/focusmanager.lua +++ b/frontend/ui/widget/focusmanager.lua @@ -26,13 +26,17 @@ to not get stuck in an invalid position. but notice that this does _not_ do the layout for you, it rather defines an abstract layout. ]] -local FocusManager = InputContainer:new{ +local FocusManager = InputContainer:extend{ selected = nil, -- defaults to x=1, y=1 layout = nil, -- mandatory movement_allowed = { x = true, y = true }, } -function FocusManager:init() +-- Only build the default mappings once, we'll make copies during instantiation. +local KEY_EVENTS = {} +local BUILTIN_KEY_EVENTS = {} +local EXTRA_KEY_EVENTS = {} +do if Device:hasDPad() then local event_keys = {} -- these will all generate the same event, just with different arguments @@ -57,19 +61,16 @@ function FocusManager:init() table.insert(event_keys, {"FocusNext", { {"Tab"}, doc = "move focus to next widget", event="FocusNext"} }) table.insert(event_keys, {"FocusPrevious", { {"Shift", "Tab"}, doc = "move focus to previous widget", event="FocusPrevious"} }) - self.key_events = {} - self.builtin_key_events = {} - self.extra_key_events = {} for i = 1, FEW_KEYS_END_INDEX do local key_name = event_keys[i][1] - self.key_events[key_name] = event_keys[i][2] - self.builtin_key_events[key_name] = event_keys[i][2] + KEY_EVENTS[key_name] = event_keys[i][2] + BUILTIN_KEY_EVENTS[key_name] = event_keys[i][2] end if not Device:hasFewKeys() then for i = FEW_KEYS_END_INDEX+1, NORMAL_KEYS_END_INDEX do local key_name = event_keys[i][1] - self.key_events[key_name] = event_keys[i][2] - self.builtin_key_events[key_name] = event_keys[i][2] + KEY_EVENTS[key_name] = event_keys[i][2] + BUILTIN_KEY_EVENTS[key_name] = event_keys[i][2] end local focus_manager_setting = G_reader_settings:child("focus_manager") -- Enable advanced feature, like Hold, FocusNext, FocusPrevious @@ -83,8 +84,8 @@ function FocusManager:init() local handler_defition = util.tableDeepCopy(event_keys[i][2]) handler_defition[1] = alternative_keymap -- replace sample key combinations local new_event_key = "Alternative" .. key_name - self.key_events[new_event_key] = handler_defition - self.extra_key_events[new_event_key] = handler_defition + KEY_EVENTS[new_event_key] = handler_defition + EXTRA_KEY_EVENTS[new_event_key] = handler_defition end end end @@ -92,21 +93,21 @@ function FocusManager:init() end end - function FocusManager:_init() InputContainer._init(self) - -- Make sure each FocusManager instance has its own selection field. - -- Take ButtonTable = FocusManager:new{} for example. - -- FocusManager:init method called once and all ButtonTable instances share same selected field. - -- It has problem when - -- 1. ButtonTable A (layout 1 row, 4 columns) shown, and move focus, make selected to (4, 1) - -- 2. ButtonTable A closed and ButtonTable B (layout 2 rows, 2 columns) shown - -- 3. selected (4, 1) is invalid(overflow) for ButtonTable B, and FocusManager ignore all focus move events. + + -- These *need* to be instance-specific, hence the copy if not self.selected then self.selected = { x = 1, y = 1 } else self.selected = {x = self.selected.x, y = self.selected.y } end + + -- Ditto, as each widget may choose their own custom key bindings + self.key_events = util.tableDeepCopy(KEY_EVENTS) + -- We should be fine with a simple ref for those, though + self.builtin_key_events = BUILTIN_KEY_EVENTS + self.extra_key_events = EXTRA_KEY_EVENTS end function FocusManager:isAlternativeKey(key) diff --git a/frontend/ui/widget/footnotewidget.lua b/frontend/ui/widget/footnotewidget.lua index 488f83443..232e0e52d 100644 --- a/frontend/ui/widget/footnotewidget.lua +++ b/frontend/ui/widget/footnotewidget.lua @@ -112,7 +112,7 @@ body > section > title { -- body { background-color: #eeeeee; } -- Widget to display footnote HTML content -local FootnoteWidget = InputContainer:new{ +local FootnoteWidget = InputContainer:extend{ html = nil, css = nil, -- font_face can't really be overriden, it needs to be known by MuPDF @@ -121,7 +121,7 @@ local FootnoteWidget = InputContainer:new{ -- (already scaled) sizes in screen pixels doc_font_size = Screen:scaleBySize(18), doc_font_name = nil, - doc_margins = { + doc_margins = { -- const left = Screen:scaleBySize(20), right = Screen:scaleBySize(20), top = Screen:scaleBySize(10), diff --git a/frontend/ui/widget/frontlightwidget.lua b/frontend/ui/widget/frontlightwidget.lua index 45e6112cd..0e45a75da 100644 --- a/frontend/ui/widget/frontlightwidget.lua +++ b/frontend/ui/widget/frontlightwidget.lua @@ -25,7 +25,7 @@ local _ = require("gettext") local C_ = _.pgettext local Screen = Device.screen -local FrontLightWidget = FocusManager:new{ +local FrontLightWidget = FocusManager:extend{ name = "FrontLightWidget", width = nil, height = nil, diff --git a/frontend/ui/widget/horizontalgroup.lua b/frontend/ui/widget/horizontalgroup.lua index e15893ae1..079c21f8e 100644 --- a/frontend/ui/widget/horizontalgroup.lua +++ b/frontend/ui/widget/horizontalgroup.lua @@ -6,7 +6,7 @@ local BD = require("ui/bidi") local WidgetContainer = require("ui/widget/container/widgetcontainer") local util = require("util") -local HorizontalGroup = WidgetContainer:new{ +local HorizontalGroup = WidgetContainer:extend{ align = "center", allow_mirroring = true, _size = nil, diff --git a/frontend/ui/widget/horizontalscrollbar.lua b/frontend/ui/widget/horizontalscrollbar.lua index 6581cb9ce..e8cefdf48 100644 --- a/frontend/ui/widget/horizontalscrollbar.lua +++ b/frontend/ui/widget/horizontalscrollbar.lua @@ -7,7 +7,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local Size = require("ui/size") local Screen = require("device").screen -local HorizontalScrollBar = InputContainer:new{ +local HorizontalScrollBar = InputContainer:extend{ enable = true, low = 0, high = 1, diff --git a/frontend/ui/widget/horizontalspan.lua b/frontend/ui/widget/horizontalspan.lua index 2bb5cdd65..7d585b5bb 100644 --- a/frontend/ui/widget/horizontalspan.lua +++ b/frontend/ui/widget/horizontalspan.lua @@ -3,7 +3,7 @@ local Widget = require("ui/widget/widget") --[[ Dummy Widget that reserves horizontal space --]] -local HorizontalSpan = Widget:new{ +local HorizontalSpan = Widget:extend{ width = 0, } diff --git a/frontend/ui/widget/htmlboxwidget.lua b/frontend/ui/widget/htmlboxwidget.lua index 8b8113537..3477ef3d3 100644 --- a/frontend/ui/widget/htmlboxwidget.lua +++ b/frontend/ui/widget/htmlboxwidget.lua @@ -14,7 +14,7 @@ local logger = require("logger") local time = require("ui/time") local util = require("util") -local HtmlBoxWidget = InputContainer:new{ +local HtmlBoxWidget = InputContainer:extend{ bb = nil, dimen = nil, document = nil, diff --git a/frontend/ui/widget/iconbutton.lua b/frontend/ui/widget/iconbutton.lua index eb3ba133c..8b6957c44 100644 --- a/frontend/ui/widget/iconbutton.lua +++ b/frontend/ui/widget/iconbutton.lua @@ -15,7 +15,7 @@ local Screen = Device.screen local DGENERIC_ICON_SIZE = G_defaults:readSetting("DGENERIC_ICON_SIZE") -local IconButton = InputContainer:new{ +local IconButton = InputContainer:extend{ icon = "notice-warning", icon_rotation_angle = 0, dimen = nil, diff --git a/frontend/ui/widget/imageviewer.lua b/frontend/ui/widget/imageviewer.lua index 78a996bb1..2de6ef5f8 100644 --- a/frontend/ui/widget/imageviewer.lua +++ b/frontend/ui/widget/imageviewer.lua @@ -24,7 +24,7 @@ local logger = require("logger") local _ = require("gettext") local Screen = Device.screen -local ImageViewer = InputContainer:new{ +local ImageViewer = InputContainer:extend{ -- Allow for providing same different input types as ImageWidget : -- a path to a file file = nil, diff --git a/frontend/ui/widget/imagewidget.lua b/frontend/ui/widget/imagewidget.lua index e0f817f15..b80a2f598 100644 --- a/frontend/ui/widget/imagewidget.lua +++ b/frontend/ui/widget/imagewidget.lua @@ -48,7 +48,7 @@ local ImageCache = Cache:new{ enable_eviction_cb = false, } -local ImageWidget = Widget:new{ +local ImageWidget = Widget:extend{ -- Can be provided with a path to a file file = nil, -- or an already made BlitBuffer (ie: made by RenderImage) diff --git a/frontend/ui/widget/infomessage.lua b/frontend/ui/widget/infomessage.lua index e745e7add..e66e6c680 100644 --- a/frontend/ui/widget/infomessage.lua +++ b/frontend/ui/widget/infomessage.lua @@ -44,7 +44,7 @@ local _ = require("gettext") local Input = Device.input local Screen = Device.screen -local InfoMessage = InputContainer:new{ +local InfoMessage = InputContainer:extend{ modal = true, face = Font:getFace("infofont"), text = "", diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index 9b7b945d9..6d8963bef 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -120,7 +120,7 @@ local T = require("ffi/util").template local util = require("util") local _ = require("gettext") -local InputDialog = FocusManager:new{ +local InputDialog = FocusManager:extend{ is_always_active = true, title = "", input = "", diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index d7ef3d1ba..b37ddb23c 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -18,10 +18,10 @@ local util = require("util") local _ = require("gettext") local Screen = Device.screen -local Keyboard -local FocusManagerInstance = FocusManager:new{} +local Keyboard -- Conditional instantiation +local FocusManagerInstance -- Delayed instantiation -local InputText = InputContainer:new{ +local InputText = InputContainer:extend{ text = "", hint = "demo hint", input_type = nil, -- "number" or anything else @@ -576,8 +576,7 @@ function InputText:onKeyPress(key) if key["Backspace"] then self:delChar() elseif key["Del"] then - self:rightChar() - self:delChar() + self:delNextChar() elseif key["Left"] then self:leftChar() elseif key["Right"] then @@ -616,6 +615,9 @@ function InputText:onKeyPress(key) -- FocusManager may turn on alternative key maps. -- These key map maybe single text keys. -- It will cause unexpected focus move instead of enter text to InputText + if not FocusManagerInstance then + FocusManagerInstance = FocusManager:new{} + end local is_alternative_key = FocusManagerInstance:isAlternativeKey(key) if not is_alternative_key and Device:isSDL() then -- SDL already insert char via TextInput event @@ -814,6 +816,16 @@ function InputText:delChar() self:initTextBox(table.concat(self.charlist)) end +function InputText:delNextChar() + if self.readonly or not self:isTextEditable(true) then + return + end + if self.charpos > #self.charlist then return end + self.is_text_edited = true + table.remove(self.charlist, self.charpos) + self:initTextBox(table.concat(self.charlist)) +end + function InputText:delToStartOfLine() if self.readonly or not self:isTextEditable(true) then return @@ -862,11 +874,13 @@ function InputText:goToEndOfLine() end function InputText:goToHome() - self.text_widget:moveCursorToCharPos(1) + self.text_widget:moveCursorHome() + self.charpos, self.top_line_num = self.text_widget:getCharPos() end function InputText:goToEnd() - self.text_widget:moveCursorToCharPos(0) + self.text_widget:moveCursorEnd() + self.charpos, self.top_line_num = self.text_widget:getCharPos() end function InputText:moveCursorToCharPos(char_pos) diff --git a/frontend/ui/widget/keyboardlayoutdialog.lua b/frontend/ui/widget/keyboardlayoutdialog.lua index cf92c5d98..8368e7b24 100644 --- a/frontend/ui/widget/keyboardlayoutdialog.lua +++ b/frontend/ui/widget/keyboardlayoutdialog.lua @@ -23,7 +23,7 @@ local _ = require("gettext") local Device = require("device") local Screen = Device.screen -local KeyboardLayoutDialog = FocusManager:new{ +local KeyboardLayoutDialog = FocusManager:extend{ is_always_active = true, modal = true, stop_events_propagation = true, diff --git a/frontend/ui/widget/keyvaluepage.lua b/frontend/ui/widget/keyvaluepage.lua index abdbc2bbb..b76d00b4e 100644 --- a/frontend/ui/widget/keyvaluepage.lua +++ b/frontend/ui/widget/keyvaluepage.lua @@ -47,7 +47,7 @@ local Screen = Device.screen local T = require("ffi/util").template local _ = require("gettext") -local KeyValueItem = InputContainer:new{ +local KeyValueItem = InputContainer:extend{ key = nil, value = nil, value_lang = nil, @@ -66,7 +66,7 @@ local KeyValueItem = InputContainer:new{ } function KeyValueItem:init() - self.dimen = Geom:new{ w = self.width, h = self.height } + self.dimen = Geom:new{ x = 0, y = 0, w = self.width, h = self.height } -- self.value may contain some control characters (\n \t...) that would -- be rendered as a square. Replace them with a shorter and nicer '|'. @@ -273,7 +273,7 @@ function KeyValueItem:onShowKeyValue() end -local KeyValuePage = FocusManager:new{ +local KeyValuePage = FocusManager:extend{ title = "", width = nil, height = nil, @@ -288,6 +288,8 @@ local KeyValuePage = FocusManager:new{ function KeyValuePage:init() self.dimen = Geom:new{ + x = 0, + y = 0, w = self.width or Screen:getWidth(), h = self.height or Screen:getHeight(), } diff --git a/frontend/ui/widget/linewidget.lua b/frontend/ui/widget/linewidget.lua index d3110de19..b80942126 100644 --- a/frontend/ui/widget/linewidget.lua +++ b/frontend/ui/widget/linewidget.lua @@ -5,7 +5,7 @@ Widget that displays a line. local Blitbuffer = require("ffi/blitbuffer") local Widget = require("ui/widget/widget") -local LineWidget = Widget:new{ +local LineWidget = Widget:extend{ style = "solid", background = Blitbuffer.COLOR_BLACK, dimen = nil, diff --git a/frontend/ui/widget/linkbox.lua b/frontend/ui/widget/linkbox.lua index 1003621a9..d8e325778 100644 --- a/frontend/ui/widget/linkbox.lua +++ b/frontend/ui/widget/linkbox.lua @@ -7,7 +7,7 @@ local Size = require("ui/size") local UIManager = require("ui/uimanager") local Screen = Device.screen -local LinkBox = InputContainer:new{ +local LinkBox = InputContainer:extend{ box = nil, color = Blitbuffer.COLOR_DARK_GRAY, radius = 0, diff --git a/frontend/ui/widget/listview.lua b/frontend/ui/widget/listview.lua index 600ec3263..a97d13eb0 100644 --- a/frontend/ui/widget/listview.lua +++ b/frontend/ui/widget/listview.lua @@ -46,7 +46,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local Size = require("ui/size") local VerticalGroup = require("ui/widget/verticalgroup") -local ListView = InputContainer:new{ +local ListView = InputContainer:extend{ width = nil, height = nil, padding = nil, @@ -58,7 +58,7 @@ function ListView:init() if #self.items <= 0 then return end self.show_page = 1 - self.dimen = Geom:new{w = self.width, h = self.height} + self.dimen = Geom:new{x = 0, y = 0, w = self.width, h = self.height} if Device:isTouchDevice() then self.ges_events.Swipe = { diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua index 0943ccb52..7737dce3a 100644 --- a/frontend/ui/widget/menu.lua +++ b/frontend/ui/widget/menu.lua @@ -40,7 +40,7 @@ local T = FFIUtil.template --[[-- Widget that displays a shortcut icon for menu item. --]] -local ItemShortCutIcon = WidgetContainer:new{ +local ItemShortCutIcon = WidgetContainer:extend{ dimen = Geom:new{ w = Screen:scaleBySize(22), h = Screen:scaleBySize(22) }, key = nil, bordersize = Size.border.default, @@ -88,7 +88,7 @@ end --[[ Widget that displays an item for menu --]] -local MenuItem = InputContainer:new{ +local MenuItem = InputContainer:extend{ text = nil, bidi_wrap_func = nil, show_parent = nil, @@ -425,7 +425,6 @@ function MenuItem:init() end local _dots_cached_info - function MenuItem:getDotsText(face) local screen_w = Screen:getWidth() if not _dots_cached_info or _dots_cached_info.screen_width ~= screen_w @@ -565,7 +564,7 @@ end --[[ Widget that displays menu --]] -local Menu = FocusManager:new{ +local Menu = FocusManager:extend{ show_parent = nil, title = "No Title", @@ -576,7 +575,7 @@ local Menu = FocusManager:new{ header_padding = Size.padding.default, dimen = nil, item_table = nil, -- NOT mandatory (will be empty) - item_shortcuts = { + item_shortcuts = { -- const "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "A", "S", "D", "F", "G", "H", "J", "K", "L", "Del", "Z", "X", "C", "V", "B", "N", "M", ".", "Sym", @@ -643,7 +642,7 @@ function Menu:init() self.show_parent = self.show_parent or self self.item_table = self.item_table or {} self.item_table_stack = {} - self.dimen = Geom:new{ w = self.width, h = self.height or Screen:getHeight() } + self.dimen = Geom:new{ x = 0, y = 0, w = self.width, h = self.height or Screen:getHeight() } if self.dimen.h > Screen:getHeight() or self.dimen.h == nil then self.dimen.h = Screen:getHeight() end diff --git a/frontend/ui/widget/multiconfirmbox.lua b/frontend/ui/widget/multiconfirmbox.lua index 348d629b2..1ba6d2c53 100644 --- a/frontend/ui/widget/multiconfirmbox.lua +++ b/frontend/ui/widget/multiconfirmbox.lua @@ -37,7 +37,7 @@ local VerticalSpan = require("ui/widget/verticalspan") local _ = require("gettext") local Screen = require("device").screen -local MultiConfirmBox = InputContainer:new{ +local MultiConfirmBox = InputContainer:extend{ modal = true, text = _("no text"), face = Font:getFace("infofont"), diff --git a/frontend/ui/widget/multiinputdialog.lua b/frontend/ui/widget/multiinputdialog.lua index 2fb90de33..2fc917028 100644 --- a/frontend/ui/widget/multiinputdialog.lua +++ b/frontend/ui/widget/multiinputdialog.lua @@ -91,10 +91,9 @@ local VerticalSpan = require("ui/widget/verticalspan") local _ = require("gettext") local Screen = Device.screen -local input_field, input_description - local MultiInputDialog = InputDialog:extend{ - fields = {}, + fields = nil, -- array, mandatory + input_fields = nil, -- array description_padding = Size.padding.default, description_margin = Size.margin.small, bottom_v_padding = Size.padding.default, @@ -108,19 +107,17 @@ function MultiInputDialog:init() self.title_bar, } - input_field = {} - input_description = {} - local k = 0 + self.input_field = {} + local input_description = {} for i, field in ipairs(self.fields) do - k = k + 1 - input_field[k] = InputText:new{ + self.input_field[i] = InputText:new{ text = field.text or "", hint = field.hint or "", input_type = field.input_type or "string", text_type = field.text_type, face = self.input_face, width = math.floor(self.width * 0.9), - focused = k == 1 and true or false, + focused = i == 1 and true or false, scroll = false, parent = self, padding = field.padding or nil, @@ -133,9 +130,9 @@ function MultiInputDialog:init() auto_para_direction = field.auto_para_direction or self.auto_para_direction, alignment_strict = field.alignment_strict or self.alignment_strict, } - table.insert(self.layout, #self.layout, {input_field[k]}) + table.insert(self.layout, #self.layout, {self.input_field[i]}) if field.description then - input_description[k] = FrameContainer:new{ + input_description[i] = FrameContainer:new{ padding = self.description_padding, margin = self.description_margin, bordersize = 0, @@ -148,17 +145,17 @@ function MultiInputDialog:init() table.insert(VerticalGroupData, CenterContainer:new{ dimen = Geom:new{ w = self.title_bar:getSize().w, - h = input_description[k]:getSize().h , + h = input_description[i]:getSize().h , }, - input_description[k], + input_description[i], }) end table.insert(VerticalGroupData, CenterContainer:new{ dimen = Geom:new{ w = self.title_bar:getSize().w, - h = input_field[k]:getSize().h, + h = self.input_field[i]:getSize().h, }, - input_field[k], + self.input_field[i], }) end @@ -188,7 +185,7 @@ function MultiInputDialog:init() VerticalGroupData, } - self._input_widget = input_field[1] + self._input_widget = self.input_field[1] self[1] = CenterContainer:new{ dimen = Geom:new{ @@ -204,14 +201,20 @@ function MultiInputDialog:init() end +--- Returns an array of our input field's *text* field. function MultiInputDialog:getFields() local fields = {} - for i=1, #input_field do - table.insert(fields, input_field[i].text) + for i, field in ipairs(self.input_field) do + table.insert(fields, field.text) end return fields end +--- BEWARE: Live ref to an internal component! +function MultiInputDialog:getRawFields() + return self.input_field +end + function MultiInputDialog:onSwitchFocus(inputbox) -- unfocus current inputbox self._input_widget:unfocus() diff --git a/frontend/ui/widget/naturallightwidget.lua b/frontend/ui/widget/naturallightwidget.lua index e6f7d38b8..c90272727 100644 --- a/frontend/ui/widget/naturallightwidget.lua +++ b/frontend/ui/widget/naturallightwidget.lua @@ -7,7 +7,6 @@ local FrameContainer = require("ui/widget/container/framecontainer") local Geom = require("ui/geometry") local HorizontalGroup = require("ui/widget/horizontalgroup") local HorizontalSpan = require("ui/widget/horizontalspan") -local InputContainer = require("ui/widget/container/inputcontainer") local InputText = require("ui/widget/inputtext") local Size = require("ui/size") local TextBoxWidget = require("ui/widget/textboxwidget") @@ -19,7 +18,7 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") local Screen = Device.screen -local NaturalLightWidget = InputContainer:new{ +local NaturalLightWidget = WidgetContainer:extend{ is_always_active = true, width = nil, height = nil, @@ -176,7 +175,7 @@ function NaturalLightWidget:update() } self[1] = WidgetContainer:new{ align = "top", - dimen =Geom:new{ + dimen = Geom:new{ x = 0, y = 0, w = self.screen_width, h = self.screen_height, diff --git a/frontend/ui/widget/networksetting.lua b/frontend/ui/widget/networksetting.lua index 3d7202c9a..27afe9810 100644 --- a/frontend/ui/widget/networksetting.lua +++ b/frontend/ui/widget/networksetting.lua @@ -74,7 +74,7 @@ local function obtainIP() end -local MinimalPaginator = Widget:new{ +local MinimalPaginator = Widget:extend{ width = nil, height = nil, progress = nil, @@ -100,7 +100,7 @@ end function MinimalPaginator:setProgress(progress) self.progress = progress end -local NetworkItem = InputContainer:new{ +local NetworkItem = InputContainer:extend{ dimen = nil, height = Screen:scaleBySize(44), icon_size = Screen:scaleBySize(32), @@ -110,7 +110,7 @@ local NetworkItem = InputContainer:new{ } function NetworkItem:init() - self.dimen = Geom:new{w = self.width, h = self.height} + self.dimen = Geom:new{x = 0, y = 0, w = self.width, h = self.height} if not self.info.ssid then self.info.ssid = "[hidden]" end @@ -384,7 +384,7 @@ function NetworkItem:onTapSelect(arg, ges_ev) end -local NetworkSetting = InputContainer:new{ +local NetworkSetting = InputContainer:extend{ width = nil, height = nil, -- sample network_list entry: { diff --git a/frontend/ui/widget/notification.lua b/frontend/ui/widget/notification.lua index 0bc45da02..5c664e923 100644 --- a/frontend/ui/widget/notification.lua +++ b/frontend/ui/widget/notification.lua @@ -39,7 +39,7 @@ local SOURCE_SOME = SOURCE_BOTTOM_MENU_FINE + SOURCE_DISPATCHER local SOURCE_DEFAULT = SOURCE_SOME + SOURCE_BOTTOM_MENU_MORE + SOURCE_BOTTOM_MENU_PROGRESS local SOURCE_ALL = SOURCE_BOTTOM_MENU + SOURCE_DISPATCHER + SOURCE_OTHER -local Notification = InputContainer:new{ +local Notification = InputContainer:extend{ face = Font:getFace("x_smallinfofont"), text = "Null Message", margin = Size.margin.default, @@ -47,7 +47,7 @@ local Notification = InputContainer:new{ timeout = 2, -- default to 2 seconds toast = true, -- closed on any event, and let the event propagate to next top widget - _nums_shown = {}, -- array of stacked notifications + _nums_shown = {}, -- actual static class member, array of stacked notifications SOURCE_BOTTOM_MENU_ICON = SOURCE_BOTTOM_MENU_ICON, SOURCE_BOTTOM_MENU_TOGGLE = SOURCE_BOTTOM_MENU_TOGGLE, diff --git a/frontend/ui/widget/overlapgroup.lua b/frontend/ui/widget/overlapgroup.lua index f596c65a3..e3cbd477a 100644 --- a/frontend/ui/widget/overlapgroup.lua +++ b/frontend/ui/widget/overlapgroup.lua @@ -3,9 +3,10 @@ A layout widget that puts objects above each other. --]] local BD = require("ui/bidi") +local Geom = require("ui/geometry") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local OverlapGroup = WidgetContainer:new{ +local OverlapGroup = WidgetContainer:extend{ -- Note: we default to allow_mirroring = true. -- When using LeftContainer, RightContainer or HorizontalGroup -- in an OverlapGroup, mostly when they take the whole width, @@ -36,19 +37,22 @@ function OverlapGroup:getSize() return self._size end -function OverlapGroup:initDimen() +-- NOTE: OverlapGroup is one of those special snowflakes that will compute self.dimen at init, +-- instead of at paintTo... +function OverlapGroup:init() self:getSize() -- populate self._size -- sync self._size with self.dimen, self.dimen has higher priority - if self.dimen.w then - self._size.w = self.dimen.w - else - self.dimen.w = self._size.w - end - if self.dimen.h then - self._size.h = self.dimen.h - else - self.dimen.h = self._size.h + if self.dimen then + -- Jump through some extra hoops because this may not be a Geom... + if self.dimen.w then + self._size.w = self.dimen.w + end + if self.dimen.h then + self._size.h = self.dimen.h + end end + -- Regardless of what was passed to the constructor, make sure dimen is actually a Geom + self.dimen = Geom:new{x = 0, y = 0, w = self._size.w, h = self._size.h} end function OverlapGroup:paintTo(bb, x, y) diff --git a/frontend/ui/widget/pagebrowserwidget.lua b/frontend/ui/widget/pagebrowserwidget.lua index 0c1696d1e..bc7bae200 100644 --- a/frontend/ui/widget/pagebrowserwidget.lua +++ b/frontend/ui/widget/pagebrowserwidget.lua @@ -28,7 +28,7 @@ local BookMapWidget = require("ui/widget/bookmapwidget") local BookMapRow = BookMapWidget.BookMapRow -- PageBrowserWidget: shows thumbnails of pages -local PageBrowserWidget = InputContainer:new{ +local PageBrowserWidget = InputContainer:extend{ title = _("Page browser"), -- Focus page: will be put at the best place in the thumbnail grid -- (that is, the grid will pick thumbnails from pages before and diff --git a/frontend/ui/widget/physicalkeyboard.lua b/frontend/ui/widget/physicalkeyboard.lua index a9b1459d7..7a38f535c 100644 --- a/frontend/ui/widget/physicalkeyboard.lua +++ b/frontend/ui/widget/physicalkeyboard.lua @@ -17,7 +17,7 @@ local logger = require("logger") local util = require("util") local Screen = Device.screen -local PhysicalNumericKey = WidgetContainer:new{ +local PhysicalNumericKey = WidgetContainer:extend{ key = nil, label = nil, physical_key_label = nil, @@ -60,6 +60,8 @@ function PhysicalNumericKey:init() }, } self.dimen = Geom:new{ + x = 0, + y = 0, w = self.width, h = self.height, } @@ -67,7 +69,7 @@ end -- start of PhysicalKeyboard -local PhysicalKeyboard = InputContainer:new{ +local PhysicalKeyboard = InputContainer:extend{ is_always_active = true, inputbox = nil, -- expect ui/widget/inputtext instance bordersize = Size.border.button, @@ -85,7 +87,7 @@ function PhysicalKeyboard:init() KeyPress = { { all_keys }, } } - self.dimen = Geom:new{ w = 0, h = 0 } + self.dimen = Geom:new{ x = 0, y = 0, w = 0, h = 0 } self:setType(self.inputbox.input_type) end diff --git a/frontend/ui/widget/progresswidget.lua b/frontend/ui/widget/progresswidget.lua index 88f2bda2b..555e0eff1 100644 --- a/frontend/ui/widget/progresswidget.lua +++ b/frontend/ui/widget/progresswidget.lua @@ -34,7 +34,7 @@ local Geom = require("ui/geometry") local Widget = require("ui/widget/widget") local Screen = require("device").screen -local ProgressWidget = Widget:new{ +local ProgressWidget = Widget:extend{ width = nil, height = nil, margin_h = Screen:scaleBySize(3), diff --git a/frontend/ui/widget/qrmessage.lua b/frontend/ui/widget/qrmessage.lua index 684bbb2aa..220e63157 100644 --- a/frontend/ui/widget/qrmessage.lua +++ b/frontend/ui/widget/qrmessage.lua @@ -30,7 +30,7 @@ local Input = Device.input local Screen = Device.screen local Size = require("ui/size") -local QRMessage = InputContainer:new{ +local QRMessage = InputContainer:extend{ modal = true, timeout = nil, -- in seconds text = nil, -- The text to encode. diff --git a/frontend/ui/widget/radiobutton.lua b/frontend/ui/widget/radiobutton.lua index 350ad7b30..86ede7829 100644 --- a/frontend/ui/widget/radiobutton.lua +++ b/frontend/ui/widget/radiobutton.lua @@ -27,7 +27,7 @@ local TextBoxWidget = require("ui/widget/textboxwidget") local TextWidget = require("ui/widget/textwidget") local UIManager = require("ui/uimanager") -local RadioButton = InputContainer:new{ +local RadioButton = InputContainer:extend{ checkable = true, checked = false, enabled = true, diff --git a/frontend/ui/widget/radiobuttontable.lua b/frontend/ui/widget/radiobuttontable.lua index a4d1bad65..a64d0bcc1 100644 --- a/frontend/ui/widget/radiobuttontable.lua +++ b/frontend/ui/widget/radiobuttontable.lua @@ -12,7 +12,7 @@ local VerticalSpan = require("ui/widget/verticalspan") local dbg = require("dbg") local Screen = Device.screen -local RadioButtonTable = FocusManager:new{ +local RadioButtonTable = FocusManager:extend{ width = Screen:getWidth(), radio_buttons = { { diff --git a/frontend/ui/widget/radiobuttonwidget.lua b/frontend/ui/widget/radiobuttonwidget.lua index 13fbaf0af..18be0d673 100644 --- a/frontend/ui/widget/radiobuttonwidget.lua +++ b/frontend/ui/widget/radiobuttonwidget.lua @@ -17,7 +17,7 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") local Screen = Device.screen -local RadioButtonWidget = FocusManager:new{ +local RadioButtonWidget = FocusManager:extend{ title_text = "", info_text = nil, width = nil, diff --git a/frontend/ui/widget/radiomark.lua b/frontend/ui/widget/radiomark.lua index e99d4179c..08586f123 100644 --- a/frontend/ui/widget/radiomark.lua +++ b/frontend/ui/widget/radiomark.lua @@ -1,10 +1,10 @@ local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Font = require("ui/font") -local InputContainer = require("ui/widget/container/inputcontainer") local TextWidget = require("ui/widget/textwidget") +local WidgetContainer = require("ui/widget/container/widgetcontainer") -local RadioMark = InputContainer:new{ +local RadioMark = WidgetContainer:extend{ checkable = true, -- empty space when false checked = false, enabled = true, diff --git a/frontend/ui/widget/rectspan.lua b/frontend/ui/widget/rectspan.lua index 9bc1d4dff..da588879b 100644 --- a/frontend/ui/widget/rectspan.lua +++ b/frontend/ui/widget/rectspan.lua @@ -3,7 +3,7 @@ local Widget = require("ui/widget/widget") --[[ Dummy Widget that reserves vertical and horizontal space ]] -local RectSpan = Widget:new{ +local RectSpan = Widget:extend{ width = 0, hright = 0, } diff --git a/frontend/ui/widget/screensaverwidget.lua b/frontend/ui/widget/screensaverwidget.lua index 36f4b2eac..408770764 100644 --- a/frontend/ui/widget/screensaverwidget.lua +++ b/frontend/ui/widget/screensaverwidget.lua @@ -10,7 +10,7 @@ local util = require("util") local _ = require("gettext") local Screen = Device.screen -local ScreenSaverWidget = InputContainer:new{ +local ScreenSaverWidget = InputContainer:extend{ name = "ScreenSaver", widget = nil, background = nil, diff --git a/frontend/ui/widget/screenshoter.lua b/frontend/ui/widget/screenshoter.lua index 1c89d7445..da59238e9 100644 --- a/frontend/ui/widget/screenshoter.lua +++ b/frontend/ui/widget/screenshoter.lua @@ -9,7 +9,7 @@ local Screen = require("device").screen local T = require("ffi/util").template local _ = require("gettext") -local Screenshoter = InputContainer:new{ +local Screenshoter = InputContainer:extend{ prefix = 'Screenshot', } diff --git a/frontend/ui/widget/scrollhtmlwidget.lua b/frontend/ui/widget/scrollhtmlwidget.lua index a43144b77..b63539d08 100644 --- a/frontend/ui/widget/scrollhtmlwidget.lua +++ b/frontend/ui/widget/scrollhtmlwidget.lua @@ -15,7 +15,7 @@ local VerticalScrollBar = require("ui/widget/verticalscrollbar") local Input = Device.input local Screen = Device.screen -local ScrollHtmlWidget = InputContainer:new{ +local ScrollHtmlWidget = InputContainer:extend{ html_body = nil, css = nil, default_font_size = Screen:scaleBySize(24), -- same as infofont diff --git a/frontend/ui/widget/scrolltextwidget.lua b/frontend/ui/widget/scrolltextwidget.lua index 578d9f39a..6480a5953 100644 --- a/frontend/ui/widget/scrolltextwidget.lua +++ b/frontend/ui/widget/scrolltextwidget.lua @@ -17,7 +17,7 @@ local UIManager = require("ui/uimanager") local Input = Device.input local Screen = Device.screen -local ScrollTextWidget = InputContainer:new{ +local ScrollTextWidget = InputContainer:extend{ text = nil, charlist = nil, charpos = nil, @@ -233,6 +233,16 @@ function ScrollTextWidget:moveCursorDown() self:updateScrollBar() end +function ScrollTextWidget:moveCursorHome() + self.text_widget:moveCursorHome() + self:updateScrollBar() +end + +function ScrollTextWidget:moveCursorEnd() + self.text_widget:moveCursorEnd() + self:updateScrollBar() +end + function ScrollTextWidget:scrollDown() self.text_widget:scrollDown() self:updateScrollBar(true) diff --git a/frontend/ui/widget/skimtowidget.lua b/frontend/ui/widget/skimtowidget.lua index f928b94ee..f11f001d1 100644 --- a/frontend/ui/widget/skimtowidget.lua +++ b/frontend/ui/widget/skimtowidget.lua @@ -20,7 +20,7 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") local Screen = Device.screen -local SkimToWidget = FocusManager:new{} +local SkimToWidget = FocusManager:extend{} function SkimToWidget:init() local screen_width = Screen:getWidth() diff --git a/frontend/ui/widget/sortwidget.lua b/frontend/ui/widget/sortwidget.lua index 42fea682a..4148597e2 100644 --- a/frontend/ui/widget/sortwidget.lua +++ b/frontend/ui/widget/sortwidget.lua @@ -26,7 +26,7 @@ local util = require("util") local T = require("ffi/util").template local _ = require("gettext") -local SortItemWidget = InputContainer:new{ +local SortItemWidget = InputContainer:extend{ item = nil, face = Font:getFace("smallinfofont"), width = nil, @@ -34,7 +34,7 @@ local SortItemWidget = InputContainer:new{ } function SortItemWidget:init() - self.dimen = Geom:new{w = self.width, h = self.height} + self.dimen = Geom:new{x = 0, y = 0, w = self.width, h = self.height} self.ges_events.Tap = { GestureRange:new{ ges = "tap", @@ -116,7 +116,7 @@ function SortItemWidget:onHold() return true end -local SortWidget = FocusManager:new{ +local SortWidget = FocusManager:extend{ title = "", width = nil, height = nil, @@ -135,6 +135,8 @@ function SortWidget:init() self.orig_item_table = nil self.dimen = Geom:new{ + x = 0, + y = 0, w = self.width or Screen:getWidth(), h = self.height or Screen:getHeight(), } diff --git a/frontend/ui/widget/spinwidget.lua b/frontend/ui/widget/spinwidget.lua index d24af61aa..fbf3a10f7 100644 --- a/frontend/ui/widget/spinwidget.lua +++ b/frontend/ui/widget/spinwidget.lua @@ -18,7 +18,7 @@ local _ = require("gettext") local Screen = Device.screen local T = require("ffi/util").template -local SpinWidget = FocusManager:new{ +local SpinWidget = FocusManager:extend{ title_text = "", info_text = nil, width = nil, diff --git a/frontend/ui/widget/textboxwidget.lua b/frontend/ui/widget/textboxwidget.lua index 1cdce2110..7795df2cd 100644 --- a/frontend/ui/widget/textboxwidget.lua +++ b/frontend/ui/widget/textboxwidget.lua @@ -33,7 +33,7 @@ local util = require("util") local xtext -- Delayed (and optional) loading local Screen = require("device").screen -local TextBoxWidget = InputContainer:new{ +local TextBoxWidget = InputContainer:extend{ text = nil, editable = false, -- Editable flag for whether drawing the cursor or not. justified = false, -- Should text be justified (spaces widened to fill width) @@ -59,6 +59,7 @@ local TextBoxWidget = InputContainer:new{ idx_pad = nil, -- idx => pad for char at idx, if non zero vertical_string_list = nil, virtual_line_num = 1, -- index of the top displayed line + current_line_num = 1, -- index of the currently edited line (i.e., where our cursor is) line_height_px = nil, -- height of a line in px lines_per_page = nil, -- number of visible lines text_height = nil, -- adjusted height to visible text (lines_per_page*line_height_px) @@ -1107,8 +1108,8 @@ function TextBoxWidget:getFontSizeToFitHeight(height_px, nb_lines, line_height_e end function TextBoxWidget:getCharPos() - -- returns virtual_line_num too - return self.charpos, self.virtual_line_num + -- returns virtual_line_num & current_line_num too + return self.charpos, self.virtual_line_num, self.current_line_num end function TextBoxWidget:getSize() @@ -1570,7 +1571,8 @@ local CURSOR_USE_REFRESH_FUNCS = G_reader_settings:nilOrTrue("ui_cursor_use_refr function TextBoxWidget:moveCursorToCharPos(charpos) self.charpos = charpos self.prev_virtual_line_num = self.virtual_line_num - local x, y = self:_getXYForCharPos() -- we can get y outside current view + local x, y, screen_line_num = self:_getXYForCharPos() -- we can get y outside current view + self.current_line_num = screen_line_num -- adjust self.virtual_line_num for overflowed y to have y in current view if y < 0 then local scroll_lines = math.ceil( -y / self.line_height_px ) @@ -1811,6 +1813,14 @@ function TextBoxWidget:moveCursorDown() self:moveCursorToXY(x, y + self.line_height_px) end +function TextBoxWidget:moveCursorHome() + self:moveCursorToCharPos(self.vertical_string_list[self.current_line_num].offset) +end + +function TextBoxWidget:moveCursorEnd() + self:moveCursorToCharPos(self.vertical_string_list[self.current_line_num+1] and self.vertical_string_list[self.current_line_num+1].offset - 1 or #self.charlist + 1) +end + --- Text selection with Hold diff --git a/frontend/ui/widget/textviewer.lua b/frontend/ui/widget/textviewer.lua index bd5875760..4c8e8af43 100644 --- a/frontend/ui/widget/textviewer.lua +++ b/frontend/ui/widget/textviewer.lua @@ -33,7 +33,7 @@ local util = require("util") local _ = require("gettext") local Screen = Device.screen -local TextViewer = InputContainer:new{ +local TextViewer = InputContainer:extend{ title = nil, text = nil, width = nil, diff --git a/frontend/ui/widget/textwidget.lua b/frontend/ui/widget/textwidget.lua index 05efbe0c1..f8c8667ec 100644 --- a/frontend/ui/widget/textwidget.lua +++ b/frontend/ui/widget/textwidget.lua @@ -24,7 +24,7 @@ local dbg = require("dbg") local util = require("util") local xtext -- Delayed (and optional) loading -local TextWidget = Widget:new{ +local TextWidget = Widget:extend{ text = nil, face = nil, bold = false, -- use bold=true to use a real bold font (or synthetized if not available), diff --git a/frontend/ui/widget/titlebar.lua b/frontend/ui/widget/titlebar.lua index ed5786583..35add8092 100644 --- a/frontend/ui/widget/titlebar.lua +++ b/frontend/ui/widget/titlebar.lua @@ -340,6 +340,8 @@ function TitleBar:init() end self.dimen = Geom:new{ + x = 0, + y = 0, w = self.width, h = self.titlebar_height, -- buttons can overflow this } @@ -379,8 +381,7 @@ function TitleBar:init() table.insert(self, self.right_button) end - -- We :extend() OverlapGroup and did not :new() it, so we can - -- :init() it now, after we have added all the subelements. + -- Call our base class's init (especially since OverlapGroup has very peculiar self.dimen semantics...) OverlapGroup.init(self) end diff --git a/frontend/ui/widget/toggleswitch.lua b/frontend/ui/widget/toggleswitch.lua index 15d7f6d72..550690463 100644 --- a/frontend/ui/widget/toggleswitch.lua +++ b/frontend/ui/widget/toggleswitch.lua @@ -23,13 +23,13 @@ local VerticalGroup = require("ui/widget/verticalgroup") local _ = require("gettext") local Screen = Device.screen -local ToggleLabel = TextWidget:new{ +local ToggleLabel = TextWidget:extend{ bold = true, bgcolor = Blitbuffer.COLOR_WHITE, fgcolor = Blitbuffer.COLOR_BLACK, } -local ToggleSwitch = FocusManager:new{ +local ToggleSwitch = FocusManager:extend{ width = Screen:scaleBySize(216), height = Size.item.height_default, bgcolor = Blitbuffer.COLOR_WHITE, -- unfocused item color diff --git a/frontend/ui/widget/touchmenu.lua b/frontend/ui/widget/touchmenu.lua index 7c9436213..4b554722d 100644 --- a/frontend/ui/widget/touchmenu.lua +++ b/frontend/ui/widget/touchmenu.lua @@ -39,7 +39,7 @@ local DGENERIC_ICON_SIZE = G_defaults:readSetting("DGENERIC_ICON_SIZE") --[[ TouchMenuItem widget --]] -local TouchMenuItem = InputContainer:new{ +local TouchMenuItem = InputContainer:extend{ menu = nil, vertical_align = "center", item = nil, @@ -267,9 +267,9 @@ end --[[ TouchMenuBar widget --]] -local TouchMenuBar = InputContainer:new{ +local TouchMenuBar = InputContainer:extend{ width = Screen:getWidth(), - icons = {}, + icons = nil, -- array, mandatory -- touch menu that holds the bar, used for trigger repaint on icons show_parent = nil, menu = nil, @@ -423,7 +423,7 @@ function TouchMenuBar:init() self.bar_sep }, } - self.dimen = Geom:new{ w = self.width, h = self.height } + self.dimen = Geom:new{ x = 0, y = 0, w = self.width, h = self.height } end function TouchMenuBar:switchToTab(index) @@ -443,7 +443,7 @@ end --[[ TouchMenu widget for hierarchical menus --]] -local TouchMenu = FocusManager:new{ +local TouchMenu = FocusManager:extend{ tab_item_table = nil, -- mandatory -- for returning in multi-level menus item_table_stack = nil, diff --git a/frontend/ui/widget/trapwidget.lua b/frontend/ui/widget/trapwidget.lua index b33d14b98..fa590078a 100644 --- a/frontend/ui/widget/trapwidget.lua +++ b/frontend/ui/widget/trapwidget.lua @@ -25,7 +25,7 @@ local UIManager = require("ui/uimanager") local Input = Device.input local Screen = Device.screen -local TrapWidget = InputContainer:new{ +local TrapWidget = InputContainer:extend{ modal = true, dismiss_callback = function() end, text = nil, -- will be invisible if no message given diff --git a/frontend/ui/widget/verticalgroup.lua b/frontend/ui/widget/verticalgroup.lua index 9e4ca516d..1de2e722f 100644 --- a/frontend/ui/widget/verticalgroup.lua +++ b/frontend/ui/widget/verticalgroup.lua @@ -5,7 +5,7 @@ A layout widget that puts objects under each other. local BD = require("ui/bidi") local WidgetContainer = require("ui/widget/container/widgetcontainer") -local VerticalGroup = WidgetContainer:new{ +local VerticalGroup = WidgetContainer:extend{ align = "center", allow_mirroring = true, _size = nil, diff --git a/frontend/ui/widget/verticalscrollbar.lua b/frontend/ui/widget/verticalscrollbar.lua index 5ac76eabb..57048cd3e 100644 --- a/frontend/ui/widget/verticalscrollbar.lua +++ b/frontend/ui/widget/verticalscrollbar.lua @@ -6,7 +6,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local Size = require("ui/size") local Screen = require("device").screen -local VerticalScrollBar = InputContainer:new{ +local VerticalScrollBar = InputContainer:extend{ enable = true, low = 0, high = 1, diff --git a/frontend/ui/widget/verticalspan.lua b/frontend/ui/widget/verticalspan.lua index db2f16302..d5b261db4 100644 --- a/frontend/ui/widget/verticalspan.lua +++ b/frontend/ui/widget/verticalspan.lua @@ -3,7 +3,7 @@ local Widget = require("ui/widget/widget") --[[ Dummy Widget that reserves vertical space --]] -local VerticalSpan = Widget:new{ +local VerticalSpan = Widget:extend{ width = 0, } diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 049ac1395..6b8ba32db 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -31,7 +31,7 @@ local DEFAULT_LABEL_SIZE = 22 local VirtualKeyPopup -local VirtualKey = InputContainer:new{ +local VirtualKey = InputContainer:extend{ key = nil, icon = nil, label = nil, @@ -456,11 +456,11 @@ function VirtualKey:invert(invert, hold) self:update_keyboard(hold, true) end -VirtualKeyPopup = FocusManager:new{ +VirtualKeyPopup = FocusManager:extend{ modal = true, disable_double_tap = true, inputbox = nil, - layout = {}, + layout = nil, -- array } function VirtualKeyPopup:onTapClose(arg, ges) @@ -489,6 +489,7 @@ function VirtualKeyPopup:init() local key_char_orig = key_chars[1] local key_char_orig_func = parent_key.callback + self.layout = {} local rows = { extra_key_chars = { key_chars[2], @@ -726,21 +727,21 @@ function VirtualKeyPopup:init() end) end -local VirtualKeyboard = FocusManager:new{ +local VirtualKeyboard = FocusManager:extend{ name = "VirtualKeyboard", modal = true, disable_double_tap = true, inputbox = nil, - KEYS = {}, -- table to store layouts - shiftmode_keys = {}, - symbolmode_keys = {}, - utf8mode_keys = {}, - umlautmode_keys = {}, + KEYS = nil, -- table to store layouts + shiftmode_keys = nil, -- table + symbolmode_keys = nil, -- table + utf8mode_keys = nil, -- table + umlautmode_keys = nil, -- table keyboard_layer = 2, shiftmode = false, symbolmode = false, umlautmode = false, - layout = {}, + layout = nil, -- array height = nil, default_label_size = DEFAULT_LABEL_SIZE, @@ -784,11 +785,11 @@ function VirtualKeyboard:init() local lang = self:getKeyboardLayout() local keyboard_layout = self.lang_to_keyboard_layout[lang] or self.lang_to_keyboard_layout["en"] local keyboard = require("ui/data/keyboardlayouts/" .. keyboard_layout) - self.KEYS = keyboard.keys - self.shiftmode_keys = keyboard.shiftmode_keys - self.symbolmode_keys = keyboard.symbolmode_keys - self.utf8mode_keys = keyboard.utf8mode_keys - self.umlautmode_keys = keyboard.umlautmode_keys + self.KEYS = keyboard.keys or {} + self.shiftmode_keys = keyboard.shiftmode_keys or {} + self.symbolmode_keys = keyboard.symbolmode_keys or {} + self.utf8mode_keys = keyboard.utf8mode_keys or {} + self.umlautmode_keys = keyboard.umlautmode_keys or {} self.width = Screen:getWidth() local keys_height = G_reader_settings:isTrue("keyboard_key_compact") and 48 or 64 self.height = Screen:scaleBySize(keys_height * #self.KEYS) diff --git a/frontend/ui/widget/widget.lua b/frontend/ui/widget/widget.lua index dde29d80d..8dd4082b1 100644 --- a/frontend/ui/widget/widget.lua +++ b/frontend/ui/widget/widget.lua @@ -14,44 +14,42 @@ local EventListener = require("ui/widget/eventlistener") --- Widget base class -- @table Widget -local Widget = EventListener:new() +local Widget = EventListener:extend{} --[[-- -Use this method to define a subclass widget class that's inherited from a -base class widget. It only setups the metabale (or prototype chain) and will -not initiate a real instance, i.e. call self:init(). +Use this method to define a widget subclass that's inherited from a base class widget. +It only setups the metatable (or prototype chain) and will not initiate a real instance, i.e. call self:init(). -@tparam Widget baseclass +@tparam table subclass @treturn Widget ]] -function Widget:extend(baseclass) - local o = baseclass or {} +function Widget:extend(subclass_prototype) + local o = subclass_prototype or {} setmetatable(o, self) self.__index = self return o end --[[-- -Use this method to initiatie a instance of a class, don't use it for class -definition because it also calls self:init(). +Use this method to initiate an instance of a class. +Do NOT use it for class definitions because it also calls self:init(). -@tparam Widget o +@tparam table o @treturn Widget ]] function Widget:new(o) o = self:extend(o) - -- Both o._init and o.init are called on object creation. But o._init is - -- used for base widget initialization (basic component used to build other - -- widgets). While o.init is for higher level widgets, for example Menu - -- Widget + -- Both o._init and o.init are called on object creation. + -- But o._init is used for base widget initialization (basic components used to build other widgets). + -- While o.init is for higher level widgets, for example Menu. if o._init then o:_init() end if o.init then o:init() end return o end --[[ -FIXME: enable this doc section when we verified all self.dimen is a Geom so we -can return self.dime:copy(). +FIXME: Enable this doc section once we've verified all self.dimen are Geom objects + so we can return self.dimen:copy() instead of a live ref. Return size of the widget. @@ -64,8 +62,8 @@ end --[[-- Paint widget to a BlitBuffer. -@tparam BlitBuffer bb BlitBuffer to paint to. If it's the screen BlitBuffer, then -widget will show up on screen refresh. +@tparam BlitBuffer bb 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 ]] diff --git a/plugins/SSH.koplugin/main.lua b/plugins/SSH.koplugin/main.lua index 6bb5130aa..0d31b8b0b 100644 --- a/plugins/SSH.koplugin/main.lua +++ b/plugins/SSH.koplugin/main.lua @@ -21,7 +21,7 @@ if not util.pathExists("dropbear") then return { disabled = true, } end -local SSH = WidgetContainer:new{ +local SSH = WidgetContainer:extend{ name = "SSH", is_doc_only = false, } diff --git a/plugins/autodim.koplugin/main.lua b/plugins/autodim.koplugin/main.lua index b831e187f..17f4944b6 100644 --- a/plugins/autodim.koplugin/main.lua +++ b/plugins/autodim.koplugin/main.lua @@ -23,7 +23,9 @@ local DEFAULT_AUTODIM_DURATION_S = 5 local DEFAULT_AUTODIM_FRACTION = 20 local AUTODIM_EVENT_FREQUENCY = 2 -- in Hz; Frequenzy for FrontlightChangedEvent on E-Ink devices -local AutoDim = WidgetContainer:new{ name = "autodim" } +local AutoDim = WidgetContainer:extend{ + name = "autodim", +} function AutoDim:init() self.autodim_starttime_m = G_reader_settings:readSetting("autodim_starttime_minutes", -1) diff --git a/plugins/autofrontlight.koplugin/main.lua b/plugins/autofrontlight.koplugin/main.lua index 627566f1e..73770d8a2 100644 --- a/plugins/autofrontlight.koplugin/main.lua +++ b/plugins/autofrontlight.koplugin/main.lua @@ -92,7 +92,7 @@ end AutoFrontlight:init() -local AutoFrontlightWidget = WidgetContainer:new{ +local AutoFrontlightWidget = WidgetContainer:extend{ name = "autofrontlight", } diff --git a/plugins/autostandby.koplugin/main.lua b/plugins/autostandby.koplugin/main.lua index 0fbb3e4bc..b1a23288d 100644 --- a/plugins/autostandby.koplugin/main.lua +++ b/plugins/autostandby.koplugin/main.lua @@ -13,7 +13,7 @@ local SpinWidget = require("ui/widget/spinwidget") local logger = require("logger") local _ = require("gettext") -local AutoStandby = WidgetContainer:new{ +local AutoStandby = WidgetContainer:extend{ is_doc_only = false, name = "autostandby", diff --git a/plugins/autosuspend.koplugin/main.lua b/plugins/autosuspend.koplugin/main.lua index 2774de1b5..f796c17f7 100644 --- a/plugins/autosuspend.koplugin/main.lua +++ b/plugins/autosuspend.koplugin/main.lua @@ -21,7 +21,7 @@ local default_autoshutdown_timeout_seconds = 3*24*60*60 -- three days local default_auto_suspend_timeout_seconds = 15*60 -- 15 minutes local default_auto_standby_timeout_seconds = 4 -- 4 seconds; should be safe on Kobo/Sage -local AutoSuspend = WidgetContainer:new{ +local AutoSuspend = WidgetContainer:extend{ name = "autosuspend", is_doc_only = false, autoshutdown_timeout_seconds = default_autoshutdown_timeout_seconds, diff --git a/plugins/autoturn.koplugin/main.lua b/plugins/autoturn.koplugin/main.lua index cc8037e13..33db80661 100644 --- a/plugins/autoturn.koplugin/main.lua +++ b/plugins/autoturn.koplugin/main.lua @@ -9,7 +9,7 @@ local util = require("util") local _ = require("gettext") local T = require("ffi/util").template -local AutoTurn = WidgetContainer:new{ +local AutoTurn = WidgetContainer:extend{ name = "autoturn", is_doc_only = true, autoturn_sec = 0, diff --git a/plugins/autowarmth.koplugin/main.lua b/plugins/autowarmth.koplugin/main.lua index 2c81c2115..877fb51b4 100644 --- a/plugins/autowarmth.koplugin/main.lua +++ b/plugins/autowarmth.koplugin/main.lua @@ -43,10 +43,10 @@ local function frac(x) return x - math.floor(x) end -local AutoWarmth = WidgetContainer:new{ +local AutoWarmth = WidgetContainer:extend{ name = "autowarmth", - sched_times_s = {}, - sched_warmths = {}, + sched_times_s = nil, -- array + sched_warmths = nil, -- array fl_turned_off = nil -- true/false if autowarmth has toggled the frontlight } diff --git a/plugins/backgroundrunner.koplugin/commandrunner.lua b/plugins/backgroundrunner.koplugin/commandrunner.lua index 3580e5b2f..9fb8b3678 100644 --- a/plugins/backgroundrunner.koplugin/commandrunner.lua +++ b/plugins/backgroundrunner.koplugin/commandrunner.lua @@ -33,7 +33,6 @@ function CommandRunner:createEnvironment() end function CommandRunner:start(job) - assert(self ~= nil) assert(self.pio == nil) assert(self.job == nil) self.job = job @@ -51,7 +50,6 @@ end -- @return a table contains the result from luawrapper.sh. Returns nil if the -- command has not been finished. function CommandRunner:poll() - assert(self ~= nil) assert(self.pio ~= nil) assert(self.job ~= nil) local line = self.pio:read() @@ -87,7 +85,6 @@ end --- Whether this is a running job. -- @treturn boolean function CommandRunner:pending() - assert(self ~= nil) return self.pio ~= nil end diff --git a/plugins/backgroundrunner.koplugin/main.lua b/plugins/backgroundrunner.koplugin/main.lua index d7d747b76..61d14c7af 100644 --- a/plugins/backgroundrunner.koplugin/main.lua +++ b/plugins/backgroundrunner.koplugin/main.lua @@ -115,7 +115,6 @@ function BackgroundRunner:_shouldRepeat(job) end function BackgroundRunner:_finishJob(job) - assert(self ~= nil) if type(job.executable) == "function" then local time_diff = job.end_time - job.start_time local threshold = time.s(1) @@ -159,7 +158,6 @@ end --- Polls the status of the pending CommandRunner. function BackgroundRunner:_poll() - assert(self ~= nil) assert(CommandRunner:pending()) local result = CommandRunner:poll() if result == nil then return end @@ -169,7 +167,6 @@ end function BackgroundRunner:_execute() logger.dbg("BackgroundRunner: _execute() @ ", os.time()) - assert(self ~= nil) if CommandRunner:pending() then self:_poll() else @@ -236,7 +233,6 @@ function BackgroundRunner:_execute() end function BackgroundRunner:_schedule() - assert(self ~= nil) if self.running == false then if #self.jobs == 0 and not CommandRunner:pending() then logger.dbg("BackgroundRunnerWidget: no job, not running @ ", os.time()) @@ -252,14 +248,13 @@ function BackgroundRunner:_schedule() end function BackgroundRunner:_insert(job) - assert(self ~= nil) job.insert_time = UIManager:getTime() table.insert(self.jobs, job) end BackgroundRunner:_schedule() -local BackgroundRunnerWidget = WidgetContainer:new{ +local BackgroundRunnerWidget = WidgetContainer:extend{ name = "backgroundrunner", runner = BackgroundRunner, } diff --git a/plugins/batterystat.koplugin/main.lua b/plugins/batterystat.koplugin/main.lua index 7a3d1d30d..f4db142d9 100644 --- a/plugins/batterystat.koplugin/main.lua +++ b/plugins/batterystat.koplugin/main.lua @@ -263,7 +263,7 @@ end BatteryStat:init() -local BatteryStatWidget = WidgetContainer:new{ +local BatteryStatWidget = WidgetContainer:extend{ name = "batterystat", } diff --git a/plugins/bookshortcuts.koplugin/main.lua b/plugins/bookshortcuts.koplugin/main.lua index 6445f1468..c3ec68dad 100644 --- a/plugins/bookshortcuts.koplugin/main.lua +++ b/plugins/bookshortcuts.koplugin/main.lua @@ -12,7 +12,7 @@ local util = require("util") local _ = require("gettext") local T = FFIUtil.template -local BookShortcuts = WidgetContainer:new{ +local BookShortcuts = WidgetContainer:extend{ name = "bookshortcuts", shortcuts = LuaSettings:open(DataStorage:getSettingsDir() .. "/bookshortcuts.lua"), updated = false, diff --git a/plugins/calibre.koplugin/main.lua b/plugins/calibre.koplugin/main.lua index 04a683264..5801bf2ac 100644 --- a/plugins/calibre.koplugin/main.lua +++ b/plugins/calibre.koplugin/main.lua @@ -20,7 +20,7 @@ local _ = require("gettext") local C_ = _.pgettext local T = require("ffi/util").template -local Calibre = WidgetContainer:new{ +local Calibre = WidgetContainer:extend{ name = "calibre", is_doc_only = false, } diff --git a/plugins/calibre.koplugin/search.lua b/plugins/calibre.koplugin/search.lua index 04d8a01a9..ac53f5a2a 100644 --- a/plugins/calibre.koplugin/search.lua +++ b/plugins/calibre.koplugin/search.lua @@ -9,11 +9,11 @@ local Device = require("device") local DocumentRegistry = require("document/documentregistry") local InputDialog = require("ui/widget/inputdialog") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local Menu = require("ui/widget/menu") local Persist = require("persist") local Screen = require("device").screen local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local rapidjson = require("rapidjson") @@ -155,7 +155,8 @@ local function getBookInfo(book) size) end -local CalibreSearch = InputContainer:new{ +-- This is a singleton +local CalibreSearch = WidgetContainer:extend{ books = {}, libraries = {}, last_scan = {}, diff --git a/plugins/calibre.koplugin/wireless.lua b/plugins/calibre.koplugin/wireless.lua index eadd09f9c..8617a6904 100644 --- a/plugins/calibre.koplugin/wireless.lua +++ b/plugins/calibre.koplugin/wireless.lua @@ -10,11 +10,11 @@ local CalibreSearch = require("search") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local FFIUtil = require("ffi/util") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local InfoMessage = require("ui/widget/infomessage") local NetworkMgr = require("ui/network/manager") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local rapidjson = require("rapidjson") @@ -55,7 +55,7 @@ local function updateDir(dir) end end -local CalibreWireless = InputContainer:new{ +local CalibreWireless = WidgetContainer:extend{ id = "KOReader", model = require("device").model, version = require("version"):getCurrentRevision(), @@ -85,10 +85,11 @@ local CalibreWireless = InputContainer:new{ SET_CALIBRE_DEVICE_NAME = 2, TOTAL_SPACE = 4, }, - calibre = {}, + calibre = nil, -- hash } function CalibreWireless:init() + self.calibre = {} -- reversed operator codes and names dictionary self.opnames = {} for name, code in pairs(self.opcodes) do diff --git a/plugins/coverbrowser.koplugin/listmenu.lua b/plugins/coverbrowser.koplugin/listmenu.lua index 78d45e1de..e6eeb1213 100644 --- a/plugins/coverbrowser.koplugin/listmenu.lua +++ b/plugins/coverbrowser.koplugin/listmenu.lua @@ -51,7 +51,7 @@ local scale_by_size = Screen:scaleBySize(1000000) / 1000000 -- ItemShortCutIcon (for keyboard navigation) is private to menu.lua and can't be accessed, -- so we need to redefine it -local ItemShortCutIcon = WidgetContainer:new{ +local ItemShortCutIcon = WidgetContainer:extend{ dimen = Geom:new{ w = Screen:scaleBySize(22), h = Screen:scaleBySize(22) }, key = nil, bordersize = Size.border.default, @@ -94,8 +94,8 @@ end -- Based on menu.lua's MenuItem -local ListMenuItem = InputContainer:new{ - entry = {}, +local ListMenuItem = InputContainer:extend{ + entry = nil, -- hash, mandatory text = nil, show_parent = nil, detail = nil, diff --git a/plugins/coverbrowser.koplugin/main.lua b/plugins/coverbrowser.koplugin/main.lua index fcdce23d8..f030a2fbc 100644 --- a/plugins/coverbrowser.koplugin/main.lua +++ b/plugins/coverbrowser.koplugin/main.lua @@ -1,5 +1,5 @@ -local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local _ = require("gettext") local BookInfoManager = require("bookinfomanager") @@ -45,7 +45,7 @@ local history_display_mode = false -- not initialized yet local collection_display_mode = false -- not initialized yet local series_mode = nil -- defaults to not display series -local CoverBrowser = InputContainer:new{ +local CoverBrowser = WidgetContainer:extend{ name = "coverbrowser", } diff --git a/plugins/coverbrowser.koplugin/mosaicmenu.lua b/plugins/coverbrowser.koplugin/mosaicmenu.lua index fbfd8d797..5a736e635 100644 --- a/plugins/coverbrowser.koplugin/mosaicmenu.lua +++ b/plugins/coverbrowser.koplugin/mosaicmenu.lua @@ -48,7 +48,7 @@ local progress_widget -- ItemShortCutIcon (for keyboard navigation) is private to menu.lua and can't be accessed, -- so we need to redefine it -local ItemShortCutIcon = WidgetContainer:new{ +local ItemShortCutIcon = WidgetContainer:extend{ dimen = Geom:new{ w = Screen:scaleBySize(22), h = Screen:scaleBySize(22) }, key = nil, bordersize = Size.border.default, @@ -95,7 +95,7 @@ end -- The rendering of the TextBoxWidget we're doing below -- with decreasing font sizes till it fits is quite expensive. -local FakeCover = FrameContainer:new{ +local FakeCover = FrameContainer:extend{ width = nil, height = nil, margin = 0, @@ -343,8 +343,8 @@ end -- Based on menu.lua's MenuItem -local MosaicMenuItem = InputContainer:new{ - entry = {}, +local MosaicMenuItem = InputContainer:extend{ + entry = nil, -- table, mandatory text = nil, show_parent = nil, detail = nil, diff --git a/plugins/coverimage.koplugin/main.lua b/plugins/coverimage.koplugin/main.lua index f66de47d8..41396a150 100644 --- a/plugins/coverimage.koplugin/main.lua +++ b/plugins/coverimage.koplugin/main.lua @@ -62,7 +62,7 @@ local function getExtension(filename) return util.getFileNameSuffix(name):lower() end -local CoverImage = WidgetContainer:new{ +local CoverImage = WidgetContainer:extend{ name = "coverimage", is_doc_only = true, } diff --git a/plugins/docsettingtweak.koplugin/main.lua b/plugins/docsettingtweak.koplugin/main.lua index 9cc1555b2..9a27557e5 100644 --- a/plugins/docsettingtweak.koplugin/main.lua +++ b/plugins/docsettingtweak.koplugin/main.lua @@ -17,7 +17,7 @@ local filemanagerutil = require("apps/filemanager/filemanagerutil") local lfs = require("libs/libkoreader-lfs") local util = require("util") -local DocSettingTweak = WidgetContainer:new{ +local DocSettingTweak = WidgetContainer:extend{ name = "docsettingtweak", } diff --git a/plugins/exporter.koplugin/main.lua b/plugins/exporter.koplugin/main.lua index 4a0bca05f..65de9f16c 100644 --- a/plugins/exporter.koplugin/main.lua +++ b/plugins/exporter.koplugin/main.lua @@ -27,10 +27,10 @@ local DataStorage = require("datastorage") local Device = require("device") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local MyClipping = require("clip") local NetworkMgr = require("ui/network/manager") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local _ = require("gettext") @@ -93,7 +93,7 @@ local function updateMyClippings(clippings, new_clippings) return clippings end -local Exporter = InputContainer:new { +local Exporter = WidgetContainer:extend{ name = "exporter", clipping_dir = DataStorage:getDataDir() .. "/clipboard", targets = { diff --git a/plugins/gestures.koplugin/main.lua b/plugins/gestures.koplugin/main.lua index 8ac06d7cf..c022a8a65 100644 --- a/plugins/gestures.koplugin/main.lua +++ b/plugins/gestures.koplugin/main.lua @@ -9,12 +9,12 @@ local Geom = require("ui/geometry") local GestureDetector = require("device/gesturedetector") local GestureRange = require("ui/gesturerange") local InfoMessage = require("ui/widget/infomessage") -local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") local LuaSettings = require("luasettings") local Screen = require("device").screen local SpinWidget = require("ui/widget/spinwidget") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local util = require("util") @@ -27,7 +27,7 @@ if not Device:isTouchDevice() then return { disabled = true, } end -local Gestures = InputContainer:new{ +local Gestures = WidgetContainer:extend{ name = "gestures", settings_data = nil, gestures = nil, diff --git a/plugins/gestures.koplugin/migration.lua b/plugins/gestures.koplugin/migration.lua index 9c8dfbcee..6c79c1001 100644 --- a/plugins/gestures.koplugin/migration.lua +++ b/plugins/gestures.koplugin/migration.lua @@ -4,7 +4,7 @@ local LuaData = require("luadata") local Migration = {} local custom_multiswipes_path = DataStorage:getSettingsDir().."/multiswipes.lua" -local custom_multiswipes = LuaData:open(custom_multiswipes_path, { name = "MultiSwipes" }) +local custom_multiswipes = LuaData:open(custom_multiswipes_path, "MultiSwipes") local custom_multiswipes_table = custom_multiswipes:readSetting("multiswipes") function Migration:convertAction(location, ges, action) diff --git a/plugins/hello.koplugin/main.lua b/plugins/hello.koplugin/main.lua index 3a11ca3c5..8fbef77c0 100644 --- a/plugins/hello.koplugin/main.lua +++ b/plugins/hello.koplugin/main.lua @@ -15,7 +15,7 @@ local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") -local Hello = WidgetContainer:new{ +local Hello = WidgetContainer:extend{ name = "hello", is_doc_only = false, } diff --git a/plugins/japanese.koplugin/main.lua b/plugins/japanese.koplugin/main.lua index 8d544c5e6..5a545599f 100644 --- a/plugins/japanese.koplugin/main.lua +++ b/plugins/japanese.koplugin/main.lua @@ -29,12 +29,12 @@ local _ = require("gettext") local N_ = _.ngettext local T = require("ffi/util").template -local SingleInstanceDeinflector = Deinflector:new() +local SingleInstanceDeinflector = Deinflector:new{} -local Japanese = WidgetContainer:new({ +local Japanese = WidgetContainer:extend{ name = "japanese", pretty_name = "Japanese", -}) +} -- Yomichan uses 10 characters as the default look-ahead, but crengine's -- getNextVisibleChar counts furigana if any are present, so use a higher diff --git a/plugins/keepalive.koplugin/main.lua b/plugins/keepalive.koplugin/main.lua index f291ff002..9eb19819d 100644 --- a/plugins/keepalive.koplugin/main.lua +++ b/plugins/keepalive.koplugin/main.lua @@ -59,7 +59,7 @@ menuItem.callback = function() showConfirmBox() end -local KeepAlive = WidgetContainer:new{ +local KeepAlive = WidgetContainer:extend{ name = "keepalive", } diff --git a/plugins/kosync.koplugin/main.lua b/plugins/kosync.koplugin/main.lua index 48c650f34..a3e14f195 100644 --- a/plugins/kosync.koplugin/main.lua +++ b/plugins/kosync.koplugin/main.lua @@ -1,18 +1,18 @@ -local Dispatcher = require("dispatcher") -local InputContainer = require("ui/widget/container/inputcontainer") -local LoginDialog = require("ui/widget/logindialog") -local InfoMessage = require("ui/widget/infomessage") local ConfirmBox = require("ui/widget/confirmbox") -local NetworkMgr = require("ui/network/manager") -local UIManager = require("ui/uimanager") local Device = require("device") +local Dispatcher = require("dispatcher") local Event = require("ui/event") +local InfoMessage = require("ui/widget/infomessage") +local LoginDialog = require("ui/widget/logindialog") local Math = require("optmath") -local Screen = Device.screen +local NetworkMgr = require("ui/network/manager") +local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local md5 = require("ffi/sha2").md5 local random = require("random") local util = require("util") +local Screen = Device.screen local T = require("ffi/util").template local _ = require("gettext") @@ -20,7 +20,7 @@ if G_reader_settings:hasNot("device_id") then G_reader_settings:saveSetting("device_id", random.uuid()) end -local KOSync = InputContainer:new{ +local KOSync = WidgetContainer:extend{ name = "kosync", is_doc_only = true, title = _("Register/login to KOReader server"), diff --git a/plugins/movetoarchive.koplugin/main.lua b/plugins/movetoarchive.koplugin/main.lua index 74c702222..820bed3c8 100644 --- a/plugins/movetoarchive.koplugin/main.lua +++ b/plugins/movetoarchive.koplugin/main.lua @@ -13,7 +13,7 @@ local util = require("frontend/util") local BaseUtil = require("ffi/util") local _ = require("gettext") -local MoveToArchive = WidgetContainer:new{ +local MoveToArchive = WidgetContainer:extend{ name = "movetoarchive", } diff --git a/plugins/newsdownloader.koplugin/main.lua b/plugins/newsdownloader.koplugin/main.lua index 21a37aabd..c056469d0 100644 --- a/plugins/newsdownloader.koplugin/main.lua +++ b/plugins/newsdownloader.koplugin/main.lua @@ -22,7 +22,7 @@ local util = require("util") local _ = require("gettext") local T = FFIUtil.template -local NewsDownloader = WidgetContainer:new{ +local NewsDownloader = WidgetContainer:extend{ name = "news_downloader", initialized = false, feed_config_file = "feed_config.lua", @@ -41,7 +41,7 @@ local NewsDownloader = WidgetContainer:new{ enable_filter = false, filter_element = "" }, - kv = {} + kv = nil, -- KeyValuePage } local FEED_TYPE_RSS = "rss" diff --git a/plugins/opds.koplugin/main.lua b/plugins/opds.koplugin/main.lua index 5cf79bed3..0872d32c6 100644 --- a/plugins/opds.koplugin/main.lua +++ b/plugins/opds.koplugin/main.lua @@ -3,7 +3,7 @@ local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") -local OPDS = WidgetContainer:new{ +local OPDS = WidgetContainer:extend{ name = "opds", is_doc_only = false, } diff --git a/plugins/opds.koplugin/opdscatalog.lua b/plugins/opds.koplugin/opdscatalog.lua index 42a164558..5c8a2f208 100644 --- a/plugins/opds.koplugin/opdscatalog.lua +++ b/plugins/opds.koplugin/opdscatalog.lua @@ -2,15 +2,15 @@ local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ConfirmBox = require("ui/widget/confirmbox") local FrameContainer = require("ui/widget/container/framecontainer") -local InputContainer = require("ui/widget/container/inputcontainer") local OPDSBrowser = require("opdsbrowser") local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") local _ = require("gettext") local Screen = require("device").screen local T = require("ffi/util").template -local OPDSCatalog = InputContainer:extend{ +local OPDSCatalog = WidgetContainer:extend{ title = _("OPDS Catalog"), } diff --git a/plugins/profiles.koplugin/main.lua b/plugins/profiles.koplugin/main.lua index 3ce5b44bb..33bbb4073 100644 --- a/plugins/profiles.koplugin/main.lua +++ b/plugins/profiles.koplugin/main.lua @@ -13,7 +13,7 @@ local util = require("util") local autostart_done = false -local Profiles = WidgetContainer:new{ +local Profiles = WidgetContainer:extend{ name = "profiles", profiles_file = DataStorage:getSettingsDir() .. "/profiles.lua", profiles = nil, diff --git a/plugins/qrclipboard.koplugin/main.lua b/plugins/qrclipboard.koplugin/main.lua index 379fe7623..ceae8e211 100644 --- a/plugins/qrclipboard.koplugin/main.lua +++ b/plugins/qrclipboard.koplugin/main.lua @@ -10,7 +10,7 @@ local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local _ = require("gettext") -local QRClipboard = WidgetContainer:new{ +local QRClipboard = WidgetContainer:extend{ name = "qrclipboard", is_doc_only = false, } diff --git a/plugins/readtimer.koplugin/main.lua b/plugins/readtimer.koplugin/main.lua index f2971f68c..dc89ee567 100644 --- a/plugins/readtimer.koplugin/main.lua +++ b/plugins/readtimer.koplugin/main.lua @@ -7,7 +7,7 @@ local util = require("util") local _ = require("gettext") local T = require("ffi/util").template -local ReadTimer = WidgetContainer:new{ +local ReadTimer = WidgetContainer:extend{ name = "readtimer", time = 0, -- The expected time of alarm if enabled, or 0. } diff --git a/plugins/statistics.koplugin/calendarview.lua b/plugins/statistics.koplugin/calendarview.lua index 2273bcbe7..ef2aeeed7 100644 --- a/plugins/statistics.koplugin/calendarview.lua +++ b/plugins/statistics.koplugin/calendarview.lua @@ -28,7 +28,7 @@ local Input = Device.input local Screen = Device.screen local _ = require("gettext") -local HistogramWidget = Widget:new{ +local HistogramWidget = Widget:extend{ width = nil, height = nil, color = Blitbuffer.COLOR_BLACK, @@ -76,7 +76,7 @@ function HistogramWidget:paintTo(bb, x, y) end -local CalendarDay = InputContainer:new{ +local CalendarDay = InputContainer:extend{ daynum = nil, ratio_per_hour = nil, filler = false, @@ -170,7 +170,7 @@ function CalendarDay:onHold() end -local CalendarWeek = InputContainer:new{ +local CalendarWeek = InputContainer:extend{ width = nil, height = nil, day_width = 0, @@ -367,7 +367,7 @@ end -- Fetched from db, cached as local as it might be expensive local MIN_MONTH = nil -local CalendarView = FocusManager:new{ +local CalendarView = FocusManager:extend{ reader_statistics = nil, monthTranslation = nil, shortDayOfWeekTranslation = nil, diff --git a/plugins/statistics.koplugin/main.lua b/plugins/statistics.koplugin/main.lua index 1815a1363..ff493ceff 100644 --- a/plugins/statistics.koplugin/main.lua +++ b/plugins/statistics.koplugin/main.lua @@ -70,19 +70,8 @@ local ReaderStatistics = Widget:extend{ book_read_pages = 0, book_read_time = 0, avg_time = nil, - page_stat = {}, -- Dictionary, indexed by page (hash), contains a list (array) of { timestamp, duration } tuples. - data = { - title = "", - authors = "N/A", - language = "N/A", - series = "N/A", - performance_in_pages = {}, - total_time_in_sec = 0, - highlights = 0, - notes = 0, - pages = 0, - md5 = nil, - }, + page_stat = nil, -- Dictionary, indexed by page (hash), contains a list (array) of { timestamp, duration } tuples. + data = nil, -- table } local weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } -- in Lua wday order @@ -150,6 +139,20 @@ function ReaderStatistics:init() return end + -- Placeholder until onReaderReady + self.data = { + title = "", + authors = "N/A", + language = "N/A", + series = "N/A", + performance_in_pages = {}, + total_time_in_sec = 0, + highlights = 0, + notes = 0, + pages = 0, + md5 = nil, + } + self.start_current_period = os.time() self:resetVolatileStats() diff --git a/plugins/statistics.koplugin/readerprogress.lua b/plugins/statistics.koplugin/readerprogress.lua index 10de9635d..f0e840f9f 100644 --- a/plugins/statistics.koplugin/readerprogress.lua +++ b/plugins/statistics.koplugin/readerprogress.lua @@ -25,7 +25,8 @@ local Screen = Device.screen local LINE_COLOR = Blitbuffer.COLOR_WEB_GRAY local BG_COLOR = Blitbuffer.COLOR_LIGHT_GRAY -local ReaderProgress = InputContainer:new{ +-- Oh, hey, this one actually *is* an InputContainer! +local ReaderProgress = InputContainer:extend{ padding = Size.padding.fullscreen, } diff --git a/plugins/systemstat.koplugin/main.lua b/plugins/systemstat.koplugin/main.lua index e5f75f83c..a0e6982be 100644 --- a/plugins/systemstat.koplugin/main.lua +++ b/plugins/systemstat.koplugin/main.lua @@ -291,7 +291,7 @@ end SystemStat:init() -local SystemStatWidget = WidgetContainer:new{ +local SystemStatWidget = WidgetContainer:extend{ name = "systemstat", } diff --git a/plugins/terminal.koplugin/main.lua b/plugins/terminal.koplugin/main.lua index 16881083e..fbe614f2c 100644 --- a/plugins/terminal.koplugin/main.lua +++ b/plugins/terminal.koplugin/main.lua @@ -82,7 +82,7 @@ local T = require("ffi/util").template local CHUNK_SIZE = 80 * 40 -- max. nb of read bytes (reduce this, if taps are not detected) -local Terminal = WidgetContainer:new{ +local Terminal = WidgetContainer:extend{ name = "terminal", history = "", is_shell_open = false, @@ -429,6 +429,11 @@ function Terminal:onClose() self:killShell() end +-- Kill the shell on plugin teardown +function Terminal:onCloseWidget() + self:killShell() +end + function Terminal:onTerminalStart(touchmenu_instance) self.touchmenu_instance = touchmenu_instance diff --git a/plugins/terminal.koplugin/terminputtext.lua b/plugins/terminal.koplugin/terminputtext.lua index bdc91fce8..c0d4373fb 100644 --- a/plugins/terminal.koplugin/terminputtext.lua +++ b/plugins/terminal.koplugin/terminputtext.lua @@ -52,10 +52,16 @@ local TermInputText = InputText:extend{ wrap = true, - alternate_buffer = {}, - save_buffer = {}, + alternate_buffer = nil, -- table + save_buffer = nil, -- table } +function TermInputText:init() + self.alternate_buffer = {} + self.save_buffer = {} + InputText.init(self) +end + -- disable positioning cursor by tap in emulator mode function TermInputText:onTapTextBox(arg, ges) return true diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index e22f91485..5ea1c1df1 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -26,7 +26,7 @@ local _ = require("gettext") local Screen = require("device").screen local T = ffiutil.template -local TextEditor = WidgetContainer:new{ +local TextEditor = WidgetContainer:extend{ name = "texteditor", settings_file = DataStorage:getSettingsDir() .. "/text_editor.lua", settings = nil, -- loaded only when needed diff --git a/plugins/timesync.koplugin/main.lua b/plugins/timesync.koplugin/main.lua index b97bbaaad..6fb7a5aec 100644 --- a/plugins/timesync.koplugin/main.lua +++ b/plugins/timesync.koplugin/main.lua @@ -17,7 +17,7 @@ local T = require("ffi/util").template local _ = require("gettext") local NetworkMgr = require("ui/network/manager") -local TimeSync = WidgetContainer:new{ +local TimeSync = WidgetContainer:extend{ name = "timesync", } diff --git a/plugins/vocabbuilder.koplugin/db.lua b/plugins/vocabbuilder.koplugin/db.lua index 64e1de890..24da2a029 100644 --- a/plugins/vocabbuilder.koplugin/db.lua +++ b/plugins/vocabbuilder.koplugin/db.lua @@ -99,7 +99,7 @@ end function VocabularyBuilder:insertLookupData(db_conn) local file_path = DataStorage:getSettingsDir() .. "/lookup_history.lua" - local lookup_history = LuaData:open(file_path, { name = "LookupHistory" }) + local lookup_history = LuaData:open(file_path, "LookupHistory") if lookup_history:has("lookup_history") then local lookup_history_table = lookup_history:readSetting("lookup_history") local book_titles = {} diff --git a/plugins/vocabbuilder.koplugin/main.lua b/plugins/vocabbuilder.koplugin/main.lua index 3295218a2..2ec78d614 100644 --- a/plugins/vocabbuilder.koplugin/main.lua +++ b/plugins/vocabbuilder.koplugin/main.lua @@ -137,7 +137,7 @@ end --[[-- Menu dialogue widget --]]-- -local MenuDialog = FocusManager:new{ +local MenuDialog = FocusManager:extend{ padding = Size.padding.large, is_edit_mode = false, edit_callback = nil, @@ -381,7 +381,7 @@ end --[[-- Individual word info dialogue widget --]]-- -local WordInfoDialog = InputContainer:new{ +local WordInfoDialog = InputContainer:extend{ title = nil, book_title = nil, dates = nil, @@ -594,7 +594,7 @@ local point_widget = TextWidget:new{ --[[-- Individual word item widget --]]-- -local VocabItemWidget = InputContainer:new{ +local VocabItemWidget = InputContainer:extend{ face = Font:getFace("smallinfofont"), width = nil, height = nil, @@ -985,7 +985,7 @@ end --[[-- Container widget. Same as sortwidget --]]-- -local VocabularyBuilderWidget = FocusManager:new{ +local VocabularyBuilderWidget = FocusManager:extend{ title = "", width = nil, height = nil, @@ -1414,7 +1414,7 @@ end --[[-- Item shown in main menu --]]-- -local VocabBuilder = WidgetContainer:new{ +local VocabBuilder = WidgetContainer:extend{ name = "vocabulary_builder", is_doc_only = false } diff --git a/plugins/wallabag.koplugin/main.lua b/plugins/wallabag.koplugin/main.lua index 39dad7800..62d4c2c0b 100644 --- a/plugins/wallabag.koplugin/main.lua +++ b/plugins/wallabag.koplugin/main.lua @@ -37,7 +37,7 @@ local article_id_prefix = "[w-id_" local article_id_postfix = "] " local failed, skipped, downloaded = 1, 2, 3 -local Wallabag = WidgetContainer:new{ +local Wallabag = WidgetContainer:extend{ name = "wallabag", } diff --git a/spec/unit/koptinterface_spec.lua b/spec/unit/koptinterface_spec.lua index fbd2f42f2..9099d6fcd 100644 --- a/spec/unit/koptinterface_spec.lua +++ b/spec/unit/koptinterface_spec.lua @@ -127,7 +127,7 @@ describe("Koptinterface module", function() local word_boxes = Koptinterface:getWordFromPosition(complex_doc, { page = 19, x = 320, y = 730, }) - assert.is.same("examples", word_boxes.word) + assert.is.same("of", word_boxes.word) end) it("should get link from native position", function() @@ -142,7 +142,7 @@ describe("Koptinterface module", function() it("should get link from reflow position", function() paper_doc.configurable.text_wrap = 1 local link = Koptinterface:getLinkFromPosition(paper_doc, 1, { - x = 500, y = 480, + x = 455, y = 1105, }) assert.truthy(link) assert.is.same(20, link.page) diff --git a/spec/unit/mock_time.lua b/spec/unit/mock_time.lua index a64bab8e9..ff4271b54 100644 --- a/spec/unit/mock_time.lua +++ b/spec/unit/mock_time.lua @@ -29,7 +29,6 @@ local MockTime = { } function MockTime:install() - assert(self ~= nil) if self.original_util_time == nil then self.original_util_time = util.gettime assert(self.original_util_time ~= nil) @@ -173,7 +172,6 @@ function MockTime:install() end function MockTime:uninstall() - assert(self ~= nil) os.time = self.original_os_time --luacheck: ignore if self.original_util_time ~= nil then util.gettime = self.original_util_time @@ -202,7 +200,6 @@ function MockTime:uninstall() end function MockTime:set_realtime(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -212,7 +209,6 @@ function MockTime:set_realtime(value) end function MockTime:increase_realtime(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -222,7 +218,6 @@ function MockTime:increase_realtime(value) end function MockTime:set_monotonic(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -232,7 +227,6 @@ function MockTime:set_monotonic(value) end function MockTime:increase_monotonic(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -242,7 +236,6 @@ function MockTime:increase_monotonic(value) end function MockTime:set_boottime(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -252,7 +245,6 @@ function MockTime:set_boottime(value) end function MockTime:increase_boottime(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -262,7 +254,6 @@ function MockTime:increase_boottime(value) end function MockTime:set_boottime_or_realtime_coarse(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -272,7 +263,6 @@ function MockTime:set_boottime_or_realtime_coarse(value) end function MockTime:increase_boottime_or_realtime_coarse(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -282,7 +272,6 @@ function MockTime:increase_boottime_or_realtime_coarse(value) end function MockTime:set(value) - assert(self ~= nil) if type(value) ~= "number" then return false end @@ -298,7 +287,6 @@ function MockTime:set(value) end function MockTime:increase(value) - assert(self ~= nil) if type(value) ~= "number" then return false end diff --git a/spec/unit/readerhighlight_spec.lua b/spec/unit/readerhighlight_spec.lua index e82e83b0d..02d3f40bd 100644 --- a/spec/unit/readerhighlight_spec.lua +++ b/spec/unit/readerhighlight_spec.lua @@ -187,7 +187,7 @@ describe("Readerhighlight module", function() highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }) Screen:shot("screenshots/reader_highlight_text_pdf_scanned.png") end) - it("should response on tap gesture", function() + it("should respond to tap gesture", function() tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 }) Screen:shot("screenshots/reader_tap_highlight_text_pdf_scanned.png") end) diff --git a/spec/unit/readerview_spec.lua b/spec/unit/readerview_spec.lua index 52aca89c1..5e387c956 100644 --- a/spec/unit/readerview_spec.lua +++ b/spec/unit/readerview_spec.lua @@ -40,7 +40,6 @@ describe("Readerview module", function() readerui:onClose() - assert.is.falsy(readerui.view.hinting) for i = #UIManager._task_queue, 1, -1 do local task = UIManager._task_queue[i] if task.action == readerui.view.emitHintPageEvent then diff --git a/spec/unit/wakeupmgr_spec.lua b/spec/unit/wakeupmgr_spec.lua index 9402f558e..08e6fe553 100644 --- a/spec/unit/wakeupmgr_spec.lua +++ b/spec/unit/wakeupmgr_spec.lua @@ -7,7 +7,7 @@ describe("WakeupMgr", function() require("commonrequire") package.unloadAll() RTC = require("ffi/rtc") - WakeupMgr = require("device/wakeupmgr") + WakeupMgr = require("device/wakeupmgr"):new{} -- We could theoretically test this by running the tests as root locally. stub(WakeupMgr, "setWakeupAlarm") WakeupMgr.validateWakeupAlarmByProximity = spy.new(function() return true end) diff --git a/tools/kobo_touch_probe.lua b/tools/kobo_touch_probe.lua index 673ec778d..6c6a8e6ee 100755 --- a/tools/kobo_touch_probe.lua +++ b/tools/kobo_touch_probe.lua @@ -23,22 +23,18 @@ end local InputContainer = require("ui/widget/container/inputcontainer") local CenterContainer = require("ui/widget/container/centercontainer") local FrameContainer = require("ui/widget/container/framecontainer") -local RightContainer = require("ui/widget/container/rightcontainer") local OverlapGroup = require("ui/widget/overlapgroup") local ImageWidget = require("ui/widget/imagewidget") local TextWidget = require("ui/widget/textwidget") local GestureRange = require("ui/gesturerange") local UIManager = require("ui/uimanager") local Blitbuffer = require("ffi/blitbuffer") -local Geom = require("ui/geometry") local Device = require("device") local Screen = Device.screen -local Input = Device.input local Font = require("ui/font") -local dbg = require("dbg") --dbg:turnOn() -local TouchProbe = InputContainer:new{ +local TouchProbe = InputContainer:extend{ curr_probe_step = 1, }