Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7465670

Browse filesBrowse files
committed
Simplify wx rubberband drawing.
Like for qt/gtk, it's much easier to just draw the rectangle at gui_repaint time. AFAICT this now works on Wayland too.
1 parent f9d2918 commit 7465670
Copy full SHA for 7465670

File tree

Expand file treeCollapse file tree

1 file changed

+29
-149
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+29
-149
lines changed

‎lib/matplotlib/backends/backend_wx.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_wx.py
+29-149Lines changed: 29 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ def __init__(self, parent, id, figure):
528528
# Create the drawing bitmap
529529
self.bitmap = wx.Bitmap(w, h)
530530
_log.debug("%s - __init__() - bitmap w:%d h:%d", type(self), w, h)
531-
# TODO: Add support for 'point' inspection and plot navigation.
532531
self._isDrawn = False
532+
self._rubberband_rect = None
533533

534534
self.Bind(wx.EVT_SIZE, self._onSize)
535535
self.Bind(wx.EVT_PAINT, self._onPaint)
@@ -628,20 +628,22 @@ def gui_repaint(self, drawDC=None, origin='WX'):
628628
_log.debug("%s - gui_repaint()", type(self))
629629
# The "if self" check avoids a "wrapped C/C++ object has been deleted"
630630
# RuntimeError if doing things after window is closed.
631-
if self and self.IsShownOnScreen():
632-
if not drawDC:
633-
# not called from OnPaint use a ClientDC
634-
drawDC = wx.ClientDC(self)
635-
636-
# following is for 'WX' backend on Windows
637-
# the bitmap can not be in use by another DC,
638-
# see GraphicsContextWx._cache
639-
if wx.Platform == '__WXMSW__' and origin == 'WX':
640-
img = self.bitmap.ConvertToImage()
641-
bmp = img.ConvertToBitmap()
642-
drawDC.DrawBitmap(bmp, 0, 0)
643-
else:
644-
drawDC.DrawBitmap(self.bitmap, 0, 0)
631+
if not (self and self.IsShownOnScreen()):
632+
return
633+
if not drawDC: # not called from OnPaint use a ClientDC
634+
drawDC = wx.ClientDC(self)
635+
# For 'WX' backend on Windows, the bitmap can not be in use by another
636+
# DC (see GraphicsContextWx._cache).
637+
bmp = (self.bitmap.ConvertToImage().ConvertToBitmap()
638+
if wx.Platform == '__WXMSW__' and origin == 'WX'
639+
else self.bitmap)
640+
drawDC.DrawBitmap(bmp, 0, 0)
641+
if self._rubberband_rect is not None:
642+
x0, y0, x1, y1 = self._rubberband_rect
643+
drawDC.DrawLineList(
644+
[(x0, y0, x1, y0), (x1, y0, x1, y1),
645+
(x0, y0, x0, y1), (x0, y1, x1, y1)],
646+
wx.Pen('BLACK', 1, wx.PENSTYLE_SHORT_DASH))
645647

646648
filetypes = {
647649
**FigureCanvasBase.filetypes,
@@ -1250,58 +1252,13 @@ def release_zoom(self, event):
12501252
self._zoomAxes = None
12511253

12521254
def draw_rubberband(self, event, x0, y0, x1, y1):
1253-
if self._retinaFix: # On Macs, use the following code
1254-
# wx.DCOverlay does not work properly on Retina displays.
1255-
rubberBandColor = '#C0C0FF'
1256-
if self._prevZoomRect:
1257-
self._prevZoomRect.pop(0).remove()
1258-
self.canvas.restore_region(self._savedRetinaImage)
1259-
X0, X1 = self._zoomStartX, event.xdata
1260-
Y0, Y1 = self._zoomStartY, event.ydata
1261-
lineX = (X0, X0, X1, X1, X0)
1262-
lineY = (Y0, Y1, Y1, Y0, Y0)
1263-
self._prevZoomRect = self._zoomAxes.plot(
1264-
lineX, lineY, '-', color=rubberBandColor)
1265-
self._zoomAxes.draw_artist(self._prevZoomRect[0])
1266-
self.canvas.blit(self._zoomAxes.bbox)
1267-
return
1268-
1269-
# Use an Overlay to draw a rubberband-like bounding box.
1270-
1271-
dc = wx.ClientDC(self.canvas)
1272-
odc = wx.DCOverlay(self._wxoverlay, dc)
1273-
odc.Clear()
1274-
1275-
# Mac's DC is already the same as a GCDC, and it causes
1276-
# problems with the overlay if we try to use an actual
1277-
# wx.GCDC so don't try it.
1278-
if 'wxMac' not in wx.PlatformInfo:
1279-
dc = wx.GCDC(dc)
1280-
12811255
height = self.canvas.figure.bbox.height
1282-
y1 = height - y1
1283-
y0 = height - y0
1284-
1285-
if y1 < y0:
1286-
y0, y1 = y1, y0
1287-
if x1 < x0:
1288-
x0, x1 = x1, x0
1289-
1290-
w = x1 - x0
1291-
h = y1 - y0
1292-
rect = wx.Rect(x0, y0, w, h)
1256+
self.canvas._rubberband_rect = (x0, height - y0, x1, height - y1)
1257+
self.canvas.Refresh()
12931258

1294-
rubberBandColor = '#C0C0FF' # or load from config?
1295-
1296-
# Set a pen for the border
1297-
color = wx.Colour(rubberBandColor)
1298-
dc.SetPen(wx.Pen(color, 1))
1299-
1300-
# use the same color, plus alpha for the brush
1301-
r, g, b, a = color.Get(True)
1302-
color.Set(r, g, b, 0x60)
1303-
dc.SetBrush(wx.Brush(color))
1304-
dc.DrawRectangle(rect)
1259+
def remove_rubberband(self):
1260+
self.canvas._rubberband_rect = None
1261+
self.canvas.Refresh()
13051262

13061263
def set_message(self, s):
13071264
if self._coordinates:
@@ -1449,91 +1406,14 @@ def set_cursor(self, cursor):
14491406
self._make_classic_style_pseudo_toolbar(), cursor)
14501407

