mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Tame some ButtonTable users into re-using Buttontable instances if possible (#7166)
* QuickDictLookup, ImageViewer, NumberPicker: Smarter `update` that will re-use most of the widget's layout instead of re-instantiating all the things. * SpinWidget/DoubleSpinWidget: The NumberPicker change above renders a hack to preserve alpha on these widgets almost unnecessary. Also fixed said hack to also apply to the center, value button. * Button: Don't re-instantiate the frame in setText/setIcon when unnecessary (e.g., no change at all, or no layout change). * Button: Add a refresh method that repaints and refreshes a *specific* Button (provided it's been painted once) all on its lonesome. * ConfigDialog: Free everything that's going to be re-instatiated on update * A few more post #7118 fixes: * SkimTo: Always flag the chapter nav buttons as vsync * Button: Fix the highlight on rounded buttons when vsync is enabled (e.g., it's now entirely visible, instead of showing a weird inverted corner glitch). * Some more heuristic tweaks in Menu/TouchMenu/Button/IconButton * ButtonTable: fix the annoying rounding issue I'd noticed in #7054 ;). * Enable dithering in TextBoxWidget (e.g., in the Wikipedia full view). This involved moving the HW dithering align fixup to base, where it always ought to have been ;). * Switch a few widgets that were using "partial" on close to "ui", or, more rarely, "flashui". The intent being to limit "partial" purely to the Reader, because it has a latency cost when mixed with other refreshes, which happens often enough in UI ;). * Minor documentation tweaks around UIManager's `setDirty` to reflect that change. * ReaderFooter: Force a footer repaint on resume if it is visible (otherwise, just update it). * ReaderBookmark: In the same vein, don't repaint an invisible footer on bookmark count changes.
This commit is contained in:
@@ -36,16 +36,16 @@ local ImageViewer = InputContainer:new{
|
||||
file = nil,
|
||||
-- or an already made BlitBuffer (ie: made by Mupdf.renderImageFile())
|
||||
image = nil,
|
||||
-- whether provided BlitBuffer should be free(), normally true
|
||||
-- unless our caller wants to reuse it's provided image
|
||||
-- whether the provided BlitBuffer should be free'd. Usually true,
|
||||
-- unless our caller wants to reuse the image it provided
|
||||
image_disposable = true,
|
||||
|
||||
-- 'image' can alternatively be a table (list) of multiple BlitBuffers
|
||||
-- (or functions returning BlitBuffers).
|
||||
-- The table will have its .free() called onClose according to
|
||||
-- the image_disposable provided here.
|
||||
-- Each BlitBuffer in the table (or returned by functions) will be free()
|
||||
-- if the table has itself an attribute image_disposable=true.
|
||||
-- Each BlitBuffer in the table (or returned by functions) will be free'd
|
||||
-- if the table itself has an image_disposable field set to true.
|
||||
|
||||
-- With images list, when switching image, whether to keep previous
|
||||
-- image pan & zoom
|
||||
@@ -147,25 +147,12 @@ function ImageViewer:init()
|
||||
self._images_list_disposable = self.image_disposable
|
||||
self.image_disposable = self._images_list.image_disposable
|
||||
end
|
||||
self:update()
|
||||
end
|
||||
|
||||
function ImageViewer:_clean_image_wg()
|
||||
-- To be called before re-using / not needing self._image_wg
|
||||
-- otherwise resources used by its blitbuffer won't be freed
|
||||
if self._image_wg then
|
||||
logger.dbg("ImageViewer:_clean_image_wg()")
|
||||
self._image_wg:free()
|
||||
self._image_wg = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ImageViewer:update()
|
||||
self:_clean_image_wg() -- clean previous if any
|
||||
-- Widget layout
|
||||
if self._scale_to_fit == nil then -- initialize our toggle
|
||||
self._scale_to_fit = self.scale_factor == 0 and true or false
|
||||
self._scale_to_fit = self.scale_factor == 0
|
||||
end
|
||||
local orig_dimen = self.main_frame and self.main_frame.dimen or Geom:new{}
|
||||
local orig_dimen = Geom:new{}
|
||||
self.align = "center"
|
||||
self.region = Geom:new{
|
||||
x = 0, y = 0,
|
||||
@@ -180,180 +167,192 @@ function ImageViewer:update()
|
||||
self.width = Screen:getWidth() - Screen:scaleBySize(40)
|
||||
end
|
||||
|
||||
local button_table_size = 0
|
||||
local button_container
|
||||
if self.buttons_visible then
|
||||
local buttons = {
|
||||
-- Init the buttons no matter what
|
||||
local buttons = {
|
||||
{
|
||||
{
|
||||
{
|
||||
text = self._scale_to_fit and _("Original size") or _("Scale"),
|
||||
callback = function()
|
||||
self.scale_factor = self._scale_to_fit and 1 or 0
|
||||
self._scale_to_fit = not self._scale_to_fit
|
||||
-- Reset center ratio (may have been modified if some panning was done)
|
||||
self._center_x_ratio = 0.5
|
||||
self._center_y_ratio = 0.5
|
||||
self:update()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = self.rotated and _("No rotation") or _("Rotate"),
|
||||
callback = function()
|
||||
self.rotated = not self.rotated and true or false
|
||||
self:update()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Close"),
|
||||
callback = function()
|
||||
UIManager:close(self)
|
||||
end,
|
||||
},
|
||||
id = "scale",
|
||||
text = self._scale_to_fit and _("Original size") or _("Scale"),
|
||||
callback = function()
|
||||
self.scale_factor = self._scale_to_fit and 1 or 0
|
||||
self._scale_to_fit = not self._scale_to_fit
|
||||
-- Reset center ratio (may have been modified if some panning was done)
|
||||
self._center_x_ratio = 0.5
|
||||
self._center_y_ratio = 0.5
|
||||
self:update()
|
||||
end,
|
||||
},
|
||||
}
|
||||
local button_table = ButtonTable:new{
|
||||
width = self.width - 2*self.button_padding,
|
||||
button_font_face = "cfont",
|
||||
button_font_size = 20,
|
||||
buttons = buttons,
|
||||
zero_sep = true,
|
||||
show_parent = self,
|
||||
}
|
||||
button_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = button_table:getSize().h,
|
||||
{
|
||||
id = "rotate",
|
||||
text = self.rotated and _("No rotation") or _("Rotate"),
|
||||
callback = function()
|
||||
self.rotated = not self.rotated and true or false
|
||||
self:update()
|
||||
end,
|
||||
},
|
||||
button_table,
|
||||
}
|
||||
button_table_size = button_table:getSize().h
|
||||
{
|
||||
id = "close",
|
||||
text = _("Close"),
|
||||
callback = function()
|
||||
self:onClose()
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.button_table = ButtonTable:new{
|
||||
width = self.width - 2*self.button_padding,
|
||||
button_font_face = "cfont",
|
||||
button_font_size = 20,
|
||||
buttons = buttons,
|
||||
zero_sep = true,
|
||||
show_parent = self,
|
||||
}
|
||||
self.button_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = self.button_table:getSize().h,
|
||||
},
|
||||
self.button_table,
|
||||
}
|
||||
|
||||
if self.buttons_visible then
|
||||
self.button_table_size = self.button_table:getSize().h
|
||||
else
|
||||
self.button_table_size = 0
|
||||
end
|
||||
|
||||
-- height available to our image
|
||||
local img_container_h = self.height - button_table_size
|
||||
self.img_container_h = self.height - self.button_table_size
|
||||
|
||||
local title_bar, title_sep
|
||||
-- Init the title bar and its components no matter what
|
||||
-- Toggler (white arrow) for caption, on the left of title
|
||||
local ctoggler_text
|
||||
if self.caption_visible then
|
||||
ctoggler_text = "▽ " -- white arrow (nicer than smaller black arrow ▼)
|
||||
else
|
||||
ctoggler_text = "▷ " -- white arrow (nicer than smaller black arrow ►)
|
||||
end
|
||||
self.ctoggler_tw = TextWidget:new{
|
||||
text = ctoggler_text,
|
||||
face = self.title_face,
|
||||
}
|
||||
-- paddings chosen to align nicely with titlew
|
||||
self.ctoggler = FrameContainer:new{
|
||||
bordersize = 0,
|
||||
padding = self.title_padding,
|
||||
padding_top = self.title_padding + Size.padding.small,
|
||||
padding_right = 0,
|
||||
self.ctoggler_tw,
|
||||
}
|
||||
if self.caption then
|
||||
self.ctoggler_width = self.ctoggler:getSize().w
|
||||
else
|
||||
self.ctoggler_width = 0
|
||||
end
|
||||
self.closeb = CloseButton:new{ window = self, padding_top = Size.padding.tiny, }
|
||||
self.title_tbw = TextBoxWidget:new{
|
||||
text = self.title_text,
|
||||
face = self.title_face,
|
||||
-- bold = true, -- we're already using a bold font
|
||||
width = self.width - 2*self.title_padding - 2*self.title_margin - self.closeb:getSize().w - self.ctoggler_width,
|
||||
}
|
||||
local title_tbw_padding_bottom = self.title_padding + Size.padding.small
|
||||
if self.caption and self.caption_visible then
|
||||
title_tbw_padding_bottom = 0 -- save room between title and caption
|
||||
end
|
||||
self.titlew = FrameContainer:new{
|
||||
padding = self.title_padding,
|
||||
padding_top = self.title_padding + Size.padding.small,
|
||||
padding_bottom = title_tbw_padding_bottom,
|
||||
padding_left = self.caption and self.ctoggler_width or self.title_padding,
|
||||
margin = self.title_margin,
|
||||
bordersize = 0,
|
||||
self.title_tbw,
|
||||
}
|
||||
if self.caption then
|
||||
self.caption_tap_area = self.titlew
|
||||
end
|
||||
self.title_bar = OverlapGroup:new{
|
||||
dimen = {
|
||||
w = self.width,
|
||||
h = self.titlew:getSize().h
|
||||
},
|
||||
self.titlew,
|
||||
self.closeb
|
||||
}
|
||||
if self.caption then
|
||||
table.insert(self.title_bar, 1, self.ctoggler)
|
||||
end
|
||||
-- Init the caption no matter what
|
||||
self.caption_tbw = TextBoxWidget:new{
|
||||
text = self.caption or _("N/A"),
|
||||
face = self.caption_face,
|
||||
width = self.width - 2*self.title_padding - 2*self.title_margin - 2*self.caption_padding,
|
||||
}
|
||||
local captionw = FrameContainer:new{
|
||||
padding = self.caption_padding,
|
||||
padding_top = 0, -- don't waste vertical room for bigger image
|
||||
padding_bottom = 0,
|
||||
margin = self.title_margin,
|
||||
bordersize = 0,
|
||||
self.caption_tbw,
|
||||
}
|
||||
self.captioned_title_bar = VerticalGroup:new{
|
||||
align = "left",
|
||||
self.title_bar,
|
||||
captionw
|
||||
}
|
||||
|
||||
if self.caption and self.caption_visible then
|
||||
self.full_title_bar = self.captioned_title_bar
|
||||
else
|
||||
self.full_title_bar = self.title_bar
|
||||
end
|
||||
self.title_sep = LineWidget:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = Size.line.thick,
|
||||
}
|
||||
}
|
||||
-- adjust height available to our image
|
||||
if self.with_title_bar then
|
||||
-- Toggler (white arrow) for caption, on the left of title
|
||||
local ctoggler
|
||||
local ctoggler_width = 0
|
||||
if self.caption then
|
||||
local ctoggler_text
|
||||
if self.caption_visible then
|
||||
ctoggler_text = "▽ " -- white arrow (nicer than smaller black arrow ▼)
|
||||
else
|
||||
ctoggler_text = "▷ " -- white arrow (nicer than smaller black arrow ►)
|
||||
end
|
||||
-- paddings chosen to align nicely with titlew
|
||||
ctoggler = FrameContainer:new{
|
||||
bordersize = 0,
|
||||
padding = self.title_padding,
|
||||
padding_top = self.title_padding + Size.padding.small,
|
||||
padding_right = 0,
|
||||
TextWidget:new{
|
||||
text = ctoggler_text,
|
||||
face = self.title_face,
|
||||
}
|
||||
}
|
||||
ctoggler_width = ctoggler:getSize().w
|
||||
end
|
||||
local closeb = CloseButton:new{ window = self, padding_top = Size.padding.tiny, }
|
||||
local title_tbw = TextBoxWidget:new{
|
||||
text = self.title_text,
|
||||
face = self.title_face,
|
||||
-- bold = true, -- we're already using a bold font
|
||||
width = self.width - 2*self.title_padding - 2*self.title_margin - closeb:getSize().w - ctoggler_width,
|
||||
}
|
||||
local title_tbw_padding_bottom = self.title_padding + Size.padding.small
|
||||
if self.caption and self.caption_visible then
|
||||
title_tbw_padding_bottom = 0 -- save room between title and caption
|
||||
end
|
||||
local titlew = FrameContainer:new{
|
||||
padding = self.title_padding,
|
||||
padding_top = self.title_padding + Size.padding.small,
|
||||
padding_bottom = title_tbw_padding_bottom,
|
||||
padding_left = ctoggler and ctoggler_width or self.title_padding,
|
||||
margin = self.title_margin,
|
||||
bordersize = 0,
|
||||
title_tbw,
|
||||
}
|
||||
if self.caption then
|
||||
self.caption_tap_area = titlew
|
||||
end
|
||||
title_bar = OverlapGroup:new{
|
||||
dimen = {
|
||||
w = self.width,
|
||||
h = titlew:getSize().h
|
||||
},
|
||||
titlew,
|
||||
closeb
|
||||
}
|
||||
if ctoggler then
|
||||
table.insert(title_bar, 1, ctoggler)
|
||||
end
|
||||
if self.caption and self.caption_visible then
|
||||
local caption_tbw = TextBoxWidget:new{
|
||||
text = self.caption,
|
||||
face = self.caption_face,
|
||||
width = self.width - 2*self.title_padding - 2*self.title_margin - 2*self.caption_padding,
|
||||
}
|
||||
local captionw = FrameContainer:new{
|
||||
padding = self.caption_padding,
|
||||
padding_top = 0, -- don't waste vertical room for bigger image
|
||||
padding_bottom = 0,
|
||||
margin = self.title_margin,
|
||||
bordersize = 0,
|
||||
caption_tbw,
|
||||
}
|
||||
title_bar = VerticalGroup:new{
|
||||
align = "left",
|
||||
title_bar,
|
||||
captionw
|
||||
}
|
||||
end
|
||||
title_sep = LineWidget:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = Size.line.thick,
|
||||
}
|
||||
}
|
||||
-- adjust height available to our image
|
||||
img_container_h = img_container_h - title_bar:getSize().h - title_sep:getSize().h
|
||||
self.img_container_h = self.img_container_h - self.full_title_bar:getSize().h - self.title_sep:getSize().h
|
||||
end
|
||||
|
||||
local progress_container
|
||||
-- Init the progress bar no matter what
|
||||
-- progress bar
|
||||
local percent = 1
|
||||
if self._images_list and self._images_list_nb > 1 then
|
||||
percent = (self._images_list_cur - 1) / (self._images_list_nb - 1)
|
||||
end
|
||||
self.progress_bar = ProgressWidget:new{
|
||||
width = self.width - 2*self.button_padding,
|
||||
height = Screen:scaleBySize(5),
|
||||
percentage = percent,
|
||||
margin_h = 0,
|
||||
margin_v = 0,
|
||||
radius = 0,
|
||||
ticks = nil,
|
||||
last = nil,
|
||||
}
|
||||
self.progress_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = self.progress_bar:getSize().h + Size.padding.small,
|
||||
},
|
||||
self.progress_bar
|
||||
}
|
||||
|
||||
if self._images_list then
|
||||
-- progress bar
|
||||
local percent = 1
|
||||
if self._images_list_nb > 1 then
|
||||
percent = (self._images_list_cur - 1) / (self._images_list_nb - 1)
|
||||
end
|
||||
local progress_bar = ProgressWidget:new{
|
||||
width = self.width - 2*self.button_padding,
|
||||
height = Screen:scaleBySize(5),
|
||||
percentage = percent,
|
||||
margin_h = 0,
|
||||
margin_v = 0,
|
||||
radius = 0,
|
||||
ticks = nil,
|
||||
last = nil,
|
||||
}
|
||||
progress_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = progress_bar:getSize().h + Size.padding.small,
|
||||
},
|
||||
progress_bar
|
||||
}
|
||||
img_container_h = img_container_h - progress_container:getSize().h
|
||||
self.img_container_h = self.img_container_h - self.progress_container:getSize().h
|
||||
end
|
||||
|
||||
-- If no buttons and no title are shown, use the full screen
|
||||
local max_image_h = img_container_h
|
||||
local max_image_h = self.img_container_h
|
||||
local max_image_w = self.width
|
||||
-- Otherwise, add paddings around image
|
||||
if self.buttons_visible or self.with_title_bar then
|
||||
max_image_h = img_container_h - self.image_padding*2
|
||||
max_image_h = self.img_container_h - self.image_padding*2
|
||||
max_image_w = self.width - self.image_padding*2
|
||||
end
|
||||
|
||||
@@ -383,25 +382,25 @@ function ImageViewer:update()
|
||||
center_y_ratio = self._center_y_ratio,
|
||||
}
|
||||
|
||||
local image_container = CenterContainer:new{
|
||||
self.image_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = img_container_h,
|
||||
h = self.img_container_h,
|
||||
},
|
||||
self._image_wg,
|
||||
}
|
||||
|
||||
local frame_elements = VerticalGroup:new{ align = "left" }
|
||||
if self.with_title_bar then
|
||||
table.insert(frame_elements, title_bar)
|
||||
table.insert(frame_elements, title_sep)
|
||||
table.insert(frame_elements, self.full_title_bar)
|
||||
table.insert(frame_elements, self.title_sep)
|
||||
end
|
||||
table.insert(frame_elements, image_container)
|
||||
if progress_container then
|
||||
table.insert(frame_elements, progress_container)
|
||||
table.insert(frame_elements, self.image_container)
|
||||
if self._images_list then
|
||||
table.insert(frame_elements, self.progress_container)
|
||||
end
|
||||
if self.buttons_visible then
|
||||
table.insert(frame_elements, button_container)
|
||||
table.insert(frame_elements, self.button_container)
|
||||
end
|
||||
|
||||
self.main_frame = FrameContainer:new{
|
||||
@@ -427,7 +426,160 @@ function ImageViewer:update()
|
||||
self.dithered = true
|
||||
UIManager:setDirty(self, function()
|
||||
local update_region = self.main_frame.dimen:combine(orig_dimen)
|
||||
logger.dbg("update image region", update_region)
|
||||
return "ui", update_region, true
|
||||
end)
|
||||
end
|
||||
|
||||
function ImageViewer:_clean_image_wg()
|
||||
-- To be called before re-using / disposing of self._image_wg,
|
||||
-- otherwise resources used by its blitbuffer won't be free'd
|
||||
if self._image_wg then
|
||||
logger.dbg("ImageViewer:_clean_image_wg")
|
||||
self._image_wg:free()
|
||||
self._image_wg = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ImageViewer:update()
|
||||
-- Free our ImageWidget, which is the only thing we'll replace (e.g., leave the TextBoxWidgets alone).
|
||||
self:_clean_image_wg()
|
||||
|
||||
-- Update window geometry
|
||||
local orig_dimen = self.main_frame.dimen
|
||||
if self.fullscreen then
|
||||
self.height = Screen:getHeight()
|
||||
self.width = Screen:getWidth()
|
||||
else
|
||||
self.height = Screen:getHeight() - Screen:scaleBySize(40)
|
||||
self.width = Screen:getWidth() - Screen:scaleBySize(40)
|
||||
end
|
||||
|
||||
-- Update Buttons
|
||||
if self.buttons_visible then
|
||||
local scale_btn = self.button_table:getButtonById("scale")
|
||||
scale_btn:setText(self._scale_to_fit and _("Original size") or _("Scale"), scale_btn.width)
|
||||
local rotate_btn = self.button_table:getButtonById("rotate")
|
||||
rotate_btn:setText(self.rotated and _("No rotation") or _("Rotate"), rotate_btn.width)
|
||||
|
||||
self.button_table_size = self.button_table:getSize().h
|
||||
else
|
||||
self.button_table_size = 0
|
||||
end
|
||||
|
||||
-- height available to our image
|
||||
self.img_container_h = self.height - self.button_table_size
|
||||
|
||||
-- Update the title bar
|
||||
if self.with_title_bar then
|
||||
self.ctoggler_tw:setText(self.caption_visible and "▽ " or "▷ ")
|
||||
|
||||
-- Padding is dynamic...
|
||||
local title_tbw_padding_bottom = self.title_padding + Size.padding.small
|
||||
if self.caption and self.caption_visible then
|
||||
title_tbw_padding_bottom = 0
|
||||
end
|
||||
self.titlew.padding_bottom = title_tbw_padding_bottom
|
||||
self.title_bar.dimen.h = self.titlew:getSize().h
|
||||
|
||||
if self.caption and self.caption_visible then
|
||||
self.full_title_bar = self.captioned_title_bar
|
||||
else
|
||||
self.full_title_bar = self.title_bar
|
||||
end
|
||||
|
||||
self.img_container_h = self.img_container_h - self.full_title_bar:getSize().h - self.title_sep:getSize().h
|
||||
end
|
||||
|
||||
-- Update the progress bar
|
||||
if self._images_list then
|
||||
local percent = 1
|
||||
if self._images_list_nb > 1 then
|
||||
percent = (self._images_list_cur - 1) / (self._images_list_nb - 1)
|
||||
end
|
||||
|
||||
self.progress_bar:setPercentage(percent)
|
||||
|
||||
self.img_container_h = self.img_container_h - self.progress_container:getSize().h
|
||||
end
|
||||
|
||||
-- Update the image widget itself
|
||||
-- If no buttons and no title are shown, use the full screen
|
||||
local max_image_h = self.img_container_h
|
||||
local max_image_w = self.width
|
||||
-- Otherwise, add paddings around image
|
||||
if self.buttons_visible or self.with_title_bar then
|
||||
max_image_h = self.img_container_h - self.image_padding*2
|
||||
max_image_w = self.width - self.image_padding*2
|
||||
end
|
||||
|
||||
local rotation_angle = 0
|
||||
if self.rotated then
|
||||
-- in portrait mode, rotate according to this global setting so we are
|
||||
-- like in landscape mode
|
||||
local rotate_clockwise = DLANDSCAPE_CLOCKWISE_ROTATION
|
||||
if Screen:getWidth() > Screen:getHeight() then
|
||||
-- in landscape mode, counter-rotate landscape rotation so we are
|
||||
-- back like in portrait mode
|
||||
rotate_clockwise = not rotate_clockwise
|
||||
end
|
||||
rotation_angle = rotate_clockwise and 90 or 270
|
||||
end
|
||||
|
||||
self._image_wg = ImageWidget:new{
|
||||
file = self.file,
|
||||
image = self.image,
|
||||
image_disposable = false, -- we may re-use self.image
|
||||
alpha = true, -- we might be showing images with an alpha channel (e.g., from Wikipedia)
|
||||
width = max_image_w,
|
||||
height = max_image_h,
|
||||
rotation_angle = rotation_angle,
|
||||
scale_factor = self.scale_factor,
|
||||
center_x_ratio = self._center_x_ratio,
|
||||
center_y_ratio = self._center_y_ratio,
|
||||
}
|
||||
|
||||
self.image_container = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = self.width,
|
||||
h = self.img_container_h,
|
||||
},
|
||||
self._image_wg,
|
||||
}
|
||||
|
||||
-- Update the final layout
|
||||
local frame_elements = VerticalGroup:new{ align = "left" }
|
||||
if self.with_title_bar then
|
||||
table.insert(frame_elements, self.full_title_bar)
|
||||
table.insert(frame_elements, self.title_sep)
|
||||
end
|
||||
table.insert(frame_elements, self.image_container)
|
||||
if self._images_list then
|
||||
table.insert(frame_elements, self.progress_container)
|
||||
end
|
||||
if self.buttons_visible then
|
||||
table.insert(frame_elements, self.button_container)
|
||||
end
|
||||
|
||||
self.main_frame = FrameContainer:new{
|
||||
radius = not self.fullscreen and 8 or nil,
|
||||
padding = 0,
|
||||
margin = 0,
|
||||
background = Blitbuffer.COLOR_WHITE,
|
||||
frame_elements,
|
||||
}
|
||||
self[1] = WidgetContainer:new{
|
||||
align = self.align,
|
||||
dimen = self.region,
|
||||
FrameContainer:new{
|
||||
bordersize = 0,
|
||||
padding = Size.padding.default,
|
||||
self.main_frame,
|
||||
}
|
||||
}
|
||||
|
||||
self.dithered = true
|
||||
UIManager:setDirty(self, function()
|
||||
local update_region = self.main_frame.dimen:combine(orig_dimen)
|
||||
return "ui", update_region, true
|
||||
end)
|
||||
end
|
||||
@@ -442,7 +594,7 @@ end
|
||||
|
||||
function ImageViewer:switchToImageNum(image_num)
|
||||
if self.image and self.image_disposable and self.image.free then
|
||||
logger.dbg("ImageViewer:free(self.image)")
|
||||
logger.dbg("ImageViewer:switchToImageNum: free self.image", self.image)
|
||||
self.image:free()
|
||||
self.image = nil
|
||||
end
|
||||
@@ -470,7 +622,7 @@ function ImageViewer:onTap(_, ges)
|
||||
return self:onSaveImageView()
|
||||
end
|
||||
end
|
||||
if self.caption_tap_area and ges.pos:intersectWith(self.caption_tap_area.dimen) then
|
||||
if self.with_title_bar and self.caption_tap_area and ges.pos:intersectWith(self.caption_tap_area.dimen) then
|
||||
self.caption_visible = not self.caption_visible
|
||||
self:update()
|
||||
return true
|
||||
@@ -710,17 +862,38 @@ function ImageViewer:onAnyKeyPressed()
|
||||
end
|
||||
|
||||
function ImageViewer:onCloseWidget()
|
||||
-- clean all our BlitBuffer objects when UIManager:close() was called
|
||||
self:_clean_image_wg()
|
||||
-- Our ImageWidget (self._image_wg) is always a proper child widget, so it'll receive this event,
|
||||
-- and attempt to free its resources accordingly.
|
||||
-- But, if it didn't have to touch the original BB (self.image) passed to ImageViewer (e.g., no scaling needed),
|
||||
-- it will *re-use* self.image, and flag it as non-disposable, meaning it will not have been free'd earlier.
|
||||
-- Since we're the ones who ultimately truly know whether we should dispose of self.image or not, do that now ;).
|
||||
if self.image and self.image_disposable and self.image.free then
|
||||
logger.dbg("ImageViewer:free(self.image)")
|
||||
logger.dbg("ImageViewer:onCloseWidget: free self.image", self.image)
|
||||
self.image:free()
|
||||
self.image = nil
|
||||
end
|
||||
-- also clean _images_list if it provides a method for that
|
||||
if self._images_list and self._images_list_disposable and self._images_list.free then
|
||||
logger.dbg("ImageViewer:onCloseWidget: free self._images_list", self._images_list)
|
||||
self._images_list:free()
|
||||
end
|
||||
|
||||
-- Those, on the other hand, are always initialized, but may not actually be in our widget tree right now,
|
||||
-- depending on what we needed to show, so they might not get sent a CloseWidget event.
|
||||
-- They (and their FFI/C resources) would eventually get released by the GC, but let's be pedantic ;).
|
||||
if not self.with_title_bar then
|
||||
self.captioned_title_bar:free()
|
||||
end
|
||||
if not self.caption then
|
||||
self.ctoggler:free()
|
||||
end
|
||||
if not self._images_list then
|
||||
self.progress_container:free()
|
||||
end
|
||||
if not self.buttons_visible then
|
||||
self.button_container:free()
|
||||
end
|
||||
|
||||
-- NOTE: Assume there's no image beneath us, so, no dithering request
|
||||
UIManager:setDirty(nil, function()
|
||||
return "flashui", self.main_frame.dimen
|
||||
|
||||
Reference in New Issue
Block a user