Commit 0b283dbe808e29124751cdf64c2455338c169595

Authored by Thiago Franco de Moraes
1 parent 4773dbbf
Exists in phoenix

Adapting InVesalius to Phoenix (new wxpython version)

@@ -29,10 +29,11 @@ if sys.platform == 'win32': @@ -29,10 +29,11 @@ if sys.platform == 'win32':
29 import _winreg 29 import _winreg
30 else: 30 else:
31 if sys.platform != 'darwin': 31 if sys.platform != 'darwin':
32 - import wxversion 32 + pass
  33 + # import wxversion
33 #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True) 34 #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True)
34 #wxversion.select('2.8-unicode', optionsRequired=True) 35 #wxversion.select('2.8-unicode', optionsRequired=True)
35 - wxversion.ensureMinimal('3.0') 36 + # wxversion.ensureMinimal('3.0')
36 37
37 import wx 38 import wx
38 #from wx.lib.pubsub import setupv1 #new wx 39 #from wx.lib.pubsub import setupv1 #new wx
@@ -48,6 +49,11 @@ from wx.lib.pubsub import pub as Publisher @@ -48,6 +49,11 @@ from wx.lib.pubsub import pub as Publisher
48 # if sys.platform != 'darwin': 49 # if sys.platform != 'darwin':
49 # _SplashScreen = wx.SplashScreen 50 # _SplashScreen = wx.SplashScreen
50 51
  52 +try:
  53 + from wx.adv import SplashScreen as _SplashScreen
  54 +except ImportError:
  55 + from wx import SplashScreen as _SplashScreen
  56 +
51 57
52 import invesalius.gui.language_dialog as lang_dlg 58 import invesalius.gui.language_dialog as lang_dlg
53 import invesalius.i18n as i18n 59 import invesalius.i18n as i18n
@@ -92,7 +98,7 @@ class InVesalius(wx.App): @@ -92,7 +98,7 @@ class InVesalius(wx.App):
92 98
93 # ------------------------------------------------------------------ 99 # ------------------------------------------------------------------
94 100
95 -class SplashScreen(wx.SplashScreen): 101 +class SplashScreen(_SplashScreen):
96 """ 102 """
97 Splash screen to be shown in InVesalius initialization. 103 Splash screen to be shown in InVesalius initialization.
98 """ 104 """
@@ -175,8 +181,12 @@ class SplashScreen(wx.SplashScreen): @@ -175,8 +181,12 @@ class SplashScreen(wx.SplashScreen):
175 181
176 bmp = wx.Image(path).ConvertToBitmap() 182 bmp = wx.Image(path).ConvertToBitmap()
177 183
178 - style = wx.SPLASH_TIMEOUT | wx.SPLASH_CENTRE_ON_SCREEN  
179 - wx.SplashScreen.__init__(self, 184 + try:
  185 + style = wx.SPLASH_TIMEOUT | wx.SPLASH_CENTRE_ON_SCREEN
  186 + except AttributeError:
  187 + style = wx.adv.SPLASH_TIMEOUT | wx.adv.SPLASH_CENTRE_ON_SCREEN
  188 +
  189 + _SplashScreen.__init__(self,
180 bitmap=bmp, 190 bitmap=bmp,
181 splashStyle=style, 191 splashStyle=style,
182 milliseconds=1500, 192 milliseconds=1500,
invesalius/data/viewer_slice.py
@@ -26,7 +26,8 @@ import tempfile @@ -26,7 +26,8 @@ import tempfile
26 import numpy as np 26 import numpy as np
27 27
28 import vtk 28 import vtk
29 -from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor 29 +from invesalius.data.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
  30 +# from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
30 31
31 import invesalius.data.styles as styles 32 import invesalius.data.styles as styles
32 import wx 33 import wx
@@ -95,10 +96,10 @@ class ContourMIPConfig(wx.Panel): @@ -95,10 +96,10 @@ class ContourMIPConfig(wx.Panel):
95 sizer = wx.BoxSizer(wx.HORIZONTAL) 96 sizer = wx.BoxSizer(wx.HORIZONTAL)
96 sizer.Add(txt_mip_size, 0, wx.EXPAND | wx.ALL, 2) 97 sizer.Add(txt_mip_size, 0, wx.EXPAND | wx.ALL, 2)
97 sizer.Add(self.mip_size_spin, 0, wx.EXPAND) 98 sizer.Add(self.mip_size_spin, 0, wx.EXPAND)
98 - sizer.AddSpacer((10, 0)) 99 + sizer.AddSpacer(10)
99 sizer.Add(self.txt_mip_border, 0, wx.EXPAND | wx.ALL, 2) 100 sizer.Add(self.txt_mip_border, 0, wx.EXPAND | wx.ALL, 2)
100 sizer.Add(self.border_spin, 0, wx.EXPAND) 101 sizer.Add(self.border_spin, 0, wx.EXPAND)
101 - sizer.AddSpacer((10, 0)) 102 + sizer.AddSpacer(10)
102 sizer.Add(self.inverted, 0, wx.EXPAND) 103 sizer.Add(self.inverted, 0, wx.EXPAND)
103 self.SetSizer(sizer) 104 self.SetSizer(sizer)
104 sizer.Fit(self) 105 sizer.Fit(self)
@@ -196,7 +197,7 @@ class CanvasRendererCTX: @@ -196,7 +197,7 @@ class CanvasRendererCTX:
196 self.alpha = np.zeros((h, w, 1), dtype=np.uint8) 197 self.alpha = np.zeros((h, w, 1), dtype=np.uint8)
197 198
198 self.bitmap = wx.EmptyBitmapRGBA(w, h) 199 self.bitmap = wx.EmptyBitmapRGBA(w, h)
199 - self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) 200 + self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha.data)
200 201
201 def _resize_canvas(self, w, h): 202 def _resize_canvas(self, w, h):
202 self._array = np.zeros((h, w, 4), dtype=np.uint8) 203 self._array = np.zeros((h, w, 4), dtype=np.uint8)
@@ -208,7 +209,7 @@ class CanvasRendererCTX: @@ -208,7 +209,7 @@ class CanvasRendererCTX:
208 self.alpha = np.zeros((h, w, 1), dtype=np.uint8) 209 self.alpha = np.zeros((h, w, 1), dtype=np.uint8)
209 210
210 self.bitmap = wx.EmptyBitmapRGBA(w, h) 211 self.bitmap = wx.EmptyBitmapRGBA(w, h)
211 - self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) 212 + self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha.data)
212 213
213 self.modified = True 214 self.modified = True
214 215
@@ -582,7 +583,7 @@ class Viewer(wx.Panel): @@ -582,7 +583,7 @@ class Viewer(wx.Panel):
582 sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) 583 sizer.Add(scroll, 0, wx.EXPAND|wx.GROW)
583 584
584 background_sizer = wx.BoxSizer(wx.VERTICAL) 585 background_sizer = wx.BoxSizer(wx.VERTICAL)
585 - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) 586 + background_sizer.Add(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2)
586 #background_sizer.Add(self.mip_ctrls, 0, wx.EXPAND|wx.GROW|wx.ALL, 2) 587 #background_sizer.Add(self.mip_ctrls, 0, wx.EXPAND|wx.GROW|wx.ALL, 2)
587 self.SetSizer(background_sizer) 588 self.SetSizer(background_sizer)
588 background_sizer.Fit(self) 589 background_sizer.Fit(self)
invesalius/data/viewer_volume.py
@@ -26,7 +26,8 @@ import numpy as np @@ -26,7 +26,8 @@ import numpy as np
26 from numpy.core.umath_tests import inner1d 26 from numpy.core.umath_tests import inner1d
27 import wx 27 import wx
28 import vtk 28 import vtk
29 -from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor 29 +# from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
  30 +from invesalius.data.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
