Commit b2b44bbce25c29014365a92693b5eead20f29975

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent 535a568f
Exists in master

Mac M1 HighDPI display (#421)

* Doing some tests

* Drawing texts on canvas scaled by GetContentScaleFactor

* Created a method to get mouse position

* Using GetMousePosition() on slice editor

* Using GetMousePosition() on watershed style

* Using GetMousePosition() on image reorientation

* Using GetMousePosition() on mask filling

* Using GetMousePosition() on mask crop

* Using GetMousePosition() on cross

* Using GetMousePosition() on WW&WL

* Using GetMousePosition() on mouse scroll

* Using GetMousePosition() on region growing

* Using GetMousePosition() on editor

* created a method to get vtk mouse position on viewer slice

* using get_vtk_mouse_position on canvas renderer

* using get_vtk_mouse_position on slice styles

* Removed unneed prints

* Using WX to get Mouse position on vtk renderer

* Using get_vtk_mouse_position on viewer_volume

* Added a comment to explain the problem with highdpi display on mac

* Scalling WW&WL text on ViewerVolume
invesalius/data/styles.py
... ... @@ -77,6 +77,8 @@ WATERSHED_OPERATIONS = {_("Erase"): BRUSH_ERASE,
77 77  
78 78 class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage):
79 79 def __init__(self, viewer):
  80 + self.viewer = viewer
  81 +
80 82 self.right_pressed = False
81 83 self.left_pressed = False
82 84 self.middle_pressed = False
... ... @@ -110,6 +112,22 @@ class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage):
110 112 def OnMiddleButtonReleaseEvent(self, evt, obj):
111 113 self.middle_pressed = False
112 114  
  115 + def GetMousePosition(self):
  116 + mx, my = self.viewer.get_vtk_mouse_position()
  117 + return mx, my
  118 +
  119 + def GetPickPosition(self, mouse_position=None):
  120 + if mouse_position is None:
  121 + mx, my = self.GetMousePosition()
  122 + else:
  123 + mx, my = mouse_position
  124 + iren = self.viewer.interactor
  125 + render = iren.FindPokedRenderer(mx, my)
  126 + self.picker.Pick(mx, my, 0, render)
  127 + x, y, z = self.picker.GetPickPosition()
  128 + return (x, y, z)
  129 +
  130 +
