mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Click to position handles implemented
This commit is contained in:
parent
97da8da4c9
commit
4defd82bed
@ -4,10 +4,10 @@ from __python__ import bound_methods, hash_literals
|
||||
|
||||
from dom import svgicon, ensure_id
|
||||
|
||||
WAITING_FOR_CLICK = 0
|
||||
WAITING_FOR_DRAG = 1
|
||||
DRAGGING_LEFT = 2
|
||||
DRAGGING_RIGHT = 3
|
||||
WAITING_FOR_CLICK = 1
|
||||
WAITING_FOR_DRAG = 2
|
||||
DRAGGING_LEFT = 3
|
||||
DRAGGING_RIGHT = 4
|
||||
|
||||
|
||||
def selection_handle(invert):
|
||||
@ -17,6 +17,7 @@ def selection_handle(invert):
|
||||
s.transform = 'scaleX(-1)'
|
||||
s.position = 'absolute'
|
||||
s.boxSizing = 'border-box'
|
||||
s.touchAction = 'none'
|
||||
return ans
|
||||
|
||||
|
||||
@ -28,6 +29,14 @@ def map_from_iframe_coords(point):
|
||||
return point
|
||||
|
||||
|
||||
def map_to_iframe_coords(point):
|
||||
l = document.getElementById('book-left-margin')
|
||||
point.x -= l.offsetWidth
|
||||
t = document.getElementById('book-top-margin')
|
||||
point.y -= t.offsetHeight
|
||||
return point
|
||||
|
||||
|
||||
class CreateAnnotation:
|
||||
|
||||
container_id = 'create-annotation-overlay'
|
||||
@ -44,6 +53,14 @@ class CreateAnnotation:
|
||||
self.right_handle_id = ensure_id(rh, 'handle')
|
||||
container.appendChild(rh)
|
||||
|
||||
container.addEventListener('click', self.container_clicked)
|
||||
|
||||
def container_clicked(self, ev):
|
||||
ev.stopPropagation(), ev.preventDefault()
|
||||
if self.state is WAITING_FOR_CLICK:
|
||||
pt = map_to_iframe_coords({'x': ev.clientX, 'y': ev.clientY})
|
||||
self.send_message(type='position-handles-at-point', x=pt.x, y=pt.y)
|
||||
|
||||
@property
|
||||
def container(self):
|
||||
return document.getElementById(self.container_id)
|
||||
@ -78,6 +95,9 @@ class CreateAnnotation:
|
||||
self.hide_handles()
|
||||
if msg.extents.start.x is not None:
|
||||
self.place_handles(msg.extents)
|
||||
elif msg.type is 'position-handles':
|
||||
if self.state is WAITING_FOR_CLICK:
|
||||
self.place_handles(msg.extents)
|
||||
else:
|
||||
print('Ignoring annotations message with unknown type:', msg.type)
|
||||
|
||||
|
@ -4,6 +4,7 @@ from __python__ import bound_methods, hash_literals
|
||||
|
||||
import traceback
|
||||
from gettext import gettext as _
|
||||
from select import selection_extents, selection_extents_at_point
|
||||
|
||||
from fs_images import fix_fullscreen_svg_images
|
||||
from iframe_comm import IframeClient
|
||||
@ -50,7 +51,7 @@ from read_book.touch import (
|
||||
create_handlers as create_touch_handlers, reset_handlers as reset_touch_handlers
|
||||
)
|
||||
from read_book.viewport import scroll_viewport
|
||||
from utils import debounce, html_escape, is_ios, selection_extents
|
||||
from utils import debounce, html_escape, is_ios
|
||||
|
||||
FORCE_FLOW_MODE = False
|
||||
CALIBRE_VERSION = '__CALIBRE_VERSION__'
|
||||
@ -120,6 +121,7 @@ class IframeBoss:
|
||||
'overlay_visibility_changed': self.on_overlay_visibility_changed,
|
||||
'show_search_result': self.show_search_result,
|
||||
'handle_navigation_shortcut': self.on_handle_navigation_shortcut,
|
||||
'annotations': self.annotations_msg_received,
|
||||
}
|
||||
self.comm = IframeClient(handlers)
|
||||
self.last_window_ypos = 0
|
||||
@ -608,6 +610,15 @@ class IframeBoss:
|
||||
extents=selection_extents(),
|
||||
)
|
||||
|
||||
def annotations_msg_received(self, data):
|
||||
if data.type is 'position-handles-at-point':
|
||||
self.send_message(
|
||||
'annotations',
|
||||
type='position-handles',
|
||||
extents=selection_extents_at_point(data.x, data.y))
|
||||
else:
|
||||
console.log('Ignoring annotations message to iframe with unknown type: ' + data.type)
|
||||
|
||||
|
||||
def main():
|
||||
main.boss = IframeBoss()
|
||||
|
@ -42,3 +42,51 @@ def word_at_point(x, y):
|
||||
r.setStart(r.startContainer, word_info.start)
|
||||
r.setEnd(r.startContainer, word_info.end)
|
||||
return r
|
||||
|
||||
|
||||
def range_extents(start, end):
|
||||
ans = {'start': {'x': None, 'y': None, 'height': None}, 'end': {'x': None, 'y': None, 'height': None}}
|
||||
if not start or not end:
|
||||
return ans
|
||||
start = start.cloneRange()
|
||||
end = end.cloneRange()
|
||||
start.collapse(True)
|
||||
end.collapse(False)
|
||||
|
||||
def for_boundary(r, ans):
|
||||
rects = r.getClientRects()
|
||||
if not rects.length:
|
||||
return
|
||||
rect = rects[0]
|
||||
ans.x = rect.left
|
||||
ans.y = rect.top
|
||||
ans.height = rect.bottom - rect.top
|
||||
|
||||
for_boundary(start, ans.start)
|
||||
for_boundary(end, ans.end)
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
def selection_extents():
|
||||
sel = window.getSelection()
|
||||
if not sel or not sel.rangeCount:
|
||||
return range_extents()
|
||||
start = sel.getRangeAt(0)
|
||||
end = sel.getRangeAt(sel.rangeCount - 1)
|
||||
return range_extents(start, end)
|
||||
|
||||
|
||||
def selection_extents_at_point(x, y):
|
||||
r = word_at_point(x, y)
|
||||
if r:
|
||||
sel = window.getSelection()
|
||||
sel.removeAllRanges()
|
||||
sel.addRange(r)
|
||||
return selection_extents(r, r)
|
||||
ans = range_extents()
|
||||
ans.start.y = ans.end.y = y
|
||||
ans.start.height = ans.end.height = parseInt(window.getComputedStyle(document.body).fontSize) + 4
|
||||
ans.start.x = x
|
||||
ans.end.x = x + ans.start.height * 3
|
||||
return ans
|
||||
|
@ -252,30 +252,6 @@ def sandboxed_html(html, style, sandbox):
|
||||
return ans
|
||||
|
||||
|
||||
def selection_extents():
|
||||
ans = {'start': {'x': None, 'y': None, 'height': None}, 'end': {'x': None, 'y': None, 'height': None}}
|
||||
sel = window.getSelection()
|
||||
if not sel or not sel.rangeCount:
|
||||
return ans
|
||||
start = sel.getRangeAt(0).cloneRange()
|
||||
end = sel.getRangeAt(sel.rangeCount - 1).cloneRange()
|
||||
start.collapse(True)
|
||||
end.collapse(False)
|
||||
|
||||
def for_boundary(r, ans):
|
||||
rects = r.getClientRects()
|
||||
if not rects.length:
|
||||
return
|
||||
rect = rects[0]
|
||||
ans.x = rect.left
|
||||
ans.y = rect.top
|
||||
ans.height = rect.bottom - rect.top
|
||||
|
||||
for_boundary(start, ans.start)
|
||||
for_boundary(end, ans.end)
|
||||
return ans
|
||||
|
||||
|
||||
if __name__ is '__main__':
|
||||
from pythonize import strings
|
||||
strings()
|
||||
|
Loading…
x
Reference in New Issue
Block a user