30 from wx.lib.pubsub import pub as Publisher 31 from wx.lib.pubsub import pub as Publisher
31 32
32 import invesalius.constants as const 33 import invesalius.constants as const
invesalius/data/wxVTKRenderWindowInteractor.py 0 → 100644
@@ -0,0 +1,706 @@ @@ -0,0 +1,706 @@
  1 +"""
  2 +
  3 +A VTK RenderWindowInteractor widget for wxPython.
  4 +
  5 +Find wxPython info at http://wxPython.org
  6 +
  7 +Created by Prabhu Ramachandran, April 2002
  8 +Based on wxVTKRenderWindow.py
  9 +
  10 +Fixes and updates by Charl P. Botha 2003-2008
  11 +
  12 +Updated to new wx namespace and some cleaning up by Andrea Gavana,
  13 +December 2006
  14 +"""
  15 +
  16 +"""
  17 +Please see the example at the end of this file.
  18 +
  19 +----------------------------------------
  20 +Creation:
  21 +
  22 + wxVTKRenderWindowInteractor(parent, ID, stereo=0, [wx keywords]):
  23 +
  24 + You should create a wx.App(False) or some other wx.App subclass
  25 + before creating the window.
  26 +
  27 +Behaviour:
  28 +
  29 + Uses __getattr__ to make the wxVTKRenderWindowInteractor behave just
  30 + like a vtkGenericRenderWindowInteractor.
  31 +
  32 +----------------------------------------
  33 +
  34 +"""
  35 +
  36 +# import usual libraries
  37 +import math, os, sys
  38 +import wx
  39 +import vtk
  40 +
  41 +# a few configuration items, see what works best on your system
  42 +
  43 +# Use GLCanvas as base class instead of wx.Window.
  44 +# This is sometimes necessary under wxGTK or the image is blank.
  45 +# (in wxWindows 2.3.1 and earlier, the GLCanvas had scroll bars)
  46 +baseClass = wx.Window
  47 +if wx.Platform == "__WXGTK__":
  48 + import wx.glcanvas
  49 + baseClass = wx.glcanvas.GLCanvas
  50 +
  51 +# Keep capturing mouse after mouse is dragged out of window
  52 +# (in wxGTK 2.3.2 there is a bug that keeps this from working,
  53 +# but it is only relevant in wxGTK if there are multiple windows)
  54 +_useCapture = (wx.Platform == "__WXMSW__")
  55 +
  56 +# end of configuration items
  57 +
  58 +
  59 +class EventTimer(wx.Timer):
  60 + """Simple wx.Timer class.
  61 + """
  62 +
  63 + def __init__(self, iren):
  64 + """Default class constructor.
  65 + @param iren: current render window
  66 + """
  67 + wx.Timer.__init__(self)
  68 + self.iren = iren
  69 +
  70 +
  71 + def Notify(self):
  72 + """ The timer has expired.
  73 + """
  74 + self.iren.TimerEvent()
  75 +
  76 +
  77 +class wxVTKRenderWindowInteractor(baseClass):
  78 + """
  79 + A wxRenderWindow for wxPython.
  80 + Use GetRenderWindow() to get the vtkRenderWindow.
  81 + Create with the keyword stereo=1 in order to
  82 + generate a stereo-capable window.
  83 + """
  84 +
  85 + # class variable that can also be used to request instances that use
  86 + # stereo; this is overridden by the stereo=1/0 parameter. If you set
  87 + # it to True, the NEXT instantiated object will attempt to allocate a
  88 + # stereo visual. E.g.:
  89 + # wxVTKRenderWindowInteractor.USE_STEREO = True
  90 + # myRWI = wxVTKRenderWindowInteractor(parent, -1)
  91 + USE_STEREO = False
  92 +
  93 + def __init__(self, parent, ID, *args, **kw):
  94 + """Default class constructor.
  95 + @param parent: parent window
  96 + @param ID: window id
  97 + @param **kw: wxPython keywords (position, size, style) plus the
  98 + 'stereo' keyword
  99 + """
  100 + # private attributes
  101 + self.__RenderWhenDisabled = 0
  102 +
  103 + # First do special handling of some keywords:
  104 + # stereo, position, size, width, height, style
  105 +
  106 + try:
  107 + stereo = bool(kw['stereo'])
  108 + del kw['stereo']
  109 + except KeyError:
  110 + stereo = False
  111 +
  112 + try:
  113 + position = kw['position']
  114 + del kw['position']
  115 + except KeyError:
  116 + position = wx.DefaultPosition
  117 +
  118 + try:
  119 + size = kw['size']
  120 + del kw['size']
  121 + except KeyError:
  122 + try:
  123 + size = parent.GetSize()
  124 + except AttributeError:
  125 + size = wx.DefaultSize
  126 +
  127 + # wx.WANTS_CHARS says to give us e.g. TAB
  128 + # wx.NO_FULL_REPAINT_ON_RESIZE cuts down resize flicker under GTK
  129 + style = wx.WANTS_CHARS | wx.NO_FULL_REPAINT_ON_RESIZE
  130 +
  131 + try:
  132 + style = style | kw['style']
  133 + del kw['style']
  134 + except KeyError:
  135 + pass
  136 +
  137 + # the enclosing frame must be shown under GTK or the windows
  138 + # don't connect together properly
  139 + if wx.Platform != '__WXMSW__':
  140 + l = []
  141 + p = parent
  142 + while p: # make a list of all parents
  143 + l.append(p)
  144 + p = p.GetParent()
  145 + l.reverse() # sort list into descending order
  146 + for p in l:
  147 + p.Show(1)
  148 +
  149 + if baseClass.__name__ == 'GLCanvas':
  150 + # code added by cpbotha to enable stereo and double
  151 + # buffering correctly where the user requests this; remember
  152 + # that the glXContext in this case is NOT allocated by VTK,
  153 + # but by WX, hence all of this.
  154 +
  155 + # Initialize GLCanvas with correct attriblist
  156 + attribList = [wx.glcanvas.WX_GL_RGBA,
  157 + wx.glcanvas.WX_GL_MIN_RED, 1,
  158 + wx.glcanvas.WX_GL_MIN_GREEN, 1,
  159 + wx.glcanvas.WX_GL_MIN_BLUE, 1,
  160 + wx.glcanvas.WX_GL_DEPTH_SIZE, 16,
  161 + wx.glcanvas.WX_GL_DOUBLEBUFFER]
  162 + if stereo:
  163 + attribList.append(wx.glcanvas.WX_GL_STEREO)
  164 +
  165 + try:
  166 + baseClass.__init__(self, parent, ID, pos=position, size=size,
  167 + style=style,
  168 + attribList=attribList)
  169 + except wx.PyAssertionError:
  170 + # visual couldn't be allocated, so we go back to default
  171 + baseClass.__init__(self, parent, ID, pos=position, size=size,
  172 + style=style)
  173 + if stereo:
  174 + # and make sure everyone knows that the stereo
  175 + # visual wasn't set.
  176 + stereo = 0
  177 +
  178 + else:
  179 + baseClass.__init__(self, parent, ID, pos=position, size=size,
  180 + style=style)
  181 +
  182 + # create the RenderWindow and initialize it
  183 + self._Iren = vtk.vtkGenericRenderWindowInteractor()
  184 + self._Iren.SetRenderWindow( vtk.vtkRenderWindow() )
  185 + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer)
  186 + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer)
  187 + self._Iren.GetRenderWindow().AddObserver('CursorChangedEvent',
  188 + self.CursorChangedEvent)
  189 +
  190 + try:
  191 + self._Iren.GetRenderWindow().SetSize(size.width, size.height)
  192 + except AttributeError:
  193 + self._Iren.GetRenderWindow().SetSize(size[0], size[1])
  194 +
  195 + if stereo:
  196 + self._Iren.GetRenderWindow().StereoCapableWindowOn()
  197 + self._Iren.GetRenderWindow().SetStereoTypeToCrystalEyes()
  198 +
  199 + self.__handle = None
  200 +
  201 + self.BindEvents()
  202 +
  203 + # with this, we can make sure that the reparenting logic in
  204 + # Render() isn't called before the first OnPaint() has
  205 + # successfully been run (and set up the VTK/WX display links)
  206 + self.__has_painted = False
  207 +
  208 + # set when we have captured the mouse.
  209 + self._own_mouse = False
  210 + # used to store WHICH mouse button led to mouse capture
  211 + self._mouse_capture_button = 0
  212 +
  213 + # A mapping for cursor changes.
  214 + self._cursor_map = {0: wx.CURSOR_ARROW, # VTK_CURSOR_DEFAULT
  215 + 1: wx.CURSOR_ARROW, # VTK_CURSOR_ARROW
  216 + 2: wx.CURSOR_SIZENESW, # VTK_CURSOR_SIZENE
  217 + 3: wx.CURSOR_SIZENWSE, # VTK_CURSOR_SIZENWSE
  218 + 4: wx.CURSOR_SIZENESW, # VTK_CURSOR_SIZESW
  219 + 5: wx.CURSOR_SIZENWSE, # VTK_CURSOR_SIZESE
  220 + 6: wx.CURSOR_SIZENS, # VTK_CURSOR_SIZENS
  221 + 7: wx.CURSOR_SIZEWE, # VTK_CURSOR_SIZEWE
  222 + 8: wx.CURSOR_SIZING, # VTK_CURSOR_SIZEALL
  223 + 9: wx.CURSOR_HAND, # VTK_CURSOR_HAND
  224 + 10: wx.CURSOR_CROSS, # VTK_CURSOR_CROSSHAIR
  225 + }
  226 +
  227 + def BindEvents(self):
  228 + """Binds all the necessary events for navigation, sizing,
  229 + drawing.
  230 + """
  231 + # refresh window by doing a Render
  232 + self.Bind(wx.EVT_PAINT, self.OnPaint)
  233 + # turn off background erase to reduce flicker
  234 + self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
  235 +
  236 + # Bind the events to the event converters
  237 + self.Bind(wx.EVT_RIGHT_DOWN, self.OnButtonDown)
  238 + self.Bind(wx.EVT_LEFT_DOWN, self.OnButtonDown)
  239 + self.Bind(wx.EVT_MIDDLE_DOWN, self.OnButtonDown)
  240 + self.Bind(wx.EVT_RIGHT_UP, self.OnButtonUp)
  241 + self.Bind(wx.EVT_LEFT_UP, self.OnButtonUp)
  242 + self.Bind(wx.EVT_MIDDLE_UP, self.OnButtonUp)
  243 + self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
  244 + self.Bind(wx.EVT_MOTION, self.OnMotion)
  245 +
  246 + self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
  247 + self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
  248 +
  249 + # If we use EVT_KEY_DOWN instead of EVT_CHAR, capital versions
  250 + # of all characters are always returned. EVT_CHAR also performs
  251 + # other necessary keyboard-dependent translations.
  252 + self.Bind(wx.EVT_CHAR, self.OnKeyDown)
  253 + self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
  254 +
  255 + self.Bind(wx.EVT_SIZE, self.OnSize)
  256 +
  257 + # the wx 2.8.7.1 documentation states that you HAVE to handle
  258 + # this event if you make use of CaptureMouse, which we do.
  259 + if _useCapture and hasattr(wx, 'EVT_MOUSE_CAPTURE_LOST'):
  260 + self.Bind(wx.EVT_MOUSE_CAPTURE_LOST,
  261 + self.OnMouseCaptureLost)
  262 +
  263 +
  264 + def __getattr__(self, attr):
  265 + """Makes the object behave like a
  266 + vtkGenericRenderWindowInteractor.
  267 + """
  268 + if attr == '__vtk__':
  269 + return lambda t=self._Iren: t
  270 + elif hasattr(self._Iren, attr):
  271 + return getattr(self._Iren, attr)
  272 + else:
  273 + raise AttributeError(self.__class__.__name__ +
  274 + " has no attribute named " + attr)
  275 +
  276 + def CreateTimer(self, obj, evt):
  277 + """ Creates a timer.
  278 + """
  279 + self._timer = EventTimer(self)
  280 + self._timer.Start(10, True)
  281 +
  282 + def DestroyTimer(self, obj, evt):
  283 + """The timer is a one shot timer so will expire automatically.
  284 + """
  285 + return 1
  286 +
  287 + def _CursorChangedEvent(self, obj, evt):
  288 + """Change the wx cursor if the renderwindow's cursor was
  289 + changed.
  290 + """
  291 + cur = self._cursor_map[obj.GetCurrentCursor()]
  292 + c = wx.StockCursor(cur)
  293 + self.SetCursor(c)
  294 +
  295 + def CursorChangedEvent(self, obj, evt):
  296 + """Called when the CursorChangedEvent fires on the render
  297 + window."""
  298 + # This indirection is needed since when the event fires, the
  299 + # current cursor is not yet set so we defer this by which time
  300 + # the current cursor should have been set.
  301 + wx.CallAfter(self._CursorChangedEvent, obj, evt)
  302 +
  303 + def HideCursor(self):
  304 + """Hides the cursor."""
  305 + c = wx.StockCursor(wx.CURSOR_BLANK)
  306 + self.SetCursor(c)
  307 +
  308 + def ShowCursor(self):
  309 + """Shows the cursor."""
  310 + rw = self._Iren.GetRenderWindow()
  311 + cur = self._cursor_map[rw.GetCurrentCursor()]
  312 + c = wx.StockCursor(cur)
  313 + self.SetCursor(c)
  314 +
  315 + def GetDisplayId(self):
  316 + """Function to get X11 Display ID from WX and return it in a format
  317 + that can be used by VTK Python.
  318 +
  319 + We query the X11 Display with a new call that was added in wxPython
  320 + 2.6.0.1. The call returns a SWIG object which we can query for the
  321 + address and subsequently turn into an old-style SWIG-mangled string
  322 + representation to pass to VTK.
  323 + """
  324 + d = None
  325 +
  326 + try:
  327 + d = wx.GetXDisplay()
  328 +
  329 + except AttributeError:
  330 + # wx.GetXDisplay was added by Robin Dunn in wxPython 2.6.0.1
  331 + # if it's not available, we can't pass it. In general,
  332 + # things will still work; on some setups, it'll break.
  333 + pass
  334 +
  335 + else:
  336 + # wx returns None on platforms where wx.GetXDisplay is not relevant
  337 + if d:
  338 + d = hex(d)
  339 + # On wxPython-2.6.3.2 and above there is no leading '0x'.
  340 + if not d.startswith('0x'):
  341 + d = '0x' + d
  342 +
  343 + # VTK wants it as: _xxxxxxxx_p_void (SWIG pointer)
  344 + d = '_%s_%s\0' % (d[2:], 'p_void')
  345 +
  346 + return d
  347 +
  348 + def OnMouseCaptureLost(self, event):
  349 + """This is signalled when we lose mouse capture due to an
  350 + external event, such as when a dialog box is shown. See the
  351 + wx documentation.
  352 + """
  353 +
  354 + # the documentation seems to imply that by this time we've
  355 + # already lost capture. I have to assume that we don't need
  356 + # to call ReleaseMouse ourselves.
  357 + if _useCapture and self._own_mouse:
  358 + self._own_mouse = False
  359 +
  360 + def OnPaint(self,event):
  361 + """Handles the wx.EVT_PAINT event for
  362 + wxVTKRenderWindowInteractor.
  363 + """
  364 +
  365 + # wx should continue event processing after this handler.
  366 + # We call this BEFORE Render(), so that if Render() raises
  367 + # an exception, wx doesn't re-call OnPaint repeatedly.
  368 + event.Skip()
  369 +
  370 + dc = wx.PaintDC(self)
  371 +
  372 + # make sure the RenderWindow is sized correctly
  373 + self._Iren.GetRenderWindow().SetSize(self.GetSize())
  374 +
  375 + # Tell the RenderWindow to render inside the wx.Window.
  376 + if not self.__handle:
  377 +
  378 + # on relevant platforms, set the X11 Display ID
  379 + d = self.GetDisplayId()
  380 + if d and self.__has_painted:
  381 + self._Iren.GetRenderWindow().SetDisplayId(d)
  382 +
  383 + # store the handle
  384 + self.__handle = self.GetHandle()
  385 + # and give it to VTK
  386 + self._Iren.GetRenderWindow().SetWindowInfo(str(self.__handle))
  387 +
  388 + # now that we've painted once, the Render() reparenting logic
  389 + # is safe
  390 + self.__has_painted = True
  391 +
  392 + self.Render()
  393 +
  394 + def OnSize(self,event):
  395 + """Handles the wx.EVT_SIZE event for
  396 + wxVTKRenderWindowInteractor.
  397 + """
  398 +
  399 + # event processing should continue (we call this before the
  400 + # Render(), in case it raises an exception)
  401 + event.Skip()
  402 +
  403 + try:
  404 + width, height = event.GetSize()
  405 + except:
  406 + width = event.GetSize().width
  407 + height = event.GetSize().height
  408 + self._Iren.SetSize(width, height)
  409 + self._Iren.ConfigureEvent()
  410 +
  411 + # this will check for __handle
  412 + self.Render()
  413 +
  414 + def OnMotion(self,event):
  415 + """Handles the wx.EVT_MOTION event for
  416 + wxVTKRenderWindowInteractor.
  417 + """
  418 +
  419 + # event processing should continue
  420 + # we call this early in case any of the VTK code raises an
  421 + # exception.
  422 + event.Skip()
  423 +
  424 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  425 + event.ControlDown(),
  426 + event.ShiftDown(),
  427 + chr(0), 0, None)
  428 + self._Iren.MouseMoveEvent()
  429 +
  430 + def OnEnter(self,event):
  431 + """Handles the wx.EVT_ENTER_WINDOW event for
  432 + wxVTKRenderWindowInteractor.
  433 + """
  434 +
  435 + # event processing should continue
  436 + event.Skip()
  437 +
  438 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  439 + event.ControlDown(),
  440 + event.ShiftDown(),
  441 + chr(0), 0, None)
  442 + self._Iren.EnterEvent()
  443 +
  444 +
  445 + def OnLeave(self,event):
  446 + """Handles the wx.EVT_LEAVE_WINDOW event for
  447 + wxVTKRenderWindowInteractor.
  448 + """
  449 +
  450 + # event processing should continue
  451 + event.Skip()
  452 +
  453 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  454 + event.ControlDown(),
  455 + event.ShiftDown(),
  456 + chr(0), 0, None)
  457 + self._Iren.LeaveEvent()
  458 +
  459 +
  460 + def OnButtonDown(self,event):
  461 + """Handles the wx.EVT_LEFT/RIGHT/MIDDLE_DOWN events for
  462 + wxVTKRenderWindowInteractor.
  463 + """
  464 +
  465 + # allow wx event processing to continue
  466 + # on wxPython 2.6.0.1, omitting this will cause problems with
  467 + # the initial focus, resulting in the wxVTKRWI ignoring keypresses
  468 + # until we focus elsewhere and then refocus the wxVTKRWI frame
  469 + # we do it this early in case any of the following VTK code
  470 + # raises an exception.
  471 + event.Skip()
  472 +
  473 + ctrl, shift = event.ControlDown(), event.ShiftDown()
  474 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  475 + ctrl, shift, chr(0), 0, None)
  476 +
  477 + button = 0
  478 + if event.RightDown():
  479 + self._Iren.RightButtonPressEvent()
  480 + button = 'Right'
  481 + elif event.LeftDown():
  482 + self._Iren.LeftButtonPressEvent()
  483 + button = 'Left'
  484 + elif event.MiddleDown():
  485 + self._Iren.MiddleButtonPressEvent()
  486 + button = 'Middle'
  487 +
  488 + # save the button and capture mouse until the button is released
  489 + # we only capture the mouse if it hasn't already been captured
  490 + if _useCapture and not self._own_mouse:
  491 + self._own_mouse = True
  492 + self._mouse_capture_button = button
  493 + self.CaptureMouse()
  494 +
  495 +
  496 + def OnButtonUp(self,event):
  497 + """Handles the wx.EVT_LEFT/RIGHT/MIDDLE_UP events for
  498 + wxVTKRenderWindowInteractor.
  499 + """
  500 +
  501 + # event processing should continue
  502 + event.Skip()
  503 +
  504 + button = 0
  505 + if event.RightUp():
  506 + button = 'Right'
  507 + elif event.LeftUp():
  508 + button = 'Left'
  509 + elif event.MiddleUp():
  510 + button = 'Middle'
  511 +
  512 + # if the same button is released that captured the mouse, and
  513 + # we have the mouse, release it.
  514 + # (we need to get rid of this as soon as possible; if we don't
  515 + # and one of the event handlers raises an exception, mouse
  516 + # is never released.)
  517 + if _useCapture and self._own_mouse and \
  518 + button==self._mouse_capture_button:
  519 + self.ReleaseMouse()
  520 + self._own_mouse = False
  521 +
  522 + ctrl, shift = event.ControlDown(), event.ShiftDown()
  523 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  524 + ctrl, shift, chr(0), 0, None)
  525 +
  526 + if button == 'Right':
  527 + self._Iren.RightButtonReleaseEvent()
  528 + elif button == 'Left':
  529 + self._Iren.LeftButtonReleaseEvent()
  530 + elif button == 'Middle':
  531 + self._Iren.MiddleButtonReleaseEvent()
  532 +
  533 +
  534 + def OnMouseWheel(self,event):
  535 + """Handles the wx.EVT_MOUSEWHEEL event for
  536 + wxVTKRenderWindowInteractor.
  537 + """
  538 +
  539 + # event processing should continue
  540 + event.Skip()
  541 +
  542 + ctrl, shift = event.ControlDown(), event.ShiftDown()
  543 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  544 + ctrl, shift, chr(0), 0, None)
  545 + if event.GetWheelRotation() > 0:
  546 + self._Iren.MouseWheelForwardEvent()
  547 + else:
  548 + self._Iren.MouseWheelBackwardEvent()
  549 +
  550 +
  551 + def OnKeyDown(self,event):
  552 + """Handles the wx.EVT_KEY_DOWN event for
  553 + wxVTKRenderWindowInteractor.
  554 + """
  555 +
  556 + # event processing should continue
  557 + event.Skip()
  558 +
  559 + ctrl, shift = event.ControlDown(), event.ShiftDown()
  560 + keycode, keysym = event.GetKeyCode(), None
  561 + key = chr(0)
  562 + if keycode < 256:
  563 + key = chr(keycode)
  564 +
  565 + # wxPython 2.6.0.1 does not return a valid event.Get{X,Y}()
  566 + # for this event, so we use the cached position.
  567 + (x,y)= self._Iren.GetEventPosition()
  568 + self._Iren.SetEventInformation(x, y,
  569 + ctrl, shift, key, 0,
  570 + keysym)
  571 +
  572 + self._Iren.KeyPressEvent()
  573 + self._Iren.CharEvent()
  574 +
  575 +
  576 + def OnKeyUp(self,event):
  577 + """Handles the wx.EVT_KEY_UP event for
  578 + wxVTKRenderWindowInteractor.
  579 + """
  580 +
  581 + # event processing should continue
  582 + event.Skip()
  583 +
  584 + ctrl, shift = event.ControlDown(), event.ShiftDown()
  585 + keycode, keysym = event.GetKeyCode(), None
  586 + key = chr(0)
  587 + if keycode < 256:
  588 + key = chr(keycode)
  589 +
  590 + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(),
  591 + ctrl, shift, key, 0,
  592 + keysym)
  593 + self._Iren.KeyReleaseEvent()
  594 +
  595 +
  596 + def GetRenderWindow(self):
  597 + """Returns the render window (vtkRenderWindow).
  598 + """
  599 + return self._Iren.GetRenderWindow()
  600 +
  601 + def Render(self):
  602 + """Actually renders the VTK scene on screen.
  603 + """
  604 + RenderAllowed = 1
  605 +
  606 + if not self.__RenderWhenDisabled:
  607 + # the user doesn't want us to render when the toplevel frame
  608 + # is disabled - first find the top level parent
  609 + topParent = wx.GetTopLevelParent(self)
  610 + if topParent:
  611 + # if it exists, check whether it's enabled
  612 + # if it's not enabeld, RenderAllowed will be false
  613 + RenderAllowed = topParent.IsEnabled()
  614 +
  615 + if RenderAllowed:
  616 + if self.__handle and self.__handle == self.GetHandle():
  617 + self._Iren.GetRenderWindow().Render()
  618 +
  619 + elif self.GetHandle() and self.__has_painted:
  620 + # this means the user has reparented us; let's adapt to the
  621 + # new situation by doing the WindowRemap dance
  622 + self._Iren.GetRenderWindow().SetNextWindowInfo(
  623 + str(self.GetHandle()))
  624 +
  625 + # make sure the DisplayId is also set correctly
  626 + d = self.GetDisplayId()
  627 + if d:
  628 + self._Iren.GetRenderWindow().SetDisplayId(d)
  629 +
  630 + # do the actual remap with the new parent information
  631 + self._Iren.GetRenderWindow().WindowRemap()
  632 +
  633 + # store the new situation
  634 + self.__handle = self.GetHandle()
  635 + self._Iren.GetRenderWindow().Render()
  636 +
  637 + def SetRenderWhenDisabled(self, newValue):
  638 + """Change value of __RenderWhenDisabled ivar.
  639 +
  640 + If __RenderWhenDisabled is false (the default), this widget will not
  641 + call Render() on the RenderWindow if the top level frame (i.e. the
  642 + containing frame) has been disabled.
  643 +
  644 + This prevents recursive rendering during wx.SafeYield() calls.
  645 + wx.SafeYield() can be called during the ProgressMethod() callback of
  646 + a VTK object to have progress bars and other GUI elements updated -
  647 + it does this by disabling all windows (disallowing user-input to
  648 + prevent re-entrancy of code) and then handling all outstanding
  649 + GUI events.
  650 +
  651 + However, this often triggers an OnPaint() method for wxVTKRWIs,
  652 + resulting in a Render(), resulting in Update() being called whilst
  653 + still in progress.
  654 + """
  655 + self.__RenderWhenDisabled = bool(newValue)
  656 +
  657 +
  658 +#--------------------------------------------------------------------
  659 +def wxVTKRenderWindowInteractorConeExample():
  660 + """Like it says, just a simple example
  661 + """
  662 + # every wx app needs an app
  663 + app = wx.App(False)
  664 +
  665 + # create the top-level frame, sizer and wxVTKRWI
  666 + frame = wx.Frame(None, -1, "wxVTKRenderWindowInteractor", size=(400,400))
  667 + widget = wxVTKRenderWindowInteractor(frame, -1)
  668 + sizer = wx.BoxSizer(wx.VERTICAL)
  669 + sizer.Add(widget, 1, wx.EXPAND)
  670 + frame.SetSizer(sizer)
  671 + frame.Layout()
  672 +
  673 + # It would be more correct (API-wise) to call widget.Initialize() and
  674 + # widget.Start() here, but Initialize() calls RenderWindow.Render().
  675 + # That Render() call will get through before we can setup the
  676 + # RenderWindow() to render via the wxWidgets-created context; this
  677 + # causes flashing on some platforms and downright breaks things on
  678 + # other platforms. Instead, we call widget.Enable(). This means
  679 + # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
  680 + # that doesn't matter.
  681 + widget.Enable(1)
  682 +
  683 + widget.AddObserver("ExitEvent", lambda o,e,f=frame: f.Close())
  684 +
  685 + ren = vtk.vtkRenderer()
  686 + widget.GetRenderWindow().AddRenderer(ren)
  687 +
  688 + cone = vtk.vtkConeSource()
  689 + cone.SetResolution(8)
  690 +
  691 + coneMapper = vtk.vtkPolyDataMapper()
  692 + coneMapper.SetInputConnection(cone.GetOutputPort())
  693 +
  694 + coneActor = vtk.vtkActor()
  695 + coneActor.SetMapper(coneMapper)
  696 +
  697 + ren.AddActor(coneActor)
  698 +
  699 + # show the window
  700 + frame.Show()
  701 +
  702 + app.MainLoop()
  703 +
  704 +if __name__ == "__main__":
  705 + wxVTKRenderWindowInteractorConeExample()
  706 +
