-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdialog.py
114 lines (94 loc) · 3.9 KB
/
dialog.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from browser import console, document, html, window
class Dialog(html.DIV):
"""Basic, moveable dialog box with a title bar, optional
"Ok" / "Cancel" buttons.
The "Ok" button is the attribute "ok_button" of the dialog object.
Supports drag and drop on the document.
A dialog has an attribute "panel" that can contain elements.
Method close() removes the dialog box.
"""
def __init__(self, title="", top=None, left=None, ok_cancel=False):
html.DIV.__init__(self, Class="dialog")
self._title = html.DIV(html.SPAN(title), Class="dialog-title")
self <= self._title
btn = html.SPAN("×", Class="dialog-close")
self._title <= btn
btn.bind("click", self.remove)
self.panel = html.DIV(Class="dialog-panel")
self <= self.panel
if ok_cancel:
ok_cancel_zone = html.DIV(style={"text-align": "center"})
self.ok_button = html.BUTTON("Ok")
self.cancel_button = html.BUTTON("Cancel")
self.cancel_button.bind("click", self.remove)
ok_cancel_zone <= self.ok_button + self.cancel_button
self <= ok_cancel_zone
document <= self
cstyle = window.getComputedStyle(self)
# Center horizontally and vertically
if left is None:
width = round(float(cstyle.width[:-2]))
left = int((window.innerWidth - width) / 2)
self.left = left
self.style.left = f'{left}px'
if top is None:
height = round(float(cstyle.height[:-2]))
top = int((window.innerHeight - height) / 2)
self.top = top
self.style.top = f'{top}px'
self._title.bind("mousedown", self.mousedown)
document.bind("mousemove", self.mousemove)
self._title.bind("mouseup", self.mouseup)
self.is_moving = False
def mousedown(self, event):
self.is_moving = True
self.offset = [self.left - event.x, self.top - event.y]
# prevent default behaviour to avoid selecting the moving element
event.preventDefault()
def mousemove(self, event):
if not self.is_moving:
return
# set new moving element coordinates
self.left = self.offset[0] + event.x
self.top = self.offset[1] + event.y
def mouseup(self, event):
self.is_moving = False
class EntryDialog(Dialog):
"""Dialog box with "Ok / Cancel" buttons and an INPUT element.
When the user clicks on "Ok" or hits the Enter key, an event called
"entry" is triggered on the element.
Usage:
box = EntryDialog()
@bind(box, "entry")
def entry(evt):
...
"""
def __init__(self, title="", message="", top=None, left=None):
Dialog.__init__(self, title, top, left, ok_cancel=True)
if message:
self.panel <= message
self.entry = html.INPUT()
self.panel <= html.BR() + self.entry
self.entry.focus()
self.entry.bind("keypress", self.callback)
self.ok_button.bind("click", self.callback)
@property
def value(self):
return self.entry.value
def callback(self, evt):
if evt.target == self.entry and evt.keyCode != 13:
return
self.dispatchEvent(window.Event.new("entry"))
class InfoDialog(Dialog):
"""Dialog box with an information message and no "Ok / Cancel" button."""
def __init__(self, title="", message="", top=None, left=None,
remove_after=None):
"""If remove_after is set, number of seconds after which the dialog is
removed."""
Dialog.__init__(self, title, top, left)
self.panel <= message
if remove_after:
if not isinstance(remove_after, (int, float)):
raise TypeError("remove_after should be a number, not " +
str(remove_after.__class__.__name__))
window.setTimeout(self.remove, remove_after * 1000)