14511408

1452-
if 'wxMac' not in wx.PlatformInfo:
1453-
# on most platforms, use overlay
1454-
class RubberbandWx(backend_tools.RubberbandBase):
1455-
def __init__(self, *args, **kwargs):
1456-
super().__init__(*args, **kwargs)
1457-
self._wxoverlay = None
1409+
class RubberbandWx(backend_tools.RubberbandBase):
1410+
def draw_rubberband(self, x0, y0, x1, y1):
1411+
NavigationToolbar2Wx.draw_rubberband(
1412+
self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
14581413

1459-
def draw_rubberband(self, x0, y0, x1, y1):
1460-
# Use an Overlay to draw a rubberband-like bounding box.
1461-
if self._wxoverlay is None:
1462-
self._wxoverlay = wx.Overlay()
1463-
dc = wx.ClientDC(self.canvas)
1464-
odc = wx.DCOverlay(self._wxoverlay, dc)
1465-
odc.Clear()
1466-
1467-
dc = wx.GCDC(dc)
1468-
1469-
height = self.canvas.figure.bbox.height
1470-
y1 = height - y1
1471-
y0 = height - y0
1472-
1473-
if y1 < y0:
1474-
y0, y1 = y1, y0
1475-
if x1 < x0:
1476-
x0, x1 = x1, x0
1477-
1478-
w = x1 - x0
1479-
h = y1 - y0
1480-
rect = wx.Rect(x0, y0, w, h)
1481-
1482-
rubberBandColor = '#C0C0FF' # or load from config?
1483-
1484-
# Set a pen for the border
1485-
color = wx.Colour(rubberBandColor)
1486-
dc.SetPen(wx.Pen(color, 1))
1487-
1488-
# use the same color, plus alpha for the brush
1489-
r, g, b, a = color.Get(True)
1490-
color.Set(r, g, b, 0x60)
1491-
dc.SetBrush(wx.Brush(color))
1492-
dc.DrawRectangle(rect)
1493-
1494-
def remove_rubberband(self):
1495-
if self._wxoverlay is None:
1496-
return
1497-
self._wxoverlay.Reset()
1498-
self._wxoverlay = None
1499-
1500-
else:
1501-
# on Mac OS retina displays DCOverlay does not work
1502-
# and dc.SetLogicalFunction does not have an effect on any display
1503-
# the workaround is to blit the full image for remove_rubberband
1504-
class RubberbandWx(backend_tools.RubberbandBase):
1505-
def __init__(self, *args, **kwargs):
1506-
super().__init__(*args, **kwargs)
1507-
self._rect = None
1508-
1509-
def draw_rubberband(self, x0, y0, x1, y1):
1510-
dc = wx.ClientDC(self.canvas)
1511-
# this would be required if the Canvas is a ScrolledWindow,
1512-
# which is not the case for now
1513-
# self.PrepareDC(dc)
1514-
1515-
# delete old rubberband
1516-
if self._rect:
1517-
self.remove_rubberband(dc)
1518-
1519-
# draw new rubberband
1520-
dc.SetPen(wx.Pen(wx.BLACK, 1, wx.SOLID))
1521-
dc.SetBrush(wx.TRANSPARENT_BRUSH)
1522-
self._rect = (x0, self.canvas._height-y0, x1-x0, -y1+y0)
1523-
dc.DrawRectangle(self._rect)
1524-
1525-
def remove_rubberband(self, dc=None):
1526-
if not self._rect:
1527-
return
1528-
if self.canvas.bitmap:
1529-
if dc is None:
1530-
dc = wx.ClientDC(self.canvas)
1531-
dc.DrawBitmap(self.canvas.bitmap, 0, 0)
1532-
# for testing the method on Windows, use this code instead:
1533-
# img = self.canvas.bitmap.ConvertToImage()
1534-
# bmp = img.ConvertToBitmap()
1535-
# dc.DrawBitmap(bmp, 0, 0)
1536-
self._rect = None
1414+
def remove_rubberband(self):
1415+
NavigationToolbar2Wx.remove_rubberband(
1416+
self._make_classic_style_pseudo_toolbar())
15371417

15381418

15391419
class _HelpDialog(wx.Dialog):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.