113 131  
114 132 class DefaultInteractorStyle(BaseImageInteractorStyle):
115 133 """
... ... @@ -277,7 +295,7 @@ class BaseImageEditionInteractorStyle(DefaultInteractorStyle):
277 295  
278 296 viewer._set_editor_cursor_visibility(1)
279 297  
280   - mouse_x, mouse_y = iren.GetEventPosition()
  298 + mouse_x, mouse_y = self.GetMousePosition()
281 299 render = iren.FindPokedRenderer(mouse_x, mouse_y)
282 300 slice_data = viewer.get_slice_data(render)
283 301  
... ... @@ -316,7 +334,7 @@ class BaseImageEditionInteractorStyle(DefaultInteractorStyle):
316 334  
317 335 viewer._set_editor_cursor_visibility(1)
318 336  
319   - mouse_x, mouse_y = iren.GetEventPosition()
  337 + mouse_x, mouse_y = self.GetMousePosition()
320 338 render = iren.FindPokedRenderer(mouse_x, mouse_y)
321 339 slice_data = viewer.get_slice_data(render)
322 340 operation = self.config.operation
... ... @@ -486,7 +504,7 @@ class CrossInteractorStyle(DefaultInteractorStyle):
486 504 self.ChangeCrossPosition(iren)
487 505  
488 506 def ChangeCrossPosition(self, iren):
489   - mouse_x, mouse_y = iren.GetEventPosition()
  507 + mouse_x, mouse_y = self.GetMousePosition()
490 508 x, y, z = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker)
491 509 self.viewer.UpdateSlicesPosition([x, y, z])
492 510 # This "Set cross" message is needed to update the cross in the other slices
... ... @@ -626,7 +644,7 @@ class WWWLInteractorStyle(DefaultInteractorStyle):
626 644 def OnWindowLevelMove(self, obj, evt):
627 645 if (self.left_pressed):
628 646 iren = obj.GetInteractor()
629   - mouse_x, mouse_y = iren.GetEventPosition()
  647 + mouse_x, mouse_y = self.GetMousePosition()
630 648 self.acum_achange_window += mouse_x - self.last_x
631 649 self.acum_achange_level += mouse_y - self.last_y
632 650 self.last_x, self.last_y = mouse_x, mouse_y
... ... @@ -713,7 +731,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
713 731 def OnInsertMeasurePoint(self, obj, evt):
714 732 slice_number = self.slice_data.number
715 733 x, y, z = self._get_pos_clicked()
716   - mx, my = self.viewer.interactor.GetEventPosition()
  734 + mx, my = self.GetMousePosition()
717 735  
718 736 if self.selected:
719 737 self.selected = None
... ... @@ -784,7 +802,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
784 802 self.viewer.UpdateCanvas()
785 803  
786 804 else:
787   - mx, my = self.viewer.interactor.GetEventPosition()
  805 + mx, my = self.GetMousePosition()
788 806 if self._verify_clicked_display(mx, my):
789 807 self.viewer.interactor.SetCursor(wx.Cursor(wx.CURSOR_HAND))
790 808 else:
... ... @@ -801,12 +819,8 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
801 819 self.viewer.scroll_enabled = True
802 820  
803 821 def _get_pos_clicked(self):
804   - iren = self.viewer.interactor
805   - mx,my = iren.GetEventPosition()
806   - render = iren.FindPokedRenderer(mx, my)
807 822 self.picker.AddPickList(self.slice_data.actor)
808   - self.picker.Pick(mx, my, 0, render)
809   - x, y, z = self.picker.GetPickPosition()
  823 + x, y, z = self.GetPickPosition()
810 824 self.picker.DeletePickList(self.slice_data.actor)
811 825 return (x, y, z)
812 826  
... ... @@ -919,11 +933,11 @@ class DensityMeasureStyle(DefaultInteractorStyle):
919 933  
920 934 def _pick_position(self):
921 935 iren = self.viewer.interactor
922   - mx, my = iren.GetEventPosition()
  936 + mx, my = self.GetMousePosition()
923 937 return (mx, my)
924 938  
925 939 def _get_pos_clicked(self):
926   - mouse_x, mouse_y = self._pick_position()
  940 + mouse_x, mouse_y = self.GetMousePosition()
927 941 position = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker)
928 942 return position
929 943  
... ... @@ -1232,15 +1246,14 @@ class EditorInteractorStyle(DefaultInteractorStyle):
1232 1246 self.viewer.slice_data.cursor.Show(0)
1233 1247  
1234 1248 def SetUp(self):
1235   -
1236 1249 x, y = self.viewer.interactor.ScreenToClient(wx.GetMousePosition())
1237 1250 if self.viewer.interactor.HitTest((x, y)) == wx.HT_WINDOW_INSIDE:
1238 1251 self.viewer.slice_data.cursor.Show()
1239   -
  1252 +
1240 1253 y = self.viewer.interactor.GetSize()[1] - y
1241 1254 w_x, w_y, w_z = self.viewer.get_coordinate_cursor(x, y, self.picker)
1242 1255 self.viewer.slice_data.cursor.SetPosition((w_x, w_y, w_z))
1243   -
  1256 +
1244 1257 self.viewer.interactor.SetCursor(wx.Cursor(wx.CURSOR_BLANK))
1245 1258 self.viewer.interactor.Render()
1246 1259  
... ... @@ -1319,7 +1332,7 @@ class EditorInteractorStyle(DefaultInteractorStyle):
1319 1332  
1320 1333 viewer._set_editor_cursor_visibility(1)
1321 1334  
1322   - mouse_x, mouse_y = iren.GetEventPosition()
  1335 + mouse_x, mouse_y = self.GetMousePosition()
1323 1336 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1324 1337 slice_data = viewer.get_slice_data(render)
1325 1338  
... ... @@ -1351,7 +1364,7 @@ class EditorInteractorStyle(DefaultInteractorStyle):
1351 1364  
1352 1365 viewer._set_editor_cursor_visibility(1)
1353 1366  
1354   - mouse_x, mouse_y = iren.GetEventPosition()
  1367 + mouse_x, mouse_y = self.GetMousePosition()
1355 1368 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1356 1369 slice_data = viewer.get_slice_data(render)
1357 1370  
... ... @@ -1402,7 +1415,7 @@ class EditorInteractorStyle(DefaultInteractorStyle):
1402 1415 iren = self.viewer.interactor
1403 1416 viewer = self.viewer
1404 1417 if iren.GetControlKey():
1405   - mouse_x, mouse_y = iren.GetEventPosition()
  1418 + mouse_x, mouse_y = self.GetMousePosition()
1406 1419 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1407 1420 slice_data = self.viewer.get_slice_data(render)
1408 1421 cursor = slice_data.cursor
... ... @@ -1420,7 +1433,7 @@ class EditorInteractorStyle(DefaultInteractorStyle):
1420 1433 iren = self.viewer.interactor
1421 1434 viewer = self.viewer
1422 1435 if iren.GetControlKey():
1423   - mouse_x, mouse_y = iren.GetEventPosition()
  1436 + mouse_x, mouse_y = self.GetMousePosition()
1424 1437 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1425 1438 slice_data = self.viewer.get_slice_data(render)
1426 1439 cursor = slice_data.cursor
... ... @@ -1545,11 +1558,11 @@ class WaterShedInteractorStyle(DefaultInteractorStyle):
1545 1558 x, y = self.viewer.interactor.ScreenToClient(wx.GetMousePosition())
1546 1559 if self.viewer.interactor.HitTest((x, y)) == wx.HT_WINDOW_INSIDE:
1547 1560 self.viewer.slice_data.cursor.Show()
1548   -
  1561 +
1549 1562 y = self.viewer.interactor.GetSize()[1] - y
1550 1563 w_x, w_y, w_z = self.viewer.get_coordinate_cursor(x, y, self.picker)
1551 1564 self.viewer.slice_data.cursor.SetPosition((w_x, w_y, w_z))
1552   -
  1565 +
1553 1566 self.viewer.interactor.SetCursor(wx.Cursor(wx.CURSOR_BLANK))
1554 1567 self.viewer.interactor.Render()
1555 1568  
... ... @@ -1622,7 +1635,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle):
1622 1635 iren = self.viewer.interactor
1623 1636 viewer = self.viewer
1624 1637 if iren.GetControlKey():
1625   - mouse_x, mouse_y = iren.GetEventPosition()
  1638 + mouse_x, mouse_y = self.GetMousePosition()
1626 1639 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1627 1640 slice_data = self.viewer.get_slice_data(render)
1628 1641 cursor = slice_data.cursor
... ... @@ -1640,7 +1653,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle):
1640 1653 iren = self.viewer.interactor
1641 1654 viewer = self.viewer
1642 1655 if iren.GetControlKey():
1643   - mouse_x, mouse_y = iren.GetEventPosition()
  1656 + mouse_x, mouse_y = self.GetMousePosition()
1644 1657 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1645 1658 slice_data = self.viewer.get_slice_data(render)
1646 1659 cursor = slice_data.cursor
... ... @@ -1663,7 +1676,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle):
1663 1676  
1664 1677 viewer._set_editor_cursor_visibility(1)
1665 1678  
1666   - mouse_x, mouse_y = iren.GetEventPosition()
  1679 + mouse_x, mouse_y = self.GetMousePosition()
1667 1680 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1668 1681 slice_data = viewer.get_slice_data(render)
1669 1682  
... ... @@ -1710,7 +1723,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle):
1710 1723  
1711 1724 viewer._set_editor_cursor_visibility(1)
1712 1725  
1713   - mouse_x, mouse_y = iren.GetEventPosition()
  1726 + mouse_x, mouse_y = self.GetMousePosition()
1714 1727 render = iren.FindPokedRenderer(mouse_x, mouse_y)
1715 1728 slice_data = viewer.get_slice_data(render)
1716 1729  
... ... @@ -2033,7 +2046,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
2033 2046 if self._over_center:
2034 2047 self.dragging = True
2035 2048 else:
2036   - x, y = self.viewer.interactor.GetEventPosition()
  2049 + x, y = self.GetMousePosition()
2037 2050 w, h = self.viewer.interactor.GetSize()
2038 2051  
2039 2052 self.picker.Pick(h/2.0, w/2.0, 0, self.viewer.slice_data.renderer)
... ... @@ -2063,7 +2076,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
2063 2076 else:
2064 2077 # Getting mouse position
2065 2078 iren = self.viewer.interactor
2066   - mx, my = iren.GetEventPosition()
  2079 + mx, my = self.GetMousePosition()
2067 2080  
2068 2081 # Getting center value
2069 2082 center = self.viewer.slice_.center
... ... @@ -2109,7 +2122,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
2109 2122  
2110 2123 def _move_center_rot(self):
2111 2124 iren = self.viewer.interactor
2112   - mx, my = iren.GetEventPosition()
  2125 + mx, my = self.GetMousePosition()
2113 2126  
2114 2127 icx, icy, icz = self.viewer.slice_.center
2115 2128  
... ... @@ -2131,7 +2144,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
2131 2144 def _rotate(self):
2132 2145 # Getting mouse position
2133 2146 iren = self.viewer.interactor
2134   - mx, my = iren.GetEventPosition()
  2147 + mx, my = self.GetMousePosition()
2135 2148  
2136 2149 cx, cy, cz = self.viewer.slice_.center
2137 2150  
... ... @@ -2294,7 +2307,7 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
2294 2307  
2295 2308 viewer = self.viewer
2296 2309 iren = viewer.interactor
2297   - mouse_x, mouse_y = iren.GetEventPosition()
  2310 + mouse_x, mouse_y = self.GetMousePosition()
2298 2311 x, y, z = self.viewer.get_voxel_coord_by_screen_pos(mouse_x, mouse_y, self.picker)
2299 2312  
2300 2313 mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:]
... ... @@ -2401,14 +2414,12 @@ class CropMaskInteractorStyle(DefaultInteractorStyle):
2401 2414 Publisher.subscribe(self.CropMask, "Crop mask")
2402 2415  
2403 2416 def OnMove(self, obj, evt):
2404   - iren = self.viewer.interactor
2405   - x, y = iren.GetEventPosition()
  2417 + x, y = self.GetMousePosition()
2406 2418 self.draw_retangle.MouseMove(x,y)
2407 2419  
2408 2420 def OnLeftPressed(self, obj, evt):
2409 2421 self.draw_retangle.mouse_pressed = True
2410   - iren = self.viewer.interactor
2411   - x, y = iren.GetEventPosition()
  2422 + x, y = self.GetMousePosition()
2412 2423 self.draw_retangle.LeftPressed(x,y)
2413 2424  
2414 2425 def OnReleaseLeftButton(self, obj, evt):
... ... @@ -2416,13 +2427,12 @@ class CropMaskInteractorStyle(DefaultInteractorStyle):
2416 2427 self.draw_retangle.ReleaseLeft()
2417 2428  
2418 2429 def SetUp(self):
2419   -
2420 2430 self.draw_retangle = geom.DrawCrop2DRetangle()
2421 2431 self.draw_retangle.SetViewer(self.viewer)
2422 2432  
2423 2433 self.viewer.canvas.draw_list.append(self.draw_retangle)
2424 2434 self.viewer.UpdateCanvas()
2425   -
  2435 +
2426 2436 if not(self.config.dlg_visible):
2427 2437 self.config.dlg_visible = True
2428 2438  
... ... @@ -2550,7 +2560,7 @@ class SelectMaskPartsInteractorStyle(DefaultInteractorStyle):
2550 2560 return
2551 2561  
2552 2562 iren = self.viewer.interactor
2553   - mouse_x, mouse_y = iren.GetEventPosition()
  2563 + mouse_x, mouse_y = self.GetMousePosition()
2554 2564 x, y, z = self.viewer.get_voxel_coord_by_screen_pos(mouse_x, mouse_y, self.picker)
2555 2565  
2556 2566 mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:]
... ... @@ -2670,7 +2680,7 @@ class FloodFillSegmentInteractorStyle(DefaultInteractorStyle):
2670 2680 def do_2d_seg(self):
2671 2681 viewer = self.viewer
2672 2682 iren = viewer.interactor
2673   - mouse_x, mouse_y = iren.GetEventPosition()
  2683 + mouse_x, mouse_y = self.GetMousePosition()
2674 2684 x, y = self.viewer.get_slice_pixel_coord_by_screen_pos(mouse_x, mouse_y, self.picker)
2675 2685  
2676 2686 mask = self.viewer.slice_.buffer_slices[self.orientation].mask.copy()
... ... @@ -2736,7 +2746,7 @@ class FloodFillSegmentInteractorStyle(DefaultInteractorStyle):
2736 2746 def do_3d_seg(self):
2737 2747 viewer = self.viewer
2738 2748 iren = viewer.interactor
2739   - mouse_x, mouse_y = iren.GetEventPosition()
  2749 + mouse_x, mouse_y = self.GetMousePosition()
2740 2750 x, y, z = self.viewer.get_voxel_coord_by_screen_pos(mouse_x, mouse_y, self.picker)
2741 2751  
2742 2752 mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:]
... ...
invesalius/data/styles_3d.py
... ... @@ -300,8 +300,7 @@ class WWWLInteractorStyle(DefaultInteractorStyle):
300 300  
301 301 def OnWindowLevelMove(self, obj, evt):
302 302 if self.changing_wwwl:
303   - iren = obj.GetInteractor()
304   - mouse_x, mouse_y = iren.GetEventPosition()
  303 + mouse_x, mouse_y = self.viewer.get_vtk_mouse_position()
305 304 diff_x = mouse_x - self.last_x
306 305 diff_y = mouse_y - self.last_y
307 306 self.last_x, self.last_y = mouse_x, mouse_y
... ... @@ -311,8 +310,7 @@ class WWWLInteractorStyle(DefaultInteractorStyle):
311 310 Publisher.sendMessage('Render volume viewer')
312 311  
313 312 def OnWindowLevelClick(self, obj, evt):
314   - iren = obj.GetInteractor()
315   - self.last_x, self.last_y = iren.GetLastEventPosition()
  313 + self.last_x, self.last_y = self.viewer.get_vtk_mouse_position()
316 314 self.changing_wwwl = True
317 315  
318 316 def OnWindowLevelRelease(self, obj, evt):
... ... @@ -345,7 +343,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
345 343 Publisher.sendMessage("Remove incomplete measurements")
346 344  
347 345 def OnInsertLinearMeasurePoint(self, obj, evt):
348   - x,y = self.viewer.interactor.GetEventPosition()
  346 + x,y = self.viewer.get_vtk_mouse_position()
349 347 self.measure_picker.Pick(x, y, 0, self.viewer.ren)
350 348 x, y, z = self.measure_picker.GetPickPosition()
351 349 if self.measure_picker.GetActor():
... ... @@ -384,7 +382,7 @@ class AngularMeasureInteractorStyle(DefaultInteractorStyle):
384 382 Publisher.sendMessage("Remove incomplete measurements")
385 383  
386 384 def OnInsertAngularMeasurePoint(self, obj, evt):
387   - x,y = self.viewer.interactor.GetEventPosition()
  385 + x,y = self.viewer.get_vtk_mouse_position()
388 386 self.measure_picker.Pick(x, y, 0, self.viewer.ren)
389 387 x, y, z = self.measure_picker.GetPickPosition()
390 388 if self.measure_picker.GetActor():
... ... @@ -412,7 +410,7 @@ class SeedInteractorStyle(DefaultInteractorStyle):
412 410 self.AddObserver("LeftButtonPressEvent", self.OnInsertSeed)
413 411  
414 412 def OnInsertSeed(self, obj, evt):
415   - x,y = self.viewer.interactor.GetEventPosition()
  413 + x,y = self.viewer.get_vtk_mouse_position()
416 414 self.picker.Pick(x, y, 0, self.viewer.ren)
417 415 point_id = self.picker.GetPointId()
418 416 if point_id > -1:
... ...
invesalius/data/viewer_slice.py
... ... @@ -650,6 +650,27 @@ class Viewer(wx.Panel):
650 650 my = round((z - zi)/self.slice_.spacing[2], 0)
651 651 return int(mx), int(my)
652 652  
  653 + def get_vtk_mouse_position(self):
  654 + """
  655 + Get Mouse position inside a wxVTKRenderWindowInteractorself. Return a
  656 + tuple with X and Y position.
  657 + Please use this instead of using iren.GetEventPosition because it's
  658 + not returning the correct values on Mac with HighDPI display, maybe
  659 + the same is happing with Windows and Linux, we need to test.
  660 + """
  661 + mposx, mposy = wx.GetMousePosition()
  662 + cposx, cposy = self.interactor.ScreenToClient((mposx, mposy))
  663 + mx, my = cposx, self.interactor.GetSize()[1] - cposy
  664 + if sys.platform == 'darwin':
  665 + # It's needed to mutiple by scale factor in HighDPI because of
  666 + # https://docs.wxpython.org/wx.glcanvas.GLCanvas.html
  667 + # For now we are doing this only on Mac but it may be needed on
  668 + # Windows and Linux too.
  669 + scale = self.interactor.GetContentScaleFactor()
  670 + mx *= scale
  671 + my *= scale
  672 + return int(mx), int(my)
  673 +
653 674 def get_coordinate_cursor(self, mx, my, picker=None):
654 675 """
655 676 Given the mx, my screen position returns the x, y, z position in world
... ... @@ -1028,7 +1049,7 @@ class Viewer(wx.Panel):
1028 1049 #self.scroll.Bind(wx.EVT_SCROLL_ENDSCROLL, self.OnScrollBarRelease)
1029 1050 self.interactor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
1030 1051 self.interactor.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu)
1031   - # self.interactor.Bind(wx.EVT_SIZE, self.OnSize)
  1052 + self.interactor.Bind(wx.EVT_SIZE, self.OnSize)
