mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Viewer: When resizing and the resizing back to the old size ensure we return to the same page in paged mode. Fixes #1847507 [Viewer: when ToC is opened and closed, it doesn't return to same position](https://bugs.launchpad.net/calibre/+bug/1847507)
This commit is contained in:
parent
5f9b7597d9
commit
bc83a98ddf
@ -24,7 +24,8 @@ from read_book.paged_mode import (
|
|||||||
anchor_funcs as paged_anchor_funcs, calc_columns_per_screen, current_cfi,
|
anchor_funcs as paged_anchor_funcs, calc_columns_per_screen, current_cfi,
|
||||||
handle_gesture as paged_handle_gesture, handle_shortcut as paged_handle_shortcut,
|
handle_gesture as paged_handle_gesture, handle_shortcut as paged_handle_shortcut,
|
||||||
jump_to_cfi as paged_jump_to_cfi, layout as paged_layout,
|
jump_to_cfi as paged_jump_to_cfi, layout as paged_layout,
|
||||||
onwheel as paged_onwheel, progress_frac, reset_paged_mode_globals,
|
onwheel as paged_onwheel, prepare_for_resize as paged_prepare_for_resize,
|
||||||
|
progress_frac, reset_paged_mode_globals, resize_done as paged_resize_done,
|
||||||
scroll_by_page as paged_scroll_by_page, scroll_to_elem,
|
scroll_by_page as paged_scroll_by_page, scroll_to_elem,
|
||||||
scroll_to_fraction as paged_scroll_to_fraction, snap_to_selection
|
scroll_to_fraction as paged_scroll_to_fraction, snap_to_selection
|
||||||
)
|
)
|
||||||
@ -361,13 +362,16 @@ class IframeBoss:
|
|||||||
if scroll_viewport.width() is self.last_window_width and scroll_viewport.height() is self.last_window_height:
|
if scroll_viewport.width() is self.last_window_width and scroll_viewport.height() is self.last_window_height:
|
||||||
# Safari at least, generates lots of spurious resize events
|
# Safari at least, generates lots of spurious resize events
|
||||||
return
|
return
|
||||||
self.last_window_width, self.last_window_height = scroll_viewport.width(), scroll_viewport.height()
|
|
||||||
if current_layout_mode() is not 'flow':
|
if current_layout_mode() is not 'flow':
|
||||||
|
paged_prepare_for_resize(self.last_window_width, self.last_window_height)
|
||||||
self.do_layout(self.is_titlepage)
|
self.do_layout(self.is_titlepage)
|
||||||
|
self.last_window_width, self.last_window_height = scroll_viewport.width(), scroll_viewport.height()
|
||||||
if self.last_cfi:
|
if self.last_cfi:
|
||||||
cfi = self.last_cfi[len('epubcfi(/'):-1].partition('/')[2]
|
cfi = self.last_cfi[len('epubcfi(/'):-1].partition('/')[2]
|
||||||
if cfi:
|
if cfi:
|
||||||
paged_jump_to_cfi('/' + cfi)
|
paged_jump_to_cfi('/' + cfi)
|
||||||
|
if current_layout_mode() is not 'flow':
|
||||||
|
paged_resize_done()
|
||||||
self.update_cfi()
|
self.update_cfi()
|
||||||
self.update_toc_position()
|
self.update_toc_position()
|
||||||
|
|
||||||
|
@ -58,14 +58,15 @@ def create_page_div(elem):
|
|||||||
_in_paged_mode = False
|
_in_paged_mode = False
|
||||||
def in_paged_mode():
|
def in_paged_mode():
|
||||||
return _in_paged_mode
|
return _in_paged_mode
|
||||||
col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = 0
|
col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = last_scrolled_to_column = 0
|
||||||
is_full_screen_layout = False
|
is_full_screen_layout = False
|
||||||
|
|
||||||
def reset_paged_mode_globals():
|
def reset_paged_mode_globals():
|
||||||
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen, number_of_cols
|
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen, number_of_cols, last_scrolled_to_column
|
||||||
scroll_viewport.reset_globals()
|
scroll_viewport.reset_globals()
|
||||||
col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = 0
|
col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = last_scrolled_to_column = 0
|
||||||
is_full_screen_layout = _in_paged_mode = False
|
is_full_screen_layout = _in_paged_mode = False
|
||||||
|
resize_manager.reset()
|
||||||
|
|
||||||
def column_at(xpos):
|
def column_at(xpos):
|
||||||
# Return the (zero-based) number of the column that contains xpos
|
# Return the (zero-based) number of the column that contains xpos
|
||||||
@ -130,7 +131,7 @@ def calc_columns_per_screen():
|
|||||||
return cps
|
return cps
|
||||||
|
|
||||||
|
|
||||||
def layout(is_single_page):
|
def layout(is_single_page, on_resize):
|
||||||
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen
|
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen
|
||||||
body_style = window.getComputedStyle(document.body)
|
body_style = window.getComputedStyle(document.body)
|
||||||
first_layout = not _in_paged_mode
|
first_layout = not _in_paged_mode
|
||||||
@ -151,7 +152,7 @@ def layout(is_single_page):
|
|||||||
if not single_screen and cps > 1:
|
if not single_screen and cps > 1:
|
||||||
num = cps - 1
|
num = cps - 1
|
||||||
elems = document.querySelectorAll('body > *')
|
elems = document.querySelectorAll('body > *')
|
||||||
if elems.length == 1:
|
if elems.length is 1:
|
||||||
# Workaround for the case when the content is wrapped in a
|
# Workaround for the case when the content is wrapped in a
|
||||||
# 100% height <div>. This causes the generated page divs to
|
# 100% height <div>. This causes the generated page divs to
|
||||||
# not be in the correct location, at least in WebKit. See
|
# not be in the correct location, at least in WebKit. See
|
||||||
@ -242,12 +243,15 @@ def scroll_to_offset(x):
|
|||||||
|
|
||||||
|
|
||||||
def scroll_to_column(number, notify=False, duration=1000):
|
def scroll_to_column(number, notify=False, duration=1000):
|
||||||
|
nonlocal last_scrolled_to_column
|
||||||
|
last_scrolled_to_column = number
|
||||||
pos = number * col_and_gap
|
pos = number * col_and_gap
|
||||||
limit = scroll_viewport.paged_content_width() - screen_width
|
limit = scroll_viewport.paged_content_width() - screen_width
|
||||||
pos = min(pos, limit)
|
pos = min(pos, limit)
|
||||||
scroll_to_offset(pos)
|
scroll_to_offset(pos)
|
||||||
|
|
||||||
def scroll_to_xpos(xpos, notify=False, duration=1000):
|
def scroll_to_xpos(xpos, notify=False, duration=1000):
|
||||||
|
nonlocal last_scrolled_to_column
|
||||||
# Scroll so that the column containing xpos is the left most column in
|
# Scroll so that the column containing xpos is the left most column in
|
||||||
# the viewport
|
# the viewport
|
||||||
if jstype(xpos) is not 'number':
|
if jstype(xpos) is not 'number':
|
||||||
@ -255,6 +259,7 @@ def scroll_to_xpos(xpos, notify=False, duration=1000):
|
|||||||
return
|
return
|
||||||
if is_full_screen_layout:
|
if is_full_screen_layout:
|
||||||
scroll_to_offset(0)
|
scroll_to_offset(0)
|
||||||
|
last_scrolled_to_column = 0
|
||||||
return
|
return
|
||||||
scroll_to_column(column_at(xpos), notify=notify, duration=duration)
|
scroll_to_column(column_at(xpos), notify=notify, duration=duration)
|
||||||
|
|
||||||
@ -565,3 +570,44 @@ anchor_funcs = {
|
|||||||
return a - b
|
return a - b
|
||||||
,
|
,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ResizeManager:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.resize_in_progress = None
|
||||||
|
self.last_transition = None
|
||||||
|
|
||||||
|
def start_resize(self, width, height):
|
||||||
|
self.resize_in_progress = {'width': width, 'height': height, 'column': last_scrolled_to_column}
|
||||||
|
|
||||||
|
def end_resize(self):
|
||||||
|
if not self.resize_in_progress:
|
||||||
|
return
|
||||||
|
rp, self.resize_in_progress = self.resize_in_progress, None
|
||||||
|
transition = {'before': rp, 'after': {
|
||||||
|
'width': scroll_viewport.width(), 'height': scroll_viewport.height(), 'column': last_scrolled_to_column}}
|
||||||
|
if self.is_inverse_transition(transition):
|
||||||
|
if transition.after.column is not self.last_transition.before.column:
|
||||||
|
self.scroll_to_column(transition.after.column)
|
||||||
|
transition.after.column = last_scrolled_to_column
|
||||||
|
self.last_transition = transition
|
||||||
|
|
||||||
|
def is_inverse_transition(self, transition):
|
||||||
|
p = self.last_transition
|
||||||
|
if not p:
|
||||||
|
return False
|
||||||
|
p = p.after
|
||||||
|
n = transition.before
|
||||||
|
return p.column is n.column and p.width is n.width and p.height is n.height
|
||||||
|
|
||||||
|
|
||||||
|
resize_manager = ResizeManager()
|
||||||
|
def prepare_for_resize(width, height):
|
||||||
|
resize_manager.start_resize(width, height)
|
||||||
|
|
||||||
|
def resize_done():
|
||||||
|
resize_manager.end_resize()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user