invesalius/gui/data_notebook.py
@@ -29,7 +29,10 @@ except ImportError: @@ -29,7 +29,10 @@ except ImportError:
29 29
30 import wx 30 import wx
31 import wx.grid 31 import wx.grid
32 -import wx.lib.flatnotebook as fnb 32 +try:
  33 + from wx.lib.agw import flatnotebook as fnb
  34 +except ImportError:
  35 + import wx.lib.flatnotebook as fnb
33 import wx.lib.platebtn as pbtn 36 import wx.lib.platebtn as pbtn
34 from wx.lib.pubsub import pub as Publisher 37 from wx.lib.pubsub import pub as Publisher
35 38
invesalius/gui/default_tasks.py
@@ -18,7 +18,11 @@ @@ -18,7 +18,11 @@
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 19
20 import wx 20 import wx
21 -import wx.lib.foldpanelbar as fpb 21 +try:
  22 + from wx.lib.agw import foldpanelbar as fpb
  23 +except ImportError:
  24 + import wx.lib.foldpanelbar as fpb
  25 +
22 from wx.lib.pubsub import pub as Publisher 26 from wx.lib.pubsub import pub as Publisher
23 27
24 import invesalius.constants as const 28 import invesalius.constants as const
invesalius/gui/dialogs.py
@@ -24,7 +24,10 @@ import sys @@ -24,7 +24,10 @@ import sys
24 24
25 import vtk 25 import vtk
26 import wx 26 import wx
27 -import wx.combo 27 +try:
  28 + from wx.adv import BitmapComboBox
  29 +except ImportError:
  30 + from wx.combo import BitmapComboBox
