--[[-- HTML widget with vertical scroll bar. --]] local Device = require("device") local HtmlBoxWidget = require("ui/widget/htmlboxwidget") local Geom = require("ui/geometry") local GestureRange = require("ui/gesturerange") local HorizontalGroup = require("ui/widget/horizontalgroup") local HorizontalSpan = require("ui/widget/horizontalspan") local InputContainer = require("ui/widget/container/inputcontainer") local UIManager = require("ui/uimanager") local VerticalScrollBar = require("ui/widget/verticalscrollbar") local Math = require("optmath") local Input = Device.input local Screen = Device.screen local ScrollHtmlWidget = InputContainer:new{ html_body = nil, css = nil, default_font_size = 18, htmlbox_widget = nil, v_scroll_bar = nil, dialog = nil, html_link_tapped_callback = nil, dimen = nil, width = 0, height = 0, scroll_bar_width = Screen:scaleBySize(6), text_scroll_span = Screen:scaleBySize(12), } function ScrollHtmlWidget:init() self.htmlbox_widget = HtmlBoxWidget:new{ dimen = Geom:new{ w = self.width - self.scroll_bar_width - self.text_scroll_span, h = self.height, }, html_link_tapped_callback = self.html_link_tapped_callback, } self.htmlbox_widget:setContent(self.html_body, self.css, self.default_font_size) self.v_scroll_bar = VerticalScrollBar:new{ enable = self.htmlbox_widget.page_count > 1, width = self.scroll_bar_width, height = self.height, } self.v_scroll_bar:set((self.htmlbox_widget.page_number-1) / self.htmlbox_widget.page_count, self.htmlbox_widget.page_number / self.htmlbox_widget.page_count) local horizontal_group = HorizontalGroup:new{} table.insert(horizontal_group, self.htmlbox_widget) table.insert(horizontal_group, HorizontalSpan:new{width=self.text_scroll_span}) table.insert(horizontal_group, self.v_scroll_bar) self[1] = horizontal_group self.dimen = Geom:new(self[1]:getSize()) if Device:isTouchDevice() then self.ges_events = { ScrollText = { GestureRange:new{ ges = "swipe", range = function() return self.dimen end, }, }, TapScrollText = { -- allow scrolling with tap GestureRange:new{ ges = "tap", range = function() return self.dimen end, }, }, } end if Device:hasKeys() then self.key_events = { ScrollDown = {{Input.group.PgFwd}, doc = "scroll down"}, ScrollUp = {{Input.group.PgBack}, doc = "scroll up"}, } end end function ScrollHtmlWidget:getSinglePageHeight() return self.htmlbox_widget:getSinglePageHeight() end function ScrollHtmlWidget:scrollToRatio(ratio) ratio = math.max(0, math.min(1, ratio)) -- ensure ratio is between 0 and 1 (100%) local page_num = 1 + Math.round((self.htmlbox_widget.page_count - 1) * ratio) if page_num == self.htmlbox_widget.page_number then return end self.htmlbox_widget.page_number = page_num self.v_scroll_bar:set((page_num-1) / self.htmlbox_widget.page_count, page_num / self.htmlbox_widget.page_count) self.htmlbox_widget:freeBb() self.htmlbox_widget:_render() UIManager:setDirty(self.dialog, function() return "partial", self.dimen end) end function ScrollHtmlWidget:scrollText(direction) if direction == 0 then return end if direction > 0 then if self.htmlbox_widget.page_number >= self.htmlbox_widget.page_count then return end self.htmlbox_widget.page_number = self.htmlbox_widget.page_number + 1 elseif direction < 0 then if self.htmlbox_widget.page_number <= 1 then return end self.htmlbox_widget.page_number = self.htmlbox_widget.page_number - 1 end self.v_scroll_bar:set((self.htmlbox_widget.page_number-1) / self.htmlbox_widget.page_count, self.htmlbox_widget.page_number / self.htmlbox_widget.page_count) self.htmlbox_widget:freeBb() self.htmlbox_widget:_render() UIManager:setDirty(self.dialog, function() return "partial", self.dimen end) end function ScrollHtmlWidget:onScrollText(arg, ges) if ges.direction == "north" then self:scrollText(1) return true elseif ges.direction == "south" then self:scrollText(-1) return true end -- if swipe west/east, let it propagate up (e.g. for quickdictlookup to -- go to next/prev result) end function ScrollHtmlWidget:onTapScrollText(arg, ges) if ges.pos.x < Screen:getWidth()/2 then if self.htmlbox_widget.page_number > 1 then self:scrollText(-1) return true end else if self.htmlbox_widget.page_number < self.htmlbox_widget.page_count then self:scrollText(1) return true end end -- if we couldn't scroll (because we're already at top or bottom), -- let it propagate up (e.g. for quickdictlookup to go to next/prev result) end function ScrollHtmlWidget:onScrollDown() self:scrollText(1) return true end function ScrollHtmlWidget:onScrollUp() self:scrollText(-1) return true end return ScrollHtmlWidget