1032 1053  
1033 1054 def LoadImagedata(self, mask_dict):
1034 1055 self.SetInput(mask_dict)
... ... @@ -1413,12 +1434,13 @@ class Viewer(wx.Panel):
1413 1434 self.OnScrollBar()
1414 1435  
1415 1436 def OnSize(self, evt):
1416   - w, h = evt.GetSize()
1417   - w = float(w)
1418   - h = float(h)
1419   - if self.slice_data:
1420   - self.slice_data.SetSize((w, h))
1421   - evt.Skip()
  1437 + print("OnSize")
  1438 + w, h = self.GetSize()
  1439 + rwin = self.interactor.GetRenderWindow()
  1440 + rwin.SetSize(w, h)
  1441 + # if self.slice_data:
  1442 + # self.slice_data.SetSize((w, h))
  1443 + # evt.Skip()
1422 1444  
1423 1445 def OnSetMIPSize(self, number_slices):
1424 1446 self.number_slices = number_slices
... ...
invesalius/data/viewer_volume.py
... ... @@ -116,6 +116,9 @@ class Viewer(wx.Panel):
116 116 self.text = vtku.TextZero()
117 117 self.text.SetValue("")
118 118 self.text.SetPosition(const.TEXT_POS_LEFT_UP)
  119 + if sys.platform == 'darwin':
  120 + font_size = const.TEXT_SIZE_LARGE * self.GetContentScaleFactor()
  121 + self.text.SetSize(int(round(font_size, 0)))
