diff --git a/frontend/document/document.lua b/frontend/document/document.lua index f453bda95..da246ff92 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -1,3 +1,5 @@ +require "../math" + --[[ This is a registry for document providers ]]-- @@ -126,17 +128,9 @@ function Document:getPageDimensions(pageno, zoom, rotation) return native_dimen end -function Document:oddEven(number) - if number % 2 == 1 then - return "odd" - else - return "even" - end -end - function Document:getPageBBox(pageno) local bbox = self.bbox[pageno] -- exact - local oddEven = self:oddEven(pageno) + local oddEven = math.oddEven(pageno) if bbox ~= nil then DEBUG("bbox from", pageno) else diff --git a/frontend/math.lua b/frontend/math.lua new file mode 100644 index 000000000..46b6a319c --- /dev/null +++ b/frontend/math.lua @@ -0,0 +1,25 @@ +--[[ +Simple math helper function +]]-- + +function math.roundAwayFromZero(num) + if num > 0 then + return math.ceil(num) + else + return math.floor(num) + end +end + +function math.round(num) + return math.floor(num + 0.5) +end + +function math.oddEven(number) + if number % 2 == 1 then + return "odd" + else + return "even" + end +end + + diff --git a/frontend/ui/bbox.lua b/frontend/ui/bbox.lua index 35b67559a..e38d0f669 100644 --- a/frontend/ui/bbox.lua +++ b/frontend/ui/bbox.lua @@ -1,3 +1,5 @@ +require "math" + --[[ BBoxWidget shows a bbox for page cropping ]] @@ -7,6 +9,43 @@ BBoxWidget = InputContainer:new{ linesize = 2, } +function BBoxWidget:init() + if Device:isTouchDevice() then + self.ges_events = { + AdjustCrop = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + ConfirmCrop = { + GestureRange:new{ + ges = "double_tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + CancelCrop = { + GestureRange:new{ + ges = "hold", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + } + end +end + function BBoxWidget:getSize() return Geom:new{ x = 0, y = 0, @@ -52,84 +91,29 @@ function BBoxWidget:screen_to_page() return bbox end -function BBoxWidget:oddEven(number) - if number % 2 == 1 then - return "odd" - else - return "even" - end -end - -function BBoxWidget:init() - if Device:isTouchDevice() then - self.ges_events = { - AdjustCrop = { - GestureRange:new{ - ges = "tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - ConfirmCrop = { - GestureRange:new{ - ges = "double_tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - CancelCrop = { - GestureRange:new{ - ges = "hold", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - } - end -end - -function BBoxWidget:onGesture(ev) - for name, gsseq in pairs(self.ges_events) do - for _, gs_range in ipairs(gsseq) do - --DEBUG("gs_range", gs_range) - if gs_range:match(ev) then - local eventname = gsseq.event or name - return self:handleEvent(Event:new(eventname, ev.pos)) - end - end - end -end - -function BBoxWidget:onAdjustCrop(pos) - DEBUG("adjusting crop bbox with pos", pos) +function BBoxWidget:onAdjustCrop(arg, ges) + DEBUG("adjusting crop bbox with pos", ges.pos) local bbox = self.screen_bbox local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0} local upper_right = Geom:new{ x = bbox.x1, y = bbox.y0} local bottom_left = Geom:new{ x = bbox.x0, y = bbox.y1} local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1} local corners = {upper_left, upper_right, bottom_left, bottom_right} - table.sort(corners, function(a,b) return a:distance(pos) < b:distance(pos) end) + table.sort(corners, function(a,b) + return a:distance(ges.pos) < b:distance(ges.pos) + end) if corners[1] == upper_left then - upper_left.x = pos.x - upper_left.y = pos.y + upper_left.x = ges.pos.x + upper_left.y = ges.pos.y elseif corners[1] == bottom_right then - bottom_right.x = pos.x - bottom_right.y = pos.y + bottom_right.x = ges.pos.x + bottom_right.y = ges.pos.y elseif corners[1] == upper_right then - bottom_right.x = pos.x - upper_left.y = pos.y + bottom_right.x = ges.pos.x + upper_left.y = ges.pos.y elseif corners[1] == bottom_left then - upper_left.x = pos.x - bottom_right.y = pos.y + upper_left.x = ges.pos.x + bottom_right.y = ges.pos.y end self.screen_bbox = { x0 = upper_left.x, @@ -146,7 +130,7 @@ function BBoxWidget:onConfirmCrop() UIManager:close(self) self.ui:handleEvent(Event:new("BBoxUpdate"), self.page_bbox) self.document.bbox[self.pageno] = self.page_bbox - self.document.bbox[self:oddEven(self.pageno)] = self.page_bbox + self.document.bbox[math.oddEven(self.pageno)] = self.page_bbox self.ui:handleEvent(Event:new("ExitPageCrop")) end diff --git a/frontend/ui/config.lua b/frontend/ui/config.lua index 1c2123025..eecd821a3 100644 --- a/frontend/ui/config.lua +++ b/frontend/ui/config.lua @@ -2,6 +2,7 @@ require "ui/widget" require "ui/focusmanager" require "ui/infomessage" require "ui/font" +require "ui/toggleswitch" FixedTextWidget = TextWidget:new{} function FixedTextWidget:getSize() @@ -171,155 +172,6 @@ function ToggleLabel:paintTo(bb, x, y) renderUtf8Text(bb, x, y+self._height*0.75, self.face, self.text, true) end -ToggleSwitch = InputContainer:new{} -function ToggleSwitch:init() - self.n_pos = #self.toggle - if self.n_pos ~= 2 and self.n_pos ~= 3 then - -- currently only support options with two or three items. - error("items number not supported") - end - self.position = nil - - local label_font_face = "cfont" - local label_font_size = 16 - - self.toggle_frame = FrameContainer:new{background = 0, color = 7, radius = 7, bordersize = 1, padding = 2,} - self.toggle_content = HorizontalGroup:new{} - - self.left_label = ToggleLabel:new{ - align = "center", - color = 0, - text = self.toggle[self.n_pos], - face = Font:getFace(label_font_face, label_font_size), - } - self.left_button = FrameContainer:new{ - background = 0, - color = 7, - margin = 0, - radius = 5, - bordersize = 1, - padding = 2, - self.left_label, - } - self.middle_label = ToggleLabel:new{ - align = "center", - color = 0, - text = self.n_pos > 2 and self.toggle[2] or "", - face = Font:getFace(label_font_face, label_font_size), - } - self.middle_button = FrameContainer:new{ - background = 0, - color = 7, - margin = 0, - radius = 5, - bordersize = 1, - padding = 2, - self.middle_label, - } - self.right_label = ToggleLabel:new{ - align = "center", - color = 0, - text = self.toggle[1], - face = Font:getFace(label_font_face, label_font_size), - } - self.right_button = FrameContainer:new{ - background = 0, - color = 7, - margin = 0, - radius = 5, - bordersize = 1, - padding = 2, - self.right_label, - } - - table.insert(self.toggle_content, self.left_button) - table.insert(self.toggle_content, self.middle_button) - table.insert(self.toggle_content, self.right_button) - - self.toggle_frame[1] = self.toggle_content - self[1] = self.toggle_frame - self.dimen = Geom:new(self.toggle_frame:getSize()) - if Device:isTouchDevice() then - self.ges_events = { - TapSelect = { - GestureRange:new{ - ges = "tap", - range = self.dimen, - }, - doc = "Toggle switch", - }, - } - end -end - -function ToggleSwitch:onGesture(ev) - for name, gsseq in pairs(self.ges_events) do - for _, gs_range in ipairs(gsseq) do - --DEBUG("gs_range", gs_range) - if gs_range:match(ev) then - local eventname = gsseq.event or name - local position = math.ceil((ev.pos.x-gs_range.range.x)/gs_range.range.w*self.n_pos) - return self:handleEvent(Event:new(eventname, position)) - end - end - end -end - -function ToggleSwitch:update() - local left_pos = self.position == 1 - local right_pos = self.position == self.n_pos - local middle_pos = not left_pos and not right_pos - self.left_label.color = right_pos and 15 or 0 - self.left_button.color = left_pos and 7 or 0 - self.left_button.background = left_pos and 7 or 0 - self.middle_label.color = middle_pos and 15 or 0 - self.middle_button.color = middle_pos and 0 or 0 - self.middle_button.background = middle_pos and 0 or 0 - self.right_label.color = left_pos and 15 or 0 - self.right_button.color = right_pos and 7 or 0 - self.right_button.background = right_pos and 7 or 0 -end - -function ToggleSwitch:setPosition(position) - self.position = position - self:update() -end - -function ToggleSwitch:togglePosition(position) - if self.n_pos == 2 and self.alternate ~= false then - self.position = (self.position+1)%self.n_pos - self.position = self.position == 0 and self.n_pos or self.position - else - self.position = position - end - self:update() -end - -function ToggleSwitch:onTapSelect(position) - DEBUG("toggle position:", position) - self:togglePosition(position) - local option_value = nil - local option_arg = nil - if self.values then - self.values = self.values or {} - option_value = self.values[self.position] - self.config:onConfigChoice(self.name, option_value) - end - if self.event then - self.args = self.args or {} - option_arg = self.args[self.position] - self.config:onConfigEvent(self.event, option_arg) - end - if self.events then - for i=1,#self.events do - self.events[i].args = self.events[i].args or {} - option_arg = self.events[i].args[self.position] - self.config:onConfigEvent(self.events[i].event, option_arg) - end - end - UIManager.repaint_all = true -end - ConfigOption = CenterContainer:new{} function ConfigOption:init() local default_name_font_size = 20 diff --git a/frontend/ui/geometry.lua b/frontend/ui/geometry.lua index 497100c6e..a20227d48 100644 --- a/frontend/ui/geometry.lua +++ b/frontend/ui/geometry.lua @@ -265,21 +265,3 @@ return the Euclidean distance between two geoms function Geom:distance(geom) return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2)) end - ---[[ -Simple math helper function -]]-- - -function math.roundAwayFromZero(num) - if num > 0 then - return math.ceil(num) - else - return math.floor(num) - end -end - -function math.round(num) - return math.floor(num + 0.5) -end - - diff --git a/frontend/ui/reader/readerpaging.lua b/frontend/ui/reader/readerpaging.lua index ff73d7603..f0cda7905 100644 --- a/frontend/ui/reader/readerpaging.lua +++ b/frontend/ui/reader/readerpaging.lua @@ -1,3 +1,5 @@ +require "math" + ReaderPaging = InputContainer:new{ current_page = 0, number_of_pages = 0, diff --git a/frontend/ui/toggleswitch.lua b/frontend/ui/toggleswitch.lua new file mode 100644 index 000000000..40e95f0cf --- /dev/null +++ b/frontend/ui/toggleswitch.lua @@ -0,0 +1,140 @@ +ToggleSwitch = InputContainer:new{} + +function ToggleSwitch:init() + self.n_pos = #self.toggle + if self.n_pos ~= 2 and self.n_pos ~= 3 then + -- currently only support options with two or three items. + error("items number not supported") + end + self.position = nil + + local label_font_face = "cfont" + local label_font_size = 16 + + self.toggle_frame = FrameContainer:new{background = 0, color = 7, radius = 7, bordersize = 1, padding = 2,} + self.toggle_content = HorizontalGroup:new{} + + self.left_label = ToggleLabel:new{ + align = "center", + color = 0, + text = self.toggle[self.n_pos], + face = Font:getFace(label_font_face, label_font_size), + } + self.left_button = FrameContainer:new{ + background = 0, + color = 7, + margin = 0, + radius = 5, + bordersize = 1, + padding = 2, + self.left_label, + } + self.middle_label = ToggleLabel:new{ + align = "center", + color = 0, + text = self.n_pos > 2 and self.toggle[2] or "", + face = Font:getFace(label_font_face, label_font_size), + } + self.middle_button = FrameContainer:new{ + background = 0, + color = 7, + margin = 0, + radius = 5, + bordersize = 1, + padding = 2, + self.middle_label, + } + self.right_label = ToggleLabel:new{ + align = "center", + color = 0, + text = self.toggle[1], + face = Font:getFace(label_font_face, label_font_size), + } + self.right_button = FrameContainer:new{ + background = 0, + color = 7, + margin = 0, + radius = 5, + bordersize = 1, + padding = 2, + self.right_label, + } + + table.insert(self.toggle_content, self.left_button) + table.insert(self.toggle_content, self.middle_button) + table.insert(self.toggle_content, self.right_button) + + self.toggle_frame[1] = self.toggle_content + self[1] = self.toggle_frame + self.dimen = Geom:new(self.toggle_frame:getSize()) + if Device:isTouchDevice() then + self.ges_events = { + TapSelect = { + GestureRange:new{ + ges = "tap", + range = self.dimen, + }, + doc = "Toggle switch", + }, + } + end +end + +function ToggleSwitch:update() + local left_pos = self.position == 1 + local right_pos = self.position == self.n_pos + local middle_pos = not left_pos and not right_pos + self.left_label.color = right_pos and 15 or 0 + self.left_button.color = left_pos and 7 or 0 + self.left_button.background = left_pos and 7 or 0 + self.middle_label.color = middle_pos and 15 or 0 + self.middle_button.color = middle_pos and 0 or 0 + self.middle_button.background = middle_pos and 0 or 0 + self.right_label.color = left_pos and 15 or 0 + self.right_button.color = right_pos and 7 or 0 + self.right_button.background = right_pos and 7 or 0 +end + +function ToggleSwitch:setPosition(position) + self.position = position + self:update() +end + +function ToggleSwitch:togglePosition(position) + if self.n_pos == 2 and self.alternate ~= false then + self.position = (self.position+1)%self.n_pos + self.position = self.position == 0 and self.n_pos or self.position + else + self.position = position + end + self:update() +end + +function ToggleSwitch:onTapSelect(arg, gev) + DEBUG("toggle position:", position) + local position = math.ceil( + (gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos + ) + self:togglePosition(position) + local option_value = nil + local option_arg = nil + if self.values then + self.values = self.values or {} + option_value = self.values[self.position] + self.config:onConfigChoice(self.name, option_value) + end + if self.event then + self.args = self.args or {} + option_arg = self.args[self.position] + self.config:onConfigEvent(self.event, option_arg) + end + if self.events then + for i=1,#self.events do + self.events[i].args = self.events[i].args or {} + option_arg = self.events[i].args[self.position] + self.config:onConfigEvent(self.events[i].event, option_arg) + end + end + UIManager.repaint_all = true +end +