mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
E-book viewer: Improve scrolling behavior when extending the selection using keyboard shortcuts
This commit is contained in:
parent
0219746e92
commit
f6e55966f5
@ -626,6 +626,27 @@ def ensure_selection_visible():
|
|||||||
unwrap(wrapper)
|
unwrap(wrapper)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_selection_boundary_visible(use_end):
|
||||||
|
sel = window.getSelection()
|
||||||
|
rr = sel.getRangeAt(0)
|
||||||
|
if rr:
|
||||||
|
r = rr.getBoundingClientRect()
|
||||||
|
if r:
|
||||||
|
node = sel.focusNode if use_end else sel.anchorNode
|
||||||
|
x = scroll_viewport.rect_inline_end(r) if use_end else scroll_viewport.rect_inline_start(r)
|
||||||
|
if x < 0 or x >= window.innerWidth:
|
||||||
|
x = scroll_viewport.viewport_to_document_inline(x, doc=node.ownerDocument)
|
||||||
|
if use_end:
|
||||||
|
x -= line_height()
|
||||||
|
scroll_viewport.scroll_to_in_inline_direction(x, True)
|
||||||
|
y = scroll_viewport.rect_block_end(r) if use_end else scroll_viewport.rect_block_start(r)
|
||||||
|
if y < 0 or y >= window.innerHeight:
|
||||||
|
y = scroll_viewport.viewport_to_document_block(y, doc=node.ownerDocument)
|
||||||
|
if use_end:
|
||||||
|
y -= line_height()
|
||||||
|
scroll_viewport.scroll_to_in_block_direction(y, True)
|
||||||
|
|
||||||
|
|
||||||
def jump_to_cfi(cfi):
|
def jump_to_cfi(cfi):
|
||||||
# Jump to the position indicated by the specified conformal fragment
|
# Jump to the position indicated by the specified conformal fragment
|
||||||
# indicator.
|
# indicator.
|
||||||
|
@ -7,11 +7,9 @@ from fs_images import fix_fullscreen_svg_images
|
|||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from iframe_comm import IframeClient
|
from iframe_comm import IframeClient
|
||||||
from range_utils import (
|
from range_utils import (
|
||||||
highlight_associated_with_selection,
|
highlight_associated_with_selection, last_span_for_crw, reset_highlight_counter,
|
||||||
last_span_for_crw, reset_highlight_counter, select_crw, unwrap_all_crw,
|
select_crw, unwrap_all_crw, unwrap_crw, wrap_text_in_range
|
||||||
unwrap_crw, wrap_text_in_range
|
|
||||||
)
|
)
|
||||||
from read_book.hints import hint_visible_links, unhint_links, apply_prefix_to_hints
|
|
||||||
from read_book.cfi import cfi_for_selection, range_from_cfi
|
from read_book.cfi import cfi_for_selection, range_from_cfi
|
||||||
from read_book.extract import get_elements
|
from read_book.extract import get_elements
|
||||||
from read_book.find import (
|
from read_book.find import (
|
||||||
@ -19,10 +17,12 @@ from read_book.find import (
|
|||||||
)
|
)
|
||||||
from read_book.flow_mode import (
|
from read_book.flow_mode import (
|
||||||
anchor_funcs as flow_anchor_funcs, auto_scroll_action as flow_auto_scroll_action,
|
anchor_funcs as flow_anchor_funcs, auto_scroll_action as flow_auto_scroll_action,
|
||||||
cancel_drag_scroll as cancel_drag_scroll_flow, ensure_selection_visible,
|
cancel_drag_scroll as cancel_drag_scroll_flow,
|
||||||
flow_onwheel, flow_to_scroll_fraction, handle_gesture as flow_handle_gesture,
|
ensure_selection_boundary_visible as ensure_selection_boundary_visible_flow,
|
||||||
handle_shortcut as flow_handle_shortcut, jump_to_cfi as flow_jump_to_cfi,
|
ensure_selection_visible, flow_onwheel, flow_to_scroll_fraction,
|
||||||
layout as flow_layout, scroll_by_page as flow_scroll_by_page,
|
handle_gesture as flow_handle_gesture, handle_shortcut as flow_handle_shortcut,
|
||||||
|
jump_to_cfi as flow_jump_to_cfi, layout as flow_layout,
|
||||||
|
scroll_by_page as flow_scroll_by_page,
|
||||||
scroll_to_extend_annotation as flow_annotation_scroll,
|
scroll_to_extend_annotation as flow_annotation_scroll,
|
||||||
start_drag_scroll as start_drag_scroll_flow
|
start_drag_scroll as start_drag_scroll_flow
|
||||||
)
|
)
|
||||||
@ -33,11 +33,13 @@ from read_book.globals import (
|
|||||||
set_toc_anchor_map
|
set_toc_anchor_map
|
||||||
)
|
)
|
||||||
from read_book.highlights import highlight_style_as_css
|
from read_book.highlights import highlight_style_as_css
|
||||||
|
from read_book.hints import apply_prefix_to_hints, hint_visible_links, unhint_links
|
||||||
from read_book.mathjax import apply_mathjax
|
from read_book.mathjax import apply_mathjax
|
||||||
from read_book.paged_mode import (
|
from read_book.paged_mode import (
|
||||||
anchor_funcs as paged_anchor_funcs,
|
anchor_funcs as paged_anchor_funcs,
|
||||||
auto_scroll_action as paged_auto_scroll_action, calc_columns_per_screen,
|
auto_scroll_action as paged_auto_scroll_action, calc_columns_per_screen,
|
||||||
cancel_drag_scroll as cancel_drag_scroll_paged, current_cfi,
|
cancel_drag_scroll as cancel_drag_scroll_paged, current_cfi,
|
||||||
|
ensure_selection_boundary_visible as ensure_selection_boundary_visible_paged,
|
||||||
get_columns_per_screen_data, handle_gesture as paged_handle_gesture,
|
get_columns_per_screen_data, handle_gesture as paged_handle_gesture,
|
||||||
handle_shortcut as paged_handle_shortcut, jump_to_cfi as paged_jump_to_cfi,
|
handle_shortcut as paged_handle_shortcut, jump_to_cfi as paged_jump_to_cfi,
|
||||||
layout as paged_layout, onwheel as paged_onwheel, page_counts,
|
layout as paged_layout, onwheel as paged_onwheel, page_counts,
|
||||||
@ -65,7 +67,7 @@ from read_book.touch import (
|
|||||||
)
|
)
|
||||||
from read_book.viewport import scroll_viewport
|
from read_book.viewport import scroll_viewport
|
||||||
from select import (
|
from select import (
|
||||||
move_end_of_selection, selection_extents, word_at_point, first_visible_word
|
first_visible_word, move_end_of_selection, selection_extents, word_at_point
|
||||||
)
|
)
|
||||||
from utils import debounce, is_ios
|
from utils import debounce, is_ios
|
||||||
|
|
||||||
@ -185,18 +187,20 @@ class IframeBoss:
|
|||||||
|
|
||||||
def modify_selection(self, data):
|
def modify_selection(self, data):
|
||||||
sel = window.getSelection()
|
sel = window.getSelection()
|
||||||
|
use_end = False
|
||||||
if data.granularity is 'all':
|
if data.granularity is 'all':
|
||||||
r = document.createRange()
|
r = document.createRange()
|
||||||
r.selectNode(document.body)
|
r.selectNode(document.body)
|
||||||
sel.removeAllRanges()
|
sel.removeAllRanges()
|
||||||
sel.addRange(r)
|
sel.addRange(r)
|
||||||
else:
|
else:
|
||||||
|
use_end = data.direction is 'forward' or data.direction is 'right'
|
||||||
try:
|
try:
|
||||||
sel.modify('extend', data.direction, data.granularity)
|
sel.modify('extend', data.direction, data.granularity)
|
||||||
except:
|
except:
|
||||||
if data.granularity is 'paragraph':
|
if data.granularity is 'paragraph':
|
||||||
sel.modify('extend', data.direction, 'line')
|
sel.modify('extend', data.direction, 'line')
|
||||||
self.ensure_selection_visible()
|
self.ensure_selection_boundary_visible(use_end)
|
||||||
|
|
||||||
def initialize(self, data):
|
def initialize(self, data):
|
||||||
scroll_viewport.update_window_size(data.width, data.height)
|
scroll_viewport.update_window_size(data.width, data.height)
|
||||||
@ -271,6 +275,7 @@ class IframeBoss:
|
|||||||
self.auto_scroll_action = flow_auto_scroll_action
|
self.auto_scroll_action = flow_auto_scroll_action
|
||||||
self.scroll_to_extend_annotation = flow_annotation_scroll
|
self.scroll_to_extend_annotation = flow_annotation_scroll
|
||||||
self.ensure_selection_visible = ensure_selection_visible
|
self.ensure_selection_visible = ensure_selection_visible
|
||||||
|
self.ensure_selection_boundary_visible = ensure_selection_boundary_visible_flow
|
||||||
self.start_drag_scroll = start_drag_scroll_flow
|
self.start_drag_scroll = start_drag_scroll_flow
|
||||||
paged_auto_scroll_action('stop')
|
paged_auto_scroll_action('stop')
|
||||||
else:
|
else:
|
||||||
@ -284,6 +289,7 @@ class IframeBoss:
|
|||||||
self.auto_scroll_action = paged_auto_scroll_action
|
self.auto_scroll_action = paged_auto_scroll_action
|
||||||
self.scroll_to_extend_annotation = paged_annotation_scroll
|
self.scroll_to_extend_annotation = paged_annotation_scroll
|
||||||
self.ensure_selection_visible = snap_to_selection
|
self.ensure_selection_visible = snap_to_selection
|
||||||
|
self.ensure_selection_boundary_visible = ensure_selection_boundary_visible_paged
|
||||||
self.start_drag_scroll = start_drag_scroll_paged
|
self.start_drag_scroll = start_drag_scroll_paged
|
||||||
flow_auto_scroll_action('stop')
|
flow_auto_scroll_action('stop')
|
||||||
update_settings(data.settings)
|
update_settings(data.settings)
|
||||||
|
@ -566,6 +566,23 @@ def snap_to_selection():
|
|||||||
# selection
|
# selection
|
||||||
scroll_to_pos(pos+5)
|
scroll_to_pos(pos+5)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_selection_boundary_visible(use_end):
|
||||||
|
sel = window.getSelection()
|
||||||
|
rr = sel.getRangeAt(0)
|
||||||
|
if rr:
|
||||||
|
r = rr.getBoundingClientRect()
|
||||||
|
if r:
|
||||||
|
cnum = column_at_current_scroll_offset()
|
||||||
|
scroll_to_column(cnum)
|
||||||
|
node = sel.focusNode if use_end else sel.anchorNode
|
||||||
|
# Columns are in the inline direction, so get the beginning of the element in the inline
|
||||||
|
x = scroll_viewport.rect_inline_end(r) if use_end else scroll_viewport.rect_inline_start(r)
|
||||||
|
if x < 0 or x >= scroll_viewport.inline_size():
|
||||||
|
pos = scroll_viewport.viewport_to_document_inline(x, doc=node.ownerDocument)
|
||||||
|
scroll_to_pos(pos+5)
|
||||||
|
|
||||||
|
|
||||||
def jump_to_cfi(cfi):
|
def jump_to_cfi(cfi):
|
||||||
# Jump to the position indicated by the specified conformal fragment
|
# Jump to the position indicated by the specified conformal fragment
|
||||||
# indicator.
|
# indicator.
|
||||||
|
@ -75,20 +75,20 @@ class ScrollViewport:
|
|||||||
else:
|
else:
|
||||||
window.scrollTo(x, y)
|
window.scrollTo(x, y)
|
||||||
|
|
||||||
def scroll_to_in_inline_direction(self, pos):
|
def scroll_to_in_inline_direction(self, pos, preserve_other):
|
||||||
# Lines flow vertically, so inline is vertical.
|
# Lines flow vertically, so inline is vertical.
|
||||||
if self.vertical_writing_mode:
|
if self.vertical_writing_mode:
|
||||||
self.scroll_to(0, pos)
|
self.scroll_to(self.x() if preserve_other else 0, pos)
|
||||||
else:
|
else:
|
||||||
self.scroll_to(pos, 0)
|
self.scroll_to(pos, self.y() if preserve_other else 0)
|
||||||
|
|
||||||
def scroll_to_in_block_direction(self, pos):
|
def scroll_to_in_block_direction(self, pos, preserve_other):
|
||||||
# In horizontal modes, the block direction is vertical.
|
# In horizontal modes, the block direction is vertical.
|
||||||
if self.horizontal_writing_mode:
|
if self.horizontal_writing_mode:
|
||||||
self.scroll_to(0, pos)
|
self.scroll_to(self.x() if preserve_other else 0, pos)
|
||||||
# In vertical modes, the block direction is horizontal.
|
# In vertical modes, the block direction is horizontal.
|
||||||
else:
|
else:
|
||||||
self.scroll_to(pos, 0)
|
self.scroll_to(pos, self.y() if preserve_other else 0)
|
||||||
|
|
||||||
def flow_scroll_into_view(self, elem):
|
def flow_scroll_into_view(self, elem):
|
||||||
elem.scrollIntoView()
|
elem.scrollIntoView()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user