28 31
29 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor 32 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
30 from wx.lib import masked 33 from wx.lib import masked
@@ -1792,7 +1795,7 @@ class MaskBooleanDialog(wx.Dialog): @@ -1792,7 +1795,7 @@ class MaskBooleanDialog(wx.Dialog):
1792 (_(u"Difference"), const.BOOLEAN_DIFF, 'bool_difference.png'), 1795 (_(u"Difference"), const.BOOLEAN_DIFF, 'bool_difference.png'),
1793 (_(u"Intersection"), const.BOOLEAN_AND, 'bool_intersection.png'), 1796 (_(u"Intersection"), const.BOOLEAN_AND, 'bool_intersection.png'),
1794 (_(u"Exclusive disjunction"), const.BOOLEAN_XOR, 'bool_disjunction.png')) 1797 (_(u"Exclusive disjunction"), const.BOOLEAN_XOR, 'bool_disjunction.png'))
1795 - self.op_boolean = wx.combo.BitmapComboBox(self, -1, op_choices[0][0], choices=[]) 1798 + self.op_boolean = BitmapComboBox(self, -1, op_choices[0][0], choices=[])
1796 1799
1797 for n, i, f in op_choices: 1800 for n, i, f in op_choices:
1798 bmp = wx.Bitmap(os.path.join(icon_folder, f), wx.BITMAP_TYPE_PNG) 1801 bmp = wx.Bitmap(os.path.join(icon_folder, f), wx.BITMAP_TYPE_PNG)
invesalius/gui/frame.py
@@ -29,6 +29,11 @@ from wx.lib.pubsub import pub as Publisher @@ -29,6 +29,11 @@ from wx.lib.pubsub import pub as Publisher
29 import wx.lib.agw.toasterbox as TB 29 import wx.lib.agw.toasterbox as TB
30 import wx.lib.popupctl as pc 30 import wx.lib.popupctl as pc
31 31
  32 +try:
  33 + from wx.adv import TaskBarIcon as _TaskBarIcon
  34 +except ImportError:
  35 + from wx import TaskBarIcon as _TaskBarIcon
  36 +
