8000 Merge remote-tracking branch 'matplotlib/master' · matplotlib/matplotlib@4c4852d · GitHub
[go: up one dir, main page]

Skip to content

Commit 4c4852d

Browse files
committed
Merge remote-tracking branch 'matplotlib/master'
2 parents dab776c + 512b5d7 commit 4c4852d

File tree

5 files changed

+695
-580
lines changed

5 files changed

+695
-580
lines changed

lib/matplotlib/backends/backend_nbagg.py

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
import tornado.ioloop
1515

1616
from IPython.display import display, Javascript, HTML
17-
from IPython.kernel.comm import Comm
17+
try:
18+
# Jupyter/IPython 4.x or later
19+
from ipykernel.comm import Comm
20+
except ImportError:
21+
# Jupyter/IPython 3.x or earlier
22+
from IPython.kernel.comm import Comm
1823

1924
from matplotlib import rcParams
2025
from matplotlib.figure import Figure
@@ -73,9 +78,10 @@ def connection_info():
7378
for manager in Gcf.get_all_fig_managers():
7479
fig = manager.canvas.figure
7580
result.append('{0} - {0}'.format((fig.get_label() or
76-
"Figure {0}".format(manager.num)),
77-
manager.web_sockets))
78-
result.append('Figures pending show: {0}'.format(len(Gcf._activeQue)))
81+
"Figure {0}".format(manager.num)),
82+
manager.web_sockets))
83+
if not is_interactive():
84+
result.append('Figures pending show: {0}'.format(len(Gcf._activeQue)))
7985
return '\n'.join(result)
8086

8187

@@ -161,13 +167,22 @@ def _create_comm(self):
161167

162168
def destroy(self):
163169
self._send_event('close')
164-
for comm in self.web_sockets.copy():
170+
# need to copy comms as callbacks will modify this list
171+
for comm in list(self.web_sockets):
165172
comm.on_close()
173+
self.clearup_closed()
166174

167175
def clearup_closed(self):
168176
"""Clear up any closed Comms."""
169177
self.web_sockets = set([socket for socket in self.web_sockets
170-
if not socket.is_open()])
178+
if socket.is_open()])
179+
180+
if len(self.web_sockets) == 0:
181+
self.canvas.close_event()
182+
183+
def remove_comm(self, comm_id):
184+
self.web_sockets = set([socket for socket in self.web_sockets
185+
if not socket.comm.comm_id == comm_id])
171186

172187

173188
class TimerTornado(TimerBase):
@@ -226,13 +241,22 @@ def new_figure_manager_given_figure(num, figure):
226241
"""
227242
Create a new figure manager instance for the given figure.
228243
"""
244+
from .._pylab_helpers import Gcf
245+
246+
def closer(event):
247+
Gcf.destroy(num)
248+
229249
canvas = FigureCanvasNbAgg(figure)
230250
if rcParams['nbagg.transparent']:
231251
figure.patch.set_alpha(0)
232252
manager = FigureManagerNbAgg(canvas, num)
253+
233254
if is_interactive():
234255
manager.show()
235256
figure.canvas.draw_idle()
257+
258+
canvas.mpl_connect('close_event', closer)
259+
236260
return manager
237261

238262

@@ -261,16 +285,27 @@ def __init__(self, manager):
261285
self.comm.on_msg(self.on_message)
262286

263287
manager = self.manager
264-
self.comm.on_close(lambda close_message: manager.clearup_closed())
288+
self._ext_close = False
289+
290+
def _on_close(close_message):
291+
self._ext_close = True
292+
manager.remove_comm(close_message['content']['comm_id'])
293+
manager.clearup_closed()
294+
295+
self.comm.on_close(_on_close)
265296

266297
def is_open(self):
267-
return not self.comm._closed
298+
return not (self._ext_close or self.comm._closed)
268299

269300
def on_close(self):
270301
# When the socket is closed, deregister the websocket with
271302
# the FigureManager.
272-
self.comm.close()
273-
self.manager.clearup_closed()
303+
if self.is_open():
304+
try:
305+
self.comm.close()
306+
except KeyError:
307+
# apparently already cleaned it up?
308+
pass
274309

275310
def send_json(self, content):
276311
self.comm.send({'data': json.dumps(content)})
@@ -293,6 +328,7 @@ def on_message(self, message):
293328
message = json.loads(message['content']['data'])
294329
if message['type'] == 'closing':
295330
self.on_close()
331+
self.manager.clearup_closed()
296332
elif message['type'] == 'supports_binary':
297333
self.supports_binary = message['value']
298334
else:

lib/matplotlib/backends/backend_qt5agg.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ def blit(self, bbox=None):
153153
"""
154154
Blit the region in bbox
155155
"""
156+
# If bbox is None, blit the entire canvas. Otherwise
157+
# blit only the area defined by the bbox.
158+
if bbox is None and self.figure:
159+
bbox = self.figure.bbox
160+
156161
self.blitbox = bbox
157162
l, b, w, h = bbox.bounds
158163
t = b + h

lib/matplotlib/backends/backend_webagg_core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ def handle_event(self, event):
329329
self.send_event('figure_label', label=figure_label)
330330
self._force_full = True
331331
self.draw_idle()
332+
332333
else:
333334
handler = getattr(self, 'handle_{0}'.format(e_type), None)
334335
if handler is None:

lib/matplotlib/backends/web_backend/nbagg_mpl.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,21 @@ mpl.mpl_figure_comm = function(comm, msg) {
5555
};
5656

5757
mpl.figure.prototype.handle_close = function(fig, msg) {
58+
fig.root.unbind('remove')
59+
5860
// Update the output cell to use the data from the current canvas.
5961
fig.push_to_output();
6062
var dataURL = fig.canvas.toDataURL();
6163
// Re-enable the keyboard manager in IPython - without this line, in FF,
6264
// the notebook keyboard shortcuts fail.
6365
IPython.keyboard_manager.enable()
6466
$(fig.parent_element).html('<img src="' + dataURL + '">');
65-
fig.send_message('closing', {});
66-
fig.ws.close()
67+
fig.close_ws(fig, msg);
68+
}
69+
70+
mpl.figure.prototype.close_ws = function(fig, msg){
71+
fig.send_message('closing', msg);
72+
// fig.ws.close()
6773
}
6874

6975
mpl.figure.prototype.push_to_output = function(remove_interactive) {
@@ -126,6 +132,12 @@ mpl.figure.prototype._init_toolbar = function() {
126132
titlebar.prepend(buttongrp);
127133
}
128134

135+
mpl.figure.prototype._root_extra_style = function(el){
136+
var fig = this
137+
el.on("remove", function(){
138+
fig.close_ws(fig, {});
139+
});
140+
}
129141

130142
mpl.figure.prototype._canvas_extra_style = function(el){
131143
// this is important to make the div 'focusable

0 commit comments

Comments
 (0)
0