119 122 self.ren.AddActor(self.text.actor)
120 123  
121 124 # self.polygon = Polygon(None, is_3d=False)
... ... @@ -318,6 +321,27 @@ class Viewer(wx.Panel):
318 321 Publisher.subscribe(self.ActivateRobotMode, 'Robot navigation mode')
319 322 Publisher.subscribe(self.OnUpdateRobotStatus, 'Update robot status')
320 323  
  324 + def get_vtk_mouse_position(self):
  325 + """
  326 + Get Mouse position inside a wxVTKRenderWindowInteractorself. Return a
  327 + tuple with X and Y position.
  328 + Please use this instead of using iren.GetEventPosition because it's
  329 + not returning the correct values on Mac with HighDPI display, maybe
  330 + the same is happing with Windows and Linux, we need to test.
  331 + """
  332 + mposx, mposy = wx.GetMousePosition()
  333 + cposx, cposy = self.interactor.ScreenToClient((mposx, mposy))
  334 + mx, my = cposx, self.interactor.GetSize()[1] - cposy
  335 + if sys.platform == 'darwin':
  336 + # It's needed to mutiple by scale factor in HighDPI because of
  337 + # https://docs.wxpython.org/wx.glcanvas.GLCanvas.html
  338 + # For now we are doing this only on Mac but it may be needed on
  339 + # Windows and Linux too.
  340 + scale = self.interactor.GetContentScaleFactor()
  341 + mx *= scale
  342 + my *= scale
  343 + return int(mx), int(my)
  344 +