32 from wx.lib.agw.aui.auibar import AuiToolBar, AUI_TB_PLAIN_BACKGROUND 37 from wx.lib.agw.aui.auibar import AuiToolBar, AUI_TB_PLAIN_BACKGROUND
33 38
34 import invesalius.constants as const 39 import invesalius.constants as const
@@ -176,23 +181,23 @@ class Frame(wx.Frame): @@ -176,23 +181,23 @@ class Frame(wx.Frame):
176 Name("Data").Position(1)) 181 Name("Data").Position(1))
177 182
178 # This is the DICOM import panel. When the two panels above as dicom # are shown, this should be hiden 183 # This is the DICOM import panel. When the two panels above as dicom # are shown, this should be hiden
179 - caption = _("Preview medical data to be reconstructed")  
180 - aui_manager.AddPane(imp.Panel(self), wx.aui.AuiPaneInfo().  
181 - Name("Import").CloseButton(False).Centre().Hide().  
182 - MaximizeButton(False).Floatable(True).  
183 - Caption(caption).CaptionVisible(True))  
184 -  
185 - caption = _("Preview bitmap to be reconstructed")  
186 - aui_manager.AddPane(imp_bmp.Panel(self), wx.aui.AuiPaneInfo().  
187 - Name("ImportBMP").CloseButton(False).Centre().Hide().  
188 - MaximizeButton(False).Floatable(True).  
189 - Caption(caption).CaptionVisible(True))  
190 -  
191 - ncaption = _("Retrieve DICOM from PACS")  
192 - aui_manager.AddPane(imp_net.Panel(self), wx.aui.AuiPaneInfo().  
193 - Name("Retrieve").Centre().Hide().  
194 - MaximizeButton(True).Floatable(True).  
195 - Caption(ncaption).CaptionVisible(True)) 184 + # caption = _("Preview medical data to be reconstructed")
  185 + # aui_manager.AddPane(imp.Panel(self), wx.aui.AuiPaneInfo().
  186 + # Name("Import").CloseButton(False).Centre().Hide().
  187 + # MaximizeButton(False).Floatable(True).
  188 + # Caption(caption).CaptionVisible(True))
  189 +
  190 + # caption = _("Preview bitmap to be reconstructed")
  191 + # aui_manager.AddPane(imp_bmp.Panel(self), wx.aui.AuiPaneInfo().
  192 + # Name("ImportBMP").CloseButton(False).Centre().Hide().
  193 + # MaximizeButton(False).Floatable(True).
  194 + # Caption(caption).CaptionVisible(True))
  195 +
  196 + # ncaption = _("Retrieve DICOM from PACS")
  197 + # aui_manager.AddPane(imp_net.Panel(self), wx.aui.AuiPaneInfo().
  198 + # Name("Retrieve").Centre().Hide().
  199 + # MaximizeButton(True).Floatable(True).
  200 + # Caption(ncaption).CaptionVisible(True))
