diff --git a/frontend/ui/config.lua b/frontend/ui/config.lua index a9c72eccd..7862380cf 100644 --- a/frontend/ui/config.lua +++ b/frontend/ui/config.lua @@ -3,6 +3,24 @@ require "ui/focusmanager" require "ui/infomessage" require "ui/font" +FixedTextWidget = TextWidget:new{} +function FixedTextWidget:getSize() + local tsize = sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true) + if not tsize then + return Geom:new{} + end + self._length = tsize.x + self._height = self.face.size + return Geom:new{ + w = self._length, + h = self._height, + } +end + +function FixedTextWidget:paintTo(bb, x, y) + renderUtf8Text(bb, x, y+self._height, self.face, self.text, true) +end + ConfigMenuItem = InputContainer:new{ dimen = nil, } @@ -26,20 +44,13 @@ function ConfigMenuItem:init() end end -function ConfigMenuItem:onFocus() - self[1].inverse = true - self.key_events = self.active_key_events - return true -end - -function ConfigMenuItem:onUnfocus() - self[1].inverse = false - self.key_events = { } - return true -end - function ConfigMenuItem:onTapSelect() - self.config:onShowDialog(self.dialog) + for _, item in pairs(self.config.menu_items) do + item[1].invert = false + end + self[1].invert = true + self.config:onShowOptions(self.options) + UIManager.repaint_all = true return true end @@ -50,50 +61,188 @@ MenuItemDialog = FocusManager:new{ is_borderless = false, } +ConfigIcons = HorizontalGroup:new{} +function ConfigIcons:init() + for c = 1, #self.icons do + table.insert(self, self.spacing) + table.insert(self, self.icons[c]) + end + table.insert(self, self.spacing) +end + +ConfigOption = CenterContainer:new{dimen = Geom:new{ w = Screen:getWidth(), h = 100},} +function ConfigOption:init() + local vertical_group = VerticalGroup:new{} + for c = 1, #self.options do + local name_align = self.options[c].name_align_right + local item_align = self.options[c].item_align_center + local horizontal_group = HorizontalGroup:new{} + local option_name_container = RightContainer:new{ + dimen = Geom:new{ w = Screen:getWidth()*(name_align and name_align or 0.33), h = 30}, + } + local option_name = TextWidget:new{ + text = self.options[c].name, + face = self.options[c].name_face, + } + table.insert(option_name_container, option_name) + table.insert(horizontal_group, option_name_container) + local option_items_container = CenterContainer:new{ + dimen = Geom:new{w = Screen:getWidth()*(item_align and item_align or 0.66), h = 30} + } + local option_items_group = HorizontalGroup:new{} + for d = 1, #self.options[c].items do + local option_item = TextWidget:new{ + text = self.options[c].items[d], + face = self.options[c].item_face, + } + table.insert(option_items_group, option_item) + table.insert(option_items_group, self.options[c].spacing) + end + table.insert(option_items_container, option_items_group) + table.insert(horizontal_group, option_items_container) + table.insert(vertical_group, horizontal_group) + end + self[1] = vertical_group +end + +ConfigFontSize = CenterContainer:new{dimen = Geom:new{ w = Screen:getWidth(), h = 100},} +function ConfigFontSize:init() + local vertical_group = VerticalGroup:new{} + local horizontal_group = HorizontalGroup:new{align = "bottom"} + for c = 1, #self.items do + local widget = FixedTextWidget:new{ + text = self.items[c], + face = Font:getFace(self.item_font_face, self.item_font_size[c]), + } + table.insert(horizontal_group, self.spacing) + table.insert(horizontal_group, widget) + end + table.insert(vertical_group, horizontal_group) + self[1] = vertical_group +end + --[[ Widget that displays config menu --]] ConfigDialog = FocusManager:new{ - -- set this to true to not paint as popup menu + -- face for option names + tface = Font:getFace("tfont", 20), + -- face for option items + cface = Font:getFace("cfont", 16), is_borderless = false, } -function ConfigDialog:init() +function ConfigDialog:init() self.menu_dimen = self.dimen:copy() ----------------------------------- -- start to set up widget layout -- ----------------------------------- - self.screen_rotate_options = HorizontalGroup:new{ - - } self.screen_rotate_icon = ImageWidget:new{ file = "resources/icons/appbar.transform.rotate.right.large.png" } - self.screen_rotate_dialog = FrameContainer:new{ - dimen = self.screen_rotate_options:getSize(), - background = 0, - bordersize = 0, - padding = 0, - margin = 0, - self.screen_rotate_options, + self.screen_rotate_options = ConfigOption:new{ + options = { + { + name = "Screen Rotation", + name_face = Font:getFace("tfont", 20), + items = {"portrait", "landscape"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + } + }, } + self.page_crop_icon = ImageWidget:new{ file = "resources/icons/appbar.crop.large.png" } + self.page_crop_options = ConfigOption:new{ + options = { + { + name = "Page Crop", + name_face = Font:getFace("tfont", 20), + items = {"auto", "manual"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + } + }, + } + self.page_layout_icon = ImageWidget:new{ file = "resources/icons/appbar.column.two.large.png" } + self.page_layout_options = ConfigOption:new{ + options = { + { + name = "Page Margin", + name_face = Font:getFace("tfont", 20), + items = {"small", "medium", "large"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + }, + { + name = "Line Spacing", + name_face = Font:getFace("tfont", 20), + items = {"small", "medium", "large"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + }, + { + name = "Word Spacing", + name_face = Font:getFace("tfont", 20), + items = {"small", "medium", "large"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + }, + }, + } + self.text_font_icon = ImageWidget:new{ file = "resources/icons/appbar.text.size.large.png" } + self.text_font_options = ConfigFontSize:new{ + items = {"Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa"}, + item_font_face = "cfont", + item_font_size={14,16,20,23,26,30,34,38,42,46}, + spacing = HorizontalSpan:new{ width = Screen:getWidth()*0.03 }, + } + self.contrast_icon = ImageWidget:new{ file = "resources/icons/appbar.grade.b.large.png" } + self.contrast_options = ConfigOption:new{ + options = { + { + name = "Contrast", + name_face = Font:getFace("tfont", 20), + name_align_right = 0.2, + items = {"lightest", "lighter", "default", "darker", "darkest"}, + item_align_center = 0.8, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 30 }, + } + }, + } + self.more_options_icon = ImageWidget:new{ file = "resources/icons/appbar.settings.large.png" } - self.icon_spacing = HorizontalSpan:new{ - width = (Screen:getWidth() - 64*6 - 20) / 7 + self.more_options = ConfigOption:new{ + options = { + { + name = "Render Quality", + name_face = Font:getFace("tfont", 20), + items = {"low", "default", "high"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 20 }, + }, + { + name = "Auto Straighten", + name_face = Font:getFace("tfont", 20), + items = {"0 deg", "5 deg", "10 deg"}, + item_face = Font:getFace("cfont", 16), + spacing = HorizontalSpan:new{ width = 20 }, + }, + } } self.icon_dimen = Geom:new{ @@ -101,68 +250,99 @@ function ConfigDialog:init() h = 64, -- hardcoded for now } - -- group for config layout - local config_dialog = VerticalGroup:new{ - align = "center", - HorizontalGroup:new{ - align = "center", - MenuItemDialog:new{ - self.screen_rotate_dialog, - dimen = self.screen_rotate_dialog:getSize(), - title = "Screen Rotation", - }, - }, + self.reading_progress = VerticalGroup:new{ + ProgressWidget:new{ + width = Screen:getWidth()*0.7, + height = 5, + percentage = 0.0, + } + } + local default_options = CenterContainer:new{ HorizontalGroup:new{ - align = "center", - self.icon_spacing, - ConfigMenuItem:new{ - self.screen_rotate_icon, - dimen = self.icon_dimen:new(), - config = self, - }, - self.icon_spacing, - ConfigMenuItem:new{ - self.page_crop_icon, - dimen = self.icon_dimen:new(), - dialog = "Crop dialog", - config = self, - }, - self.icon_spacing, - ConfigMenuItem:new{ - self.page_layout_icon, - dimen = self.icon_dimen:new(), - config = self, - }, - self.icon_spacing, - ConfigMenuItem:new{ - self.text_font_icon, - dimen = self.icon_dimen:new(), - config = self, - }, - self.icon_spacing, - ConfigMenuItem:new{ - self.contrast_icon, - dimen = self.icon_dimen:new(), - config = self, + CenterContainer:new{ + VerticalGroup:new{ + align = "center", + self.reading_progress, + }, + dimen = Geom:new{ w = Screen:getWidth()*0.8, h = 100}, }, - self.icon_spacing, - ConfigMenuItem:new{ - self.more_options_icon, - dimen = self.icon_dimen:new(), - config = self, + CenterContainer:new{ + TextWidget:new{ + text = "Goto", + face = self.tface, + }, + dimen = Geom:new{ w = Screen:getWidth()*0.2, h = 100}, }, - self.icon_spacing, - } + }, + dimen = Geom:new{ w = Screen:getWidth(), h = 100}, + } + + self.menu_items = { + ConfigMenuItem:new{ + self.screen_rotate_icon, + options = self.screen_rotate_options, + dimen = self.icon_dimen:new(), + config = self, + }, + ConfigMenuItem:new{ + self.page_crop_icon, + options = self.page_crop_options, + dimen = self.icon_dimen:new(), + config = self, + }, + ConfigMenuItem:new{ + self.page_layout_icon, + options = self.page_layout_options, + dimen = self.icon_dimen:new(), + config = self, + }, + ConfigMenuItem:new{ + self.text_font_icon, + options = self.text_font_options, + dimen = self.icon_dimen:new(), + config = self, + }, + ConfigMenuItem:new{ + self.contrast_icon, + options = self.contrast_options, + dimen = self.icon_dimen:new(), + config = self, + }, + ConfigMenuItem:new{ + self.more_options_icon, + options = self.more_options, + dimen = self.icon_dimen:new(), + config = self, + }, + } + + local config_icons = ConfigIcons:new{ + icons = self.menu_items, + spacing = HorizontalSpan:new{ + width = (Screen:getWidth() - self.icon_dimen.w * #self.menu_items - 20) / (#self.menu_items+1) + }, + } + + local config_menu = FrameContainer:new{ + dimen = config_icons:getSize(), + background = 0, + config_icons, + } + + -- group for config layout + local config_layout = VerticalGroup:new{ + default_options, + config_menu, } -- maintain reference to content so we can change it later - self.config_dialog = config_dialog + self.config_layout = config_layout self[1] = BottomContainer:new{ dimen = Screen:getSize(), FrameContainer:new{ - dimen = config_dialog:getSize(), + dimen = config_layout:getSize(), background = 0, - config_dialog + config_layout, } } @@ -191,9 +371,9 @@ function ConfigDialog:init() UIManager.repaint_all = true end -function ConfigDialog:onShowDialog(dialog) - DEBUG("Showing dialog of item", dialog) - UIManager:show(dialog) +function ConfigDialog:onShowOptions(options) + self.config_layout[1] = options + UIManager.repaint_all = true return true end diff --git a/frontend/ui/graphics.lua b/frontend/ui/graphics.lua index 6a35fd8fb..d864b5e80 100644 --- a/frontend/ui/graphics.lua +++ b/frontend/ui/graphics.lua @@ -70,9 +70,9 @@ function blitbuffer.progressBar(bb, x, y, w, h, if load_m_h*2 > h then load_m_h = h/2 end - blitbuffer.paintBorder(fb.bb, x, y, w, h, 2, 15) - fb.bb:paintRect(x+load_m_w, y+load_m_h, - (w-2*load_m_w)*load_percent, (h-2*load_m_h), c) + bb:paintBorder(x, y, w, h, 2, 15) + bb:paintRect(x+load_m_w, y+load_m_h, + (w-2*load_m_w)*load_percent, (h-2*load_m_h), c) end diff --git a/frontend/ui/widget.lua b/frontend/ui/widget.lua index e6f8819e7..42290f62a 100644 --- a/frontend/ui/widget.lua +++ b/frontend/ui/widget.lua @@ -145,6 +145,22 @@ function CenterContainer:paintTo(bb, x, y) y + (self.dimen.h - contentSize.h)/2) end +--[[ +RightContainer aligns its content (1 widget) at the right of its own dimensions +]] +RightContainer = WidgetContainer:new() + +function RightContainer:paintTo(bb, x, y) + local contentSize = self[1]:getSize() + if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then + -- throw error? paint to scrap buffer and blit partially? + -- for now, we ignore this + end + self[1]:paintTo(bb, + x + (self.dimen.w - contentSize.w), + y + (self.dimen.h - contentSize.h)/2) +end + --[[ A FrameContainer is some graphics content (1 widget) that is surrounded by a frame ]] @@ -376,6 +392,24 @@ function ImageWidget:free() end end +--[[ +ProgressWidget shows a progress bar +]] +ProgressWidget = Widget:new{ + width = nil, + height = nil, + pecentage = nil, +} + +function ProgressWidget:getSize() + return { w = self.width, h = self.height } +end + +function ProgressWidget:paintTo(bb, x, y) + local size = self:getSize() + bb:progressBar(x, y, self.width, self.height, size.w, size.h, 2, 2, self.percentage, 15) +end + --[[ A Layout widget that puts objects besides each others ]]