321 345 def SetStereoMode(self, mode):
322 346 ren_win = self.interactor.GetRenderWindow()
323 347  
... ...
invesalius/data/vtk_utils.py
... ... @@ -233,6 +233,7 @@ class TextZero(object):
233 233  
234 234 def SetSize(self, size):
235 235 self.property.SetFontSize(size)
  236 + self.actor.GetTextProperty().ShallowCopy(self.property)
236 237  
237 238 def SetSymbolicSize(self, size):
238 239 self.symbolic_syze = size
... ... @@ -288,8 +289,8 @@ class TextZero(object):
288 289 coord.SetValue(*self.position)
289 290 x, y = coord.GetComputedDisplayValue(canvas.evt_renderer)
290 291 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
291   - # font.SetWeight(wx.FONTWEIGHT_BOLD)
292 292 font.SetSymbolicSize(self.symbolic_syze)
  293 + font.Scale(canvas.viewer.GetContentScaleFactor())
293 294 if self.bottom_pos or self.right_pos:
294 295 w, h = canvas.calc_text_size(self.text, font)
295 296 if self.right_pos:
... ...
invesalius/gui/widgets/canvas_renderer.py
... ... @@ -180,13 +180,11 @@ class CanvasRendererCTX:
180 180 return False
181 181  
182 182 def Refresh(self):
183   - print('Refresh')
184 183 self.modified = True
185 184 self.viewer.interactor.Render()
186 185  
187 186 def OnMouseMove(self, evt):
188   - x, y = evt.GetPosition()
189   - y = self.viewer.interactor.GetSize()[1] - y
  187 + x, y = self.viewer.get_vtk_mouse_position()