196 201
197 # Add toolbars to manager 202 # Add toolbars to manager
198 # This is pretty tricky -- order on win32 is inverted when 203 # This is pretty tricky -- order on win32 is inverted when
@@ -1078,7 +1083,7 @@ class StatusBar(wx.StatusBar): @@ -1078,7 +1083,7 @@ class StatusBar(wx.StatusBar):
1078 # ------------------------------------------------------------------ 1083 # ------------------------------------------------------------------
1079 # ------------------------------------------------------------------ 1084 # ------------------------------------------------------------------
1080 1085
1081 -class TaskBarIcon(wx.TaskBarIcon): 1086 +class TaskBarIcon(_TaskBarIcon):
1082 """ 1087 """
1083 TaskBarIcon has different behaviours according to the platform: 1088 TaskBarIcon has different behaviours according to the platform:
1084 - win32: Show icon on "Notification Area" (near clock) 1089 - win32: Show icon on "Notification Area" (near clock)
@@ -1086,7 +1091,7 @@ class TaskBarIcon(wx.TaskBarIcon): @@ -1086,7 +1091,7 @@ class TaskBarIcon(wx.TaskBarIcon):
1086 - linux2: Show icon on "Notification Area" (near clock) 1091 - linux2: Show icon on "Notification Area" (near clock)
1087 """ 1092 """
1088 def __init__(self, parent=None): 1093 def __init__(self, parent=None):
1089 - wx.TaskBarIcon.__init__(self) 1094 + _TaskBarIcon.__init__(self)
1090 self.frame = parent 1095 self.frame = parent
1091 1096
1092 icon = wx.Icon(os.path.join(const.ICON_DIR, "invesalius.ico"), 1097 icon = wx.Icon(os.path.join(const.ICON_DIR, "invesalius.ico"),
invesalius/gui/import_bitmap_panel.py
@@ -17,7 +17,10 @@ @@ -17,7 +17,10 @@
17 # detalhes. 17 # detalhes.
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 import wx 19 import wx
20 -import wx.gizmos as gizmos 20 +try:
  21 + from wx.adv import EditableListBox as EditableListBox
  22 +except ImportError:
  23 + from wx.gizmos import TreeListCtrl
21 from wx.lib.pubsub import pub as Publisher 24 from wx.lib.pubsub import pub as Publisher
22 import wx.lib.splitter as spl 25 import wx.lib.splitter as spl
23 26
@@ -188,15 +191,15 @@ class TextPanel(wx.Panel): @@ -188,15 +191,15 @@ class TextPanel(wx.Panel):
188 self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyPress) 191 self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyPress)
189 192
190 def __init_gui(self): 193 def __init_gui(self):
191 - tree = gizmos.TreeListCtrl(self, -1, style =  
192 - wx.TR_DEFAULT_STYLE  
193 - | wx.TR_HIDE_ROOT  
194 - | wx.TR_ROW_LINES  
195 - | wx.TR_COLUMN_LINES  
196 - | wx.TR_FULL_ROW_HIGHLIGHT  
197 - | wx.TR_MULTIPLE  
198 - | wx.TR_HIDE_ROOT  
199 - ) 194 + tree = TreeListCtrl(self, -1, style =
  195 + wx.TR_DEFAULT_STYLE
  196 + | wx.TR_HIDE_ROOT
  197 + | wx.TR_ROW_LINES
  198 + | wx.TR_COLUMN_LINES
  199 + | wx.TR_FULL_ROW_HIGHLIGHT
  200 + | wx.TR_MULTIPLE
  201 + | wx.TR_HIDE_ROOT
  202 + )
200 203
201 204
202 tree.AddColumn(_("Path")) 205 tree.AddColumn(_("Path"))
invesalius/gui/import_network_panel.py
@@ -18,7 +18,10 @@ @@ -18,7 +18,10 @@
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 import wx 19 import wx
20 import sys 20 import sys
21 -import wx.gizmos as gizmos 21 +try:
  22 + from wx.adv import EditableListBox as EditableListBox
  23 +except ImportError:
  24 + from wx.gizmos import TreeListCtrl
22 from wx.lib.pubsub import pub as Publisher 25 from wx.lib.pubsub import pub as Publisher
23 import wx.lib.splitter as spl 26 import wx.lib.splitter as spl
24 27
@@ -226,15 +229,14 @@ class TextPanel(wx.Panel): @@ -226,15 +229,14 @@ class TextPanel(wx.Panel):
226 self.Bind(wx.EVT_SIZE, self.OnSize) 229 self.Bind(wx.EVT_SIZE, self.OnSize)
227 230
228 def __init_gui(self): 231 def __init_gui(self):
229 - tree = gizmos.TreeListCtrl(self, -1, style =  
230 - wx.TR_DEFAULT_STYLE  
231 - | wx.TR_HIDE_ROOT  
232 - | wx.TR_ROW_LINES  
233 - | wx.TR_COLUMN_LINES  
234 - | wx.TR_FULL_ROW_HIGHLIGHT  
235 - | wx.TR_SINGLE  
236 - )  
237 - 232 + tree = TreeListCtrl(self, -1, style =
  233 + wx.TR_DEFAULT_STYLE
  234 + | wx.TR_HIDE_ROOT
  235 + | wx.TR_ROW_LINES
  236 + | wx.TR_COLUMN_LINES
  237 + | wx.TR_FULL_ROW_HIGHLIGHT
  238 + | wx.TR_SINGLE
  239 + )
238 240
239 tree.AddColumn(_("Patient name")) 241 tree.AddColumn(_("Patient name"))
240 tree.AddColumn(_("Patient ID")) 242 tree.AddColumn(_("Patient ID"))
invesalius/gui/import_panel.py
@@ -17,7 +17,11 @@ @@ -17,7 +17,11 @@
17 # detalhes. 17 # detalhes.
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 import wx 19 import wx
20 -import wx.gizmos as gizmos 20 +
  21 +try:
  22 + from wx.dataview import TreeListCtrl
  23 +except ImportError:
  24 + from wx.gizmos import TreeListCtrl
21 from wx.lib.pubsub import pub as Publisher 25 from wx.lib.pubsub import pub as Publisher
22 import wx.lib.splitter as spl 26 import wx.lib.splitter as spl
23 27
@@ -103,7 +107,7 @@ class InnerPanel(wx.Panel): @@ -103,7 +107,7 @@ class InnerPanel(wx.Panel):
103 self.combo_interval.SetSelection(0) 107 self.combo_interval.SetSelection(0)
104 108
105 inner_sizer = wx.BoxSizer(wx.HORIZONTAL) 109 inner_sizer = wx.BoxSizer(wx.HORIZONTAL)
106 - inner_sizer.AddSizer(btnsizer, 0, wx.LEFT|wx.TOP, 5) 110 + inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5)
107 inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5) 111 inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5)
108 panel.SetSizer(inner_sizer) 112 panel.SetSizer(inner_sizer)
109 inner_sizer.Fit(panel) 113 inner_sizer.Fit(panel)
@@ -211,30 +215,47 @@ class TextPanel(wx.Panel): @@ -211,30 +215,47 @@ class TextPanel(wx.Panel):
211 self.Bind(wx.EVT_SIZE, self.OnSize) 215 self.Bind(wx.EVT_SIZE, self.OnSize)
212 216
213 def __init_gui(self): 217 def __init_gui(self):
214 - tree = gizmos.TreeListCtrl(self, -1, style =  
215 - wx.TR_DEFAULT_STYLE  
216 - | wx.TR_HIDE_ROOT  
217 - | wx.TR_ROW_LINES  
218 - | wx.TR_COLUMN_LINES  
219 - | wx.TR_FULL_ROW_HIGHLIGHT  
220 - | wx.TR_SINGLE  
221 - )  
222 -  
223 -  
224 - tree.AddColumn(_("Patient name"))  
225 - tree.AddColumn(_("Patient ID"))  
226 - tree.AddColumn(_("Age"))  
227 - tree.AddColumn(_("Gender"))  
228 - tree.AddColumn(_("Study description"))  
229 - tree.AddColumn(_("Modality"))  
230 - tree.AddColumn(_("Date acquired"))  
231 - tree.AddColumn(_("# Images"))  
232 - tree.AddColumn(_("Institution"))  
233 - tree.AddColumn(_("Date of birth"))  
234 - tree.AddColumn(_("Accession Number"))  
235 - tree.AddColumn(_("Referring physician"))  
236 -  
237 - tree.SetMainColumn(0) # the one with the tree in it... 218 + tree = TreeListCtrl(self, -1, style =
  219 + wx.TR_DEFAULT_STYLE
  220 + | wx.TR_HIDE_ROOT
  221 + | wx.TR_ROW_LINES
  222 + # | wx.TR_COLUMN_LINES
  223 + | wx.TR_FULL_ROW_HIGHLIGHT
  224 + | wx.TR_SINGLE
  225 + )
  226 +
  227 +
  228 + try:
  229 + tree.AppendColumn(_("Patient name"))
  230 + tree.AppendColumn(_("Patient ID"))
  231 + tree.AppendColumn(_("Age"))
  232 + tree.AppendColumn(_("Gender"))
  233 + tree.AppendColumn(_("Study description"))
  234 + tree.AppendColumn(_("Modality"))
  235 + tree.AppendColumn(_("Date acquired"))
  236 + tree.AppendColumn(_("# Images"))
  237 + tree.AppendColumn(_("Institution"))
  238 + tree.AppendColumn(_("Date of birth"))
  239 + tree.AppendColumn(_("Accession Number"))
  240 + tree.AppendColumn(_("Referring physician"))
  241 + except AttributeError:
  242 + tree.AddColumn(_("Patient name"))
  243 + tree.AddColumn(_("Patient ID"))
  244 + tree.AddColumn(_("Age"))
  245 + tree.AddColumn(_("Gender"))
  246 + tree.AddColumn(_("Study description"))
  247 + tree.AddColumn(_("Modality"))
  248 + tree.AddColumn(_("Date acquired"))
  249 + tree.AddColumn(_("# Images"))
  250 + tree.AddColumn(_("Institution"))
  251 + tree.AddColumn(_("Date of birth"))
  252 + tree.AddColumn(_("Accession Number"))
  253 + tree.AddColumn(_("Referring physician"))
  254 +
  255 + try:
  256 + tree.SetMainColumn(0) # the one with the tree in it...
  257 + except AttributeError:
  258 + pass
