mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on completion popups
This commit is contained in:
parent
f3b17074e9
commit
bdaa808886
@ -12,6 +12,7 @@ from book_list.prefs import PrefsPanel
|
||||
from book_list.book_details import BookDetailsPanel
|
||||
from gettext import gettext as _
|
||||
from modals import error_dialog, ajax_progress_dialog
|
||||
from popups import install_event_filters
|
||||
|
||||
class BarState:
|
||||
|
||||
@ -88,6 +89,7 @@ class UI:
|
||||
ROOT_PANEL = 'books'
|
||||
|
||||
def __init__(self, interface_data, book_list_container):
|
||||
install_event_filters()
|
||||
self.top_bar = TopBar(book_list_container)
|
||||
self.books_view = BooksView(interface_data, book_list_container)
|
||||
self.items_view = ItemsView(interface_data, book_list_container)
|
||||
|
@ -91,3 +91,14 @@ def element(elem_id, child_selector):
|
||||
if child_selector:
|
||||
ans = ans.querySelector(child_selector)
|
||||
return ans
|
||||
|
||||
auto_id_count = 0
|
||||
|
||||
def ensure_id(w):
|
||||
nonlocal auto_id_count
|
||||
ans = w.getAttribute('id')
|
||||
if not ans:
|
||||
auto_id_count += 1
|
||||
ans = 'auto-id-' + auto_id_count
|
||||
w.setAttribute('id', ans)
|
||||
return ans
|
||||
|
@ -7,6 +7,7 @@ from elementmaker import E
|
||||
from dom import set_css, clear, build_rule, svgicon
|
||||
from gettext import gettext as _
|
||||
from book_list.theme import get_color, get_font_size
|
||||
from popups import MODAL_Z_INDEX
|
||||
|
||||
modal_container = None
|
||||
modal_count = 0
|
||||
@ -43,7 +44,7 @@ class ModalContainer:
|
||||
# Container style
|
||||
set_css(div,
|
||||
position='fixed', top='0', right='0', bottom='0', left='0', # Stretch over entire window
|
||||
background_color='rgba(0,0,0,0.8)', z_index='1000',
|
||||
background_color='rgba(0,0,0,0.8)', z_index=MODAL_Z_INDEX + '',
|
||||
display='none', text_align='center', user_select='none'
|
||||
)
|
||||
|
||||
|
109
src/pyj/popups.pyj
Normal file
109
src/pyj/popups.pyj
Normal file
@ -0,0 +1,109 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import hash_literals, bound_methods
|
||||
|
||||
from dom import set_css, ensure_id
|
||||
from elementmaker import E
|
||||
|
||||
MODAL_Z_INDEX = 1000
|
||||
POPUP_Z_INDEX = MODAL_Z_INDEX + 1
|
||||
popup_count = 0
|
||||
|
||||
shown_popups = set()
|
||||
associated_widgets = {}
|
||||
|
||||
def element_contains_click_event(element, event):
|
||||
r = element.getBoundingClientRect()
|
||||
return r.left <= event.clientX <= r.right and r.top <= event.clientY <= r.bottom
|
||||
|
||||
def check_for_open_popups(event):
|
||||
if not shown_popups.length:
|
||||
return False
|
||||
for popup_id in shown_popups:
|
||||
popup = document.getElementById(popup_id)
|
||||
if element_contains_click_event(popup, event):
|
||||
return False
|
||||
w = associated_widgets[popup_id]
|
||||
if w and w.length:
|
||||
for wid in w:
|
||||
widget = document.getElementById(wid)
|
||||
if element_contains_click_event(widget, event):
|
||||
return False
|
||||
return True
|
||||
|
||||
def filter_clicks(event):
|
||||
if check_for_open_popups(event):
|
||||
event.stopPropagation(), event.preventDefault()
|
||||
for popup in list(shown_popups):
|
||||
hide_popup(popup.getAttribute('id'))
|
||||
|
||||
def install_event_filters():
|
||||
window.addEventListener('click', filter_clicks, True)
|
||||
|
||||
def create_popup(parent, idprefix):
|
||||
nonlocal popup_count
|
||||
popup_count += 1
|
||||
pid = (idprefix or 'popup') + '-' + popup_count
|
||||
div = E.div(id=pid, style='display: none; position: absolute; z-index: {}'.format(POPUP_Z_INDEX))
|
||||
parent = parent or document.body
|
||||
parent.appendChild(div)
|
||||
return pid
|
||||
|
||||
def show_popup(popup_id, *associated_widget_ids):
|
||||
elem = document.getElementById(popup_id)
|
||||
elem.style.display = 'block'
|
||||
shown_popups.add(popup_id)
|
||||
associated_widgets[popup_id] = set()
|
||||
for aid in associated_widget_ids:
|
||||
associated_widgets[popup_id].add(aid)
|
||||
|
||||
def hide_popup(popup_id):
|
||||
elem = document.getElementById(popup_id)
|
||||
elem.style.display = 'none'
|
||||
shown_popups.discard(popup_id)
|
||||
v'delete associated_widgets[popup_id]'
|
||||
|
||||
class CompletionPopup:
|
||||
|
||||
def __init__(self, parent=None, max_items=25):
|
||||
self.max_items = max_items
|
||||
self.container_id = create_popup(parent)
|
||||
self.items = []
|
||||
c = self.container
|
||||
set_css(c, user_select='none')
|
||||
self.associated_widget_ids = set()
|
||||
self.current_query, self.is_upwards = '', False
|
||||
|
||||
@property
|
||||
def container(self):
|
||||
return document.getElementById(self.container_id)
|
||||
|
||||
@property
|
||||
def is_visible(self):
|
||||
return self.container.style.display is not 'none'
|
||||
|
||||
def set_all_items(self, items):
|
||||
self.items = items
|
||||
|
||||
def add_associated_widget(self, widget_or_id):
|
||||
if type(widget_or_id) is not 'string':
|
||||
widget_or_id = ensure_id(widget_or_id)
|
||||
self.associated_widget_ids.add(widget_or_id)
|
||||
|
||||
def show_at_widget(self, w):
|
||||
br = w.getBoundingClientRect()
|
||||
if br.top > window.innerHeight - br.bottom:
|
||||
y, upwards = br.top, True
|
||||
else:
|
||||
y, upwards = br.bottom, False
|
||||
self.show_at(br.left, y, br.width, upwards)
|
||||
|
||||
def show_at(self, x, y, width, upwards):
|
||||
self.is_upwards = upwards
|
||||
c = self.container
|
||||
cs = c.style
|
||||
cs.left = x + 'px'
|
||||
cs.top = 'auto' if upwards else y + 'px'
|
||||
cs.bottom = y + 'px' if upwards else 'auto'
|
||||
cs.width = width + 'px'
|
||||
show_popup(self.container_id, *self.associated_widget_ids)
|
Loading…
x
Reference in New Issue
Block a user