190 188 redraw = False
191 189  
192 190 if self._drag_obj:
... ... @@ -230,8 +228,7 @@ class CanvasRendererCTX:
230 228 evt.Skip()
231 229  
232 230 def OnLeftButtonPress(self, evt):
233   - x, y = evt.GetPosition()
234   - y = self.viewer.interactor.GetSize()[1] - y
  231 + x, y = self.viewer.get_vtk_mouse_position()
235 232 if self._over_obj and hasattr(self._over_obj, 'on_mouse_move'):
236 233 if hasattr(self._over_obj, 'on_select'):
237 234 try:
... ... @@ -286,8 +283,7 @@ class CanvasRendererCTX:
286 283 evt.Skip()
287 284  
288 285 def OnDoubleClick(self, evt):
289   - x, y = evt.GetPosition()
290   - y = self.viewer.interactor.GetSize()[1] - y
  286 + x, y = self.viewer.get_vtk_mouse_position()
291 287 evt_obj = CanvasEvent('double_left_click', None, (x, y), self.viewer, self.evt_renderer,
292 288 control_down=evt.ControlDown(),
293 289 alt_down=evt.AltDown(),
... ... @@ -301,6 +297,7 @@ class CanvasRendererCTX:
301 297 def OnPaint(self, evt, obj):
302 298 size = self.canvas_renderer.GetSize()
303 299 w, h = size
  300 + ew, eh = self.evt_renderer.GetSize()
304 301 if self._size != size:
305 302 self._size = size
306 303 self._resize_canvas(w, h)
... ... @@ -628,17 +625,18 @@ class CanvasRendererCTX:
628 625  
629 626 if font is None:
630 627 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  628 + font.Scale(self.viewer.GetContentScaleFactor())
631 629  
632   - font = gc.CreateFont(font, txt_colour)
  630 + _font = gc.CreateFont(font, txt_colour)
633 631 px, py = pos
634 632 for t in text.split('\n'):
635 633 t = t.strip()
636 634 _py = -py
637 635 _px = px
638   - gc.SetFont(font)
  636 + gc.SetFont(_font)
639 637 gc.DrawText(t, _px, _py)
640 638  
641   - w, h = self.calc_text_size(t)
  639 + w, h = self.calc_text_size(t, font)
642 640 py -= h
643 641  
644 642 self._drawn = True
... ... @@ -661,10 +659,11 @@ class CanvasRendererCTX:
661 659  
662 660 if font is None:
663 661 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  662 + font.Scale(self.viewer.GetContentScaleFactor())
664 663  
665 664 _font = gc.CreateFont(font, txt_colour)
666 665 gc.SetFont(_font)
667   - w, h = self.calc_text_size(text)
  666 + w, h = self.calc_text_size(text, font)
668 667  
669 668 px, py = pos
670 669  
... ... @@ -880,11 +879,13 @@ class CircleHandler(CanvasHandlerBase):
880 879  
881 880 def draw_to_canvas(self, gc, canvas):
882 881 if self.visible:
  882 + viewer = canvas.viewer
  883 + scale = viewer.GetContentScaleFactor()
883 884 if self.is_3d:
884 885 px, py = self._3d_to_2d(canvas.evt_renderer, self.position)
885 886 else:
886 887 px, py = self.position
887   - x, y, w, h = canvas.draw_circle((px, py), self.radius,
  888 + x, y, w, h = canvas.draw_circle((px, py), self.radius * scale,
888 889 line_colour=self.line_colour,
889 890 fill_colour=self.fill_colour)
890 891 self.bbox = (x - w/2, y - h/2, x + w/2, y + h/2)
... ...