238 tree.SetColumnWidth(0, 280) # Patient name 259 tree.SetColumnWidth(0, 280) # Patient name
239 tree.SetColumnWidth(1, 110) # Patient ID 260 tree.SetColumnWidth(1, 110) # Patient ID
240 tree.SetColumnWidth(2, 40) # Age 261 tree.SetColumnWidth(2, 40) # Age
@@ -248,7 +269,7 @@ class TextPanel(wx.Panel): @@ -248,7 +269,7 @@ class TextPanel(wx.Panel):
248 tree.SetColumnWidth(10, 140) # Accession Number 269 tree.SetColumnWidth(10, 140) # Accession Number
249 tree.SetColumnWidth(11, 160) # Referring physician 270 tree.SetColumnWidth(11, 160) # Referring physician
250 271
251 - self.root = tree.AddRoot(_("InVesalius Database")) 272 + # self.root = tree.AddRoot(_("InVesalius Database"))
252 self.tree = tree 273 self.tree = tree
253 274
254 def SelectSeries(self, pubsub_evt): 275 def SelectSeries(self, pubsub_evt):
invesalius/gui/language_dialog.py
@@ -20,7 +20,10 @@ @@ -20,7 +20,10 @@
20 import os 20 import os
21 import sys 21 import sys
22 import wx 22 import wx
23 -import wx.combo 23 +try:
  24 + from wx.adv import BitmapComboBox
  25 +except ImportError:
  26 + from wx.combo import BitmapComboBox
24 27
25 import invesalius.i18n as i18n 28 import invesalius.i18n as i18n
26 29
@@ -62,7 +65,7 @@ class ComboBoxLanguage: @@ -62,7 +65,7 @@ class ComboBoxLanguage:
62 selection = self.locales_key.index('en') 65 selection = self.locales_key.index('en')
63 66
64 # Create bitmap combo 67 # Create bitmap combo
65 - self.bitmapCmb = bitmapCmb = wx.combo.BitmapComboBox(parent, style=wx.CB_READONLY) 68 + self.bitmapCmb = bitmapCmb = BitmapComboBox(parent, style=wx.CB_READONLY)
66 for key in self.locales_key: 69 for key in self.locales_key:
67 # Based on composed flag filename, get bitmap 70 # Based on composed flag filename, get bitmap
68 filepath = os.path.join(ICON_DIR, "%s.bmp"%(key)) 71 filepath = os.path.join(ICON_DIR, "%s.bmp"%(key))
@@ -114,7 +117,7 @@ class LanguageDialog(wx.Dialog): @@ -114,7 +117,7 @@ class LanguageDialog(wx.Dialog):
114 # selection = self.locales_key.index('en') 117 # selection = self.locales_key.index('en')
115 118
116 # # Create bitmap combo 119 # # Create bitmap combo
117 - # self.bitmapCmb = bitmapCmb = wx.combo.BitmapComboBox(self, style=wx.CB_READONLY) 120 + # self.bitmapCmb = bitmapCmb = BitmapComboBox(self, style=wx.CB_READONLY)
118 # for key in self.locales_key: 121 # for key in self.locales_key:
119 # # Based on composed flag filename, get bitmap 122 # # Based on composed flag filename, get bitmap
120 # filepath = os.path.join(ICON_DIR, "%s.bmp"%(key)) 123 # filepath = os.path.join(ICON_DIR, "%s.bmp"%(key))
invesalius/gui/preferences.py
@@ -17,11 +17,15 @@ class Preferences(wx.Dialog): @@ -17,11 +17,15 @@ class Preferences(wx.Dialog):
17 def __init__( self, parent, id = ID, title = _("Preferences"), size=wx.DefaultSize,\ 17 def __init__( self, parent, id = ID, title = _("Preferences"), size=wx.DefaultSize,\
18 pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE): 18 pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE):
19 19
20 - pre = wx.PreDialog()  
21 - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)  
22 - pre.Create(parent, ID, title, pos, size, style)  
23 -  
24 - self.PostCreate(pre) 20 + try:
  21 + pre = wx.PreDialog()
  22 + pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
  23 + pre.Create(parent, ID, title, pos, size, style)
  24 + self.PostCreate(pre)
  25 + except AttributeError:
  26 + wx.Dialog.__init__(self)
  27 + self.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
  28 + self.Create(parent, ID, title, pos, size, style)
25 29
26 sizer = wx.BoxSizer(wx.VERTICAL) 30 sizer = wx.BoxSizer(wx.VERTICAL)
27 31
@@ -55,7 +59,7 @@ class Preferences(wx.Dialog): @@ -55,7 +59,7 @@ class Preferences(wx.Dialog):
55 59
56 btnsizer.Realize() 60 btnsizer.Realize()
57 61
58 - sizer.AddSizer(btnsizer, 10, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5) 62 + sizer.Add(btnsizer, 10, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5)
59 63
60 self.SetSizer(sizer) 64 self.SetSizer(sizer)
61 sizer.Fit(self) 65 sizer.Fit(self)
invesalius/gui/task_exporter.py
@@ -21,7 +21,10 @@ import os @@ -21,7 +21,10 @@ import os
21 import sys 21 import sys
22 22
23 import wx 23 import wx
24 -import wx.lib.hyperlink as hl 24 +try:
  25 + from wx.lib.agw import hyperlink as hl
  26 +except ImportError:
  27 + import wx.lib.hyperlink as hl
25 import wx.lib.platebtn as pbtn 28 import wx.lib.platebtn as pbtn
26 from wx.lib.pubsub import pub as Publisher 29 from wx.lib.pubsub import pub as Publisher
27 30
invesalius/gui/task_importer.py
@@ -20,7 +20,10 @@ import os @@ -20,7 +20,10 @@ import os
20 import sys 20 import sys
21 21
22 import wx 22 import wx
23 -import wx.lib.hyperlink as hl 23 +try:
  24 + from wx.lib.agw import hyperlink as hl
  25 +except ImportError:
  26 + import wx.lib.hyperlink as hl
24 import wx.lib.platebtn as pbtn 27 import wx.lib.platebtn as pbtn
25 from wx.lib.pubsub import pub as Publisher 28 from wx.lib.pubsub import pub as Publisher
26 29
invesalius/gui/task_navigator.py
@@ -22,7 +22,10 @@ import sys @@ -22,7 +22,10 @@ import sys
22 22
23 import numpy as np 23 import numpy as np
24 import wx 24 import wx
25 -import wx.lib.hyperlink as hl 25 +try:
  26 + from wx.lib.agw import hyperlink as hl
  27 +except ImportError:
  28 + import wx.lib.hyperlink as hl
26 import wx.lib.masked.numctrl 29 import wx.lib.masked.numctrl
27 from wx.lib.pubsub import pub as Publisher 30 from wx.lib.pubsub import pub as Publisher
28 31
invesalius/gui/task_slice.py
@@ -21,10 +21,18 @@ import sys @@ -21,10 +21,18 @@ import sys
21 import os 21 import os
22 22
23 import wx 23 import wx
24 -import wx.lib.hyperlink as hl 24 +try:
  25 + from wx.lib.agw import hyperlink as hl
  26 +except ImportError:
  27 + import wx.lib.hyperlink as hl
25 import wx.lib.platebtn as pbtn 28 import wx.lib.platebtn as pbtn
26 from wx.lib.pubsub import pub as Publisher 29 from wx.lib.pubsub import pub as Publisher
27 30
  31 +try:
  32 + SystemSettings_GetColour = wx.SystemSettings.GetColour
  33 +except AttributeError:
  34 + SystemSettings_GetColour = wx.SystemSettings_GetColour
  35 +
28 import invesalius.data.mask as mask 36 import invesalius.data.mask as mask
29 import invesalius.data.slice_ as slice_ 37 import invesalius.data.slice_ as slice_
30 import invesalius.constants as const 38 import invesalius.constants as const
@@ -108,7 +116,7 @@ class InnerTaskPanel(wx.Panel): @@ -108,7 +116,7 @@ class InnerTaskPanel(wx.Panel):
108 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 116 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
109 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_SCROLLBAR) 117 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_SCROLLBAR)
110 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUHILIGHT) 118 #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUHILIGHT)
111 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 119 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
112 fold_panel = FoldPanel(self) 120 fold_panel = FoldPanel(self)
113 fold_panel.SetBackgroundColour(default_colour) 121 fold_panel.SetBackgroundColour(default_colour)
114 self.fold_panel = fold_panel 122 self.fold_panel = fold_panel
@@ -134,7 +142,7 @@ class InnerTaskPanel(wx.Panel): @@ -134,7 +142,7 @@ class InnerTaskPanel(wx.Panel):
134 main_sizer = wx.BoxSizer(wx.VERTICAL) 142 main_sizer = wx.BoxSizer(wx.VERTICAL)
135 main_sizer.Add(line_new, 0,wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) 143 main_sizer.Add(line_new, 0,wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5)
136 main_sizer.Add(fold_panel, 1, wx.GROW|wx.EXPAND|wx.ALL, 5) 144 main_sizer.Add(fold_panel, 1, wx.GROW|wx.EXPAND|wx.ALL, 5)
137 - main_sizer.AddSizer(line_sizer, 0, wx.GROW|wx.EXPAND) 145 + main_sizer.Add(line_sizer, 0, wx.GROW|wx.EXPAND)
138 main_sizer.AddSpacer(5) 146 main_sizer.AddSpacer(5)
139 main_sizer.Fit(self) 147 main_sizer.Fit(self)
140 148
@@ -229,7 +237,7 @@ class FoldPanel(wx.Panel): @@ -229,7 +237,7 @@ class FoldPanel(wx.Panel):
229 class InnerFoldPanel(wx.Panel): 237 class InnerFoldPanel(wx.Panel):
230 def __init__(self, parent): 238 def __init__(self, parent):
231 wx.Panel.__init__(self, parent) 239 wx.Panel.__init__(self, parent)
232 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 240 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
233 self.SetBackgroundColour(default_colour) 241 self.SetBackgroundColour(default_colour)
234 242
235 # Fold panel and its style settings 243 # Fold panel and its style settings
@@ -643,7 +651,7 @@ class MaskProperties(wx.Panel): @@ -643,7 +651,7 @@ class MaskProperties(wx.Panel):
643 class EditionTools(wx.Panel): 651 class EditionTools(wx.Panel):
644 def __init__(self, parent): 652 def __init__(self, parent):
645 wx.Panel.__init__(self, parent) 653 wx.Panel.__init__(self, parent)
646 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 654 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
647 self.SetBackgroundColour(default_colour) 655 self.SetBackgroundColour(default_colour)
648 656
649 ## LINE 1 657 ## LINE 1
@@ -807,7 +815,7 @@ class EditionTools(wx.Panel): @@ -807,7 +815,7 @@ class EditionTools(wx.Panel):
807 class WatershedTool(EditionTools): 815 class WatershedTool(EditionTools):
808 def __init__(self, parent): 816 def __init__(self, parent):
809 wx.Panel.__init__(self, parent) 817 wx.Panel.__init__(self, parent)
810 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 818 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
811 self.SetBackgroundColour(default_colour) 819 self.SetBackgroundColour(default_colour)
812 820
813 ## LINE 1 821 ## LINE 1
invesalius/gui/task_surface.py
@@ -20,9 +20,17 @@ import sys @@ -20,9 +20,17 @@ import sys
20 import os 20 import os
21 21
22 import wx 22 import wx
23 -import wx.lib.hyperlink as hl 23 +try:
  24 + from wx.lib.agw import hyperlink as hl
  25 +except ImportError:
  26 + import wx.lib.hyperlink as hl
24 from wx.lib.pubsub import pub as Publisher 27 from wx.lib.pubsub import pub as Publisher
25 28
  29 +try:
  30 + SystemSettings_GetColour = wx.SystemSettings.GetColour
  31 +except AttributeError:
  32 + SystemSettings_GetColour = wx.SystemSettings_GetColour
  33 +
26 import invesalius.constants as const 34 import invesalius.constants as const
27 import invesalius.data.slice_ as slice_ 35 import invesalius.data.slice_ as slice_
28 import invesalius.gui.dialogs as dlg 36 import invesalius.gui.dialogs as dlg
@@ -195,7 +203,7 @@ class FoldPanel(wx.Panel): @@ -195,7 +203,7 @@ class FoldPanel(wx.Panel):
195 class InnerFoldPanel(wx.Panel): 203 class InnerFoldPanel(wx.Panel):
196 def __init__(self, parent): 204 def __init__(self, parent):
197 wx.Panel.__init__(self, parent) 205 wx.Panel.__init__(self, parent)
198 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 206 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
199 self.SetBackgroundColour(default_colour) 207 self.SetBackgroundColour(default_colour)
200 208
201 # Fold panel and its style settings 209 # Fold panel and its style settings
@@ -264,7 +272,7 @@ BTN_SEEDS = wx.NewId() @@ -264,7 +272,7 @@ BTN_SEEDS = wx.NewId()
264 class SurfaceTools(wx.Panel): 272 class SurfaceTools(wx.Panel):
265 def __init__(self, parent): 273 def __init__(self, parent):
266 wx.Panel.__init__(self, parent) 274 wx.Panel.__init__(self, parent)
267 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 275 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
268 self.SetBackgroundColour(default_colour) 276 self.SetBackgroundColour(default_colour)
269 277
270 #self.SetBackgroundColour(wx.Colour(255,255,255)) 278 #self.SetBackgroundColour(wx.Colour(255,255,255))
@@ -398,7 +406,7 @@ class SurfaceTools(wx.Panel): @@ -398,7 +406,7 @@ class SurfaceTools(wx.Panel):
398 class SurfaceProperties(wx.Panel): 406 class SurfaceProperties(wx.Panel):
399 def __init__(self, parent): 407 def __init__(self, parent):
400 wx.Panel.__init__(self, parent) 408 wx.Panel.__init__(self, parent)
401 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 409 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
402 self.SetBackgroundColour(default_colour) 410 self.SetBackgroundColour(default_colour)
403 411
404 self.surface_list = [] 412 self.surface_list = []
@@ -559,7 +567,7 @@ class QualityAdjustment(wx.Panel): @@ -559,7 +567,7 @@ class QualityAdjustment(wx.Panel):
559 def __init__(self, parent): 567 def __init__(self, parent):
560 import invesalius.constants as const 568 import invesalius.constants as const
561 wx.Panel.__init__(self, parent) 569 wx.Panel.__init__(self, parent)
562 - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) 570 + default_colour = SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
563 self.SetBackgroundColour(default_colour) 571 self.SetBackgroundColour(default_colour)
564 572
565 # LINE 1 573 # LINE 1
invesalius/gui/task_tools.py
@@ -20,7 +20,10 @@ @@ -20,7 +20,10 @@
20 import wx 20 import wx
21 import os 21 import os
22 import wx.lib.embeddedimage as emb 22 import wx.lib.embeddedimage as emb
23 -import wx.lib.hyperlink as hl 23 +try:
  24 + from wx.lib.agw import hyperlink as hl
  25 +except ImportError:
  26 + import wx.lib.hyperlink as hl
24 import wx.lib.platebtn as pbtn 27 import wx.lib.platebtn as pbtn
25 from wx.lib.pubsub import pub as Publisher 28 from wx.lib.pubsub import pub as Publisher
26 29
invesalius/gui/widgets/gradient.py
@@ -121,8 +121,11 @@ class GradientSlider(wx.Panel): @@ -121,8 +121,11 @@ class GradientSlider(wx.Panel):
121 dc.GradientFillLinear((x_init_gradient, y_init_gradient, 121 dc.GradientFillLinear((x_init_gradient, y_init_gradient,
122 width_gradient, height_gradient), 122 width_gradient, height_gradient),
123 (0, 0, 0), (255,255, 255)) 123 (0, 0, 0), (255,255, 255))
124 -  
125 - n = wx.RendererNative_Get() 124 +
  125 + try:
  126 + n = wx.RendererNative.Get()
  127 + except AttributeError:
  128 + n = wx.RendererNative_Get()
126 129
127 # Drawing the push buttons 130 # Drawing the push buttons
128 n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h)) 131 n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h))