Commit a1b9aeaa846b7631720d1922b9a08d7d67a59967

Authored by Paulo Henrique Junqueira Amorim
1 parent 739b8904

ENH: Restructuring state of the tools

Showing 1 changed file with 167 additions and 194 deletions   Show diff stats
invesalius/data/viewer_slice.py
... ... @@ -50,7 +50,8 @@ class Viewer(wx.Panel):
50 50  
51 51 # Interactor additional style
52 52 self.modes = []#['DEFAULT']
53   - self.mouse_pressed = 0
  53 + self.left_pressed = 0
  54 + self.right_pressed = 0
54 55  
55 56 # All renderers and image actors in this viewer
56 57 self.slice_data_list = []
... ... @@ -144,121 +145,95 @@ class Viewer(wx.Panel):
144 145 self.ren = ren
145 146  
146 147  
147   - def append_mode(self, mode):
148   - if "ZOOM" in self.modes or "ZOOMSELECT" in self.modes:
149   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
150   -
151   - action = {const.SLICE_STATE_CROSS: {
  148 + def SetState(self, state):
  149 + self.state = state
  150 + action = {const.SLICE_STATE_CROSS:
  151 + {
152 152 "MouseMoveEvent": self.OnCrossMove,
153 153 "LeftButtonPressEvent": self.OnCrossMouseClick,
154 154 "LeftButtonReleaseEvent": self.OnCrossMouseRelease
155 155 },
156   - const.SLICE_STATE_EDITOR: {
  156 + const.SLICE_STATE_EDITOR:
  157 + {
157 158 "MouseMoveEvent": self.OnBrushMove,
158 159 "LeftButtonPressEvent": self.OnBrushClick,
159 160 "LeftButtonReleaseEvent": self.OnMouseRelease,
160 161 "EnterEvent": self.OnEnterInteractor,
161 162 "LeaveEvent": self.OnLeaveInteractor
162 163 },
163   - const.STATE_PAN:{
164   - "MouseMoveEvent": self.OnPanMove,
165   - "LeftButtonPressEvent": self.OnPanClick,
166   - "LeftButtonReleaseEvent": self.OnReleaseModes
167   - },
168   - const.STATE_SPIN:{
169   - "MouseMoveEvent": self.OnSpinMove,
170   - "LeftButtonPressEvent": self.OnSpinClick,
171   - "LeftButtonReleaseEvent": self.OnReleaseModes
172   - },
173   - const.STATE_ZOOM:{
174   - "MouseMoveEvent": self.OnZoomMove,
175   - "LeftButtonPressEvent": self.OnZoomClick,
176   - "LeftButtonReleaseEvent": self.OnReleaseModes,
177   - },
178   - const.SLICE_STATE_SCROLL:{
179   - "MouseMoveEvent": self.OnChangeSliceMove,
180   - "LeftButtonPressEvent": self.OnChangeSliceClick,
181   - "LeftButtonReleaseEvent": self.OnReleaseModes
182   - },
183   - const.STATE_WL:{
184   - "MouseMoveEvent": self.OnWindowLevelMove,
185   - "LeftButtonPressEvent": self.OnWindowLevelClick,
186   - "LeftButtonReleaseEvent": self.OnReleaseModes
187   - },
188   - const.STATE_DEFAULT:{
189   - }
  164 + const.STATE_PAN:
  165 + {
  166 + "MouseMoveEvent": self.OnPanMove,
  167 + "LeftButtonPressEvent": self.OnPanClick,
  168 + "LeftButtonReleaseEvent": self.OnReleaseLeftButton
  169 + },
  170 + const.STATE_SPIN:
  171 + {
  172 + "MouseMoveEvent": self.OnSpinMove,
  173 + "LeftButtonPressEvent": self.OnSpinClick,
  174 + "LeftButtonReleaseEvent": self.OnReleaseLeftButton
  175 + },
  176 + const.STATE_ZOOM:
  177 + {
  178 + "MouseMoveEvent": self.OnZoomMove,
  179 + "LeftButtonPressEvent": self.OnZoomLeftClick,
  180 + "LeftButtonReleaseEvent": self.OnReleaseLeftButton,
  181 + },
  182 + const.SLICE_STATE_SCROLL:
  183 + {
  184 + "MouseMoveEvent": self.OnChangeSliceMove,
  185 + "LeftButtonPressEvent": self.OnChangeSliceClick,
  186 + "LeftButtonReleaseEvent": self.OnReleaseLeftButton
  187 + },
  188 + const.STATE_WL:
  189 + {
  190 + "MouseMoveEvent": self.OnWindowLevelMove,
  191 + "LeftButtonPressEvent": self.OnWindowLevelClick,
  192 + "LeftButtonReleaseEvent": self.OnReleaseLeftButton,
  193 + },
  194 + const.STATE_DEFAULT:
  195 + {
  196 + "MouseMoveEvent": self.OnZoomMove,
  197 + "RightButtonPressEvent": self.OnZoomLeftClick,
  198 + "RightButtonReleaseEvent": self.OnReleaseRightButton,
  199 + }
190 200 }
191 201  
192 202 # Bind method according to current mode
193   - if(mode == const.STATE_ZOOM_SL):
  203 + if(state == const.STATE_ZOOM_SL):
194 204 style = vtk.vtkInteractorStyleRubberBandZoom()
195 205 else:
196 206 style = vtk.vtkInteractorStyleImage()
197 207  
198   - # Check each event available for each mode
199   - for event in action[mode]:
  208 + # Check each event available for each state
  209 + for event in action[state]:
200 210 # Bind event
201 211 style.AddObserver(event,
202   - action[mode][event])
  212 + action[state][event])
  213 +
  214 + style.AddObserver("RightButtonPressEvent",self.OnRightClick)
  215 + style.AddObserver("RightButtonReleaseEvent", self.OnReleaseRightButton)
203 216  
204   - if ((mode == const.STATE_ZOOM) or (mode == const.STATE_ZOOM_SL)):
  217 + if ((state == const.STATE_ZOOM) or (state == const.STATE_ZOOM_SL)):
205 218 self.interactor.Bind(wx.EVT_LEFT_DCLICK, self.OnUnZoom)
206 219 else:
207 220 self.interactor.Bind(wx.EVT_LEFT_DCLICK, None)
208 221  
209 222 self.style = style
210 223 self.interactor.SetInteractorStyle(style)
211   -
212   -
213 224  
214   - def __set_mode_editor(self, pubsub_evt):
215   - self.append_mode(const.SLICE_STATE_EDITOR)
216   - self.mouse_pressed = 0
217   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK))
218   -
219   - def __set_mode_spin(self, pubsub_evt):
220   - self.append_mode('SPIN')
221   - self.mouse_pressed = 0
222   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
  225 + #def OnMouseMove(self, evt, obj):
  226 + # if(self.left_pressed):
  227 +
  228 + # if(self.state == const.SLICE_STATE_CROSS):
  229 +
  230 +
  231 + def OnRightClick(self, evt, obj):
  232 + self.right_pressed = 1
223 233  
224   - def __set_mode_zoom(self, pubsub_evt):
225   - #print "Zoom"
226   - self.append_mode('ZOOM')
227   - self.mouse_pressed = 0
228   - ICON_IMAGE = wx.Image(os.path.join(const.ICON_DIR,
229   - "tool_zoom.png"),wx.BITMAP_TYPE_PNG)
230   - self.interactor.SetCursor(wx.CursorFromImage(ICON_IMAGE))
231   -
232   - def __set_mode_pan(self, pubsub_evt):
233   - self.append_mode('PAN')
234   - self.mouse_pressed = 0
235   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
236   -
237   - def __set_mode_zoom_select(self, pubsub_evt):
238   - self.append_mode('ZOOMSELECT')
239   - ICON_IMAGE = wx.Image(os.path.join(const.ICON_DIR,
240   - "tool_zoom.png"),wx.BITMAP_TYPE_PNG)
241   - self.interactor.SetCursor(wx.CursorFromImage(ICON_IMAGE))
242   -
243   - def __set_mode_window_level(self, pubsub_evt):
244   - self.append_mode('WINDOWLEVEL')
245   - self.mouse_pressed = 0
246   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
247   - self.interactor.Render()
248   -
249   -
250   - def __set_mode_slice_scroll(self, pubsub_evt):
251   - self.append_mode('CHANGESLICE')
252   - self.mouse_pressed = 0
253   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
254   -
255   - def __set_mode_cross(self, pubsub_evt):
256   - self.append_mode('CROSS')
257   - self.mouse_pressed = 0
258   - self.cross_actor.VisibilityOn()
259 234  
260 235 def OnWindowLevelMove(self, evt, obj):
261   - if self.mouse_pressed:
  236 + if (self.left_pressed):
262 237 position = self.interactor.GetLastEventPosition()
263 238 mouse_x, mouse_y = self.interactor.GetEventPosition()
264 239 self.acum_achange_window += mouse_x - self.last_x
... ... @@ -279,13 +254,16 @@ class Viewer(wx.Panel):
279 254  
280 255 #Necessary update the slice plane in the volume case exists
281 256 ps.Publisher().sendMessage('Render volume viewer')
282   -
  257 +
  258 + elif(self.right_pressed):
  259 + self.OnZoomMove(evt, obj)
  260 +
283 261 self.interactor.Render()
284 262  
285 263  
286 264 def OnWindowLevelClick(self, evt, obj):
287 265 self.last_x, self.last_y = self.interactor.GetLastEventPosition()
288   - self.mouse_pressed = 1
  266 + self.left_pressed = 1
289 267  
290 268 def UpdateWindowLevelValue(self, pubsub_evt):
291 269 window, level = pubsub_evt.data
... ... @@ -293,50 +271,54 @@ class Viewer(wx.Panel):
293 271  
294 272  
295 273 def OnChangeSliceMove(self, evt, obj):
296   -
297   - min = 0
298   - max = self.actor.GetSliceNumberMax()
299   -
300   - if (self.mouse_pressed):
301   - position = self.interactor.GetLastEventPosition()
302   - scroll_position = self.scroll.GetThumbPosition()
303   -
304   - if (position[1] > self.last_position) and\
305   - (self.acum_achange_slice > min):
306   - self.acum_achange_slice -= 1
307   - elif(position[1] < self.last_position) and\
308   - (self.acum_achange_slice < max):
309   - self.acum_achange_slice += 1
310   - self.last_position = position[1]
311   -
312   - self.scroll.SetThumbPosition(self.acum_achange_slice)
313   - self.OnScrollBar()
314   -
  274 + if (self.left_pressed):
  275 + min = 0
  276 + max = self.actor.GetSliceNumberMax()
  277 +
  278 + if (self.left_pressed):
  279 + position = self.interactor.GetLastEventPosition()
  280 + scroll_position = self.scroll.GetThumbPosition()
  281 +
  282 + if (position[1] > self.last_position) and\
  283 + (self.acum_achange_slice > min):
  284 + self.acum_achange_slice -= 1
  285 + elif(position[1] < self.last_position) and\
  286 + (self.acum_achange_slice < max):
  287 + self.acum_achange_slice += 1
  288 + self.last_position = position[1]
  289 +
  290 + self.scroll.SetThumbPosition(self.acum_achange_slice)
  291 + self.OnScrollBar()
  292 +
  293 + elif(self.right_pressed):
  294 + self.OnZoomMove(evt, obj)
315 295  
316 296 def OnChangeSliceClick(self, evt, obj):
317   - self.mouse_pressed = 1
  297 + self.left_pressed = 1
318 298 position = list(self.interactor.GetLastEventPosition())
319 299 self.acum_achange_slice = self.scroll.GetThumbPosition()
320 300 self.last_position = position[1]
321 301  
322 302 def OnPanMove(self, evt, obj):
323   - if (self.mouse_pressed):
  303 + if (self.left_pressed):
324 304 evt.Pan()
325 305 evt.OnRightButtonDown()
326   -
  306 + elif(self.right_pressed):
  307 + self.OnZoomMove(evt, obj)
  308 +
327 309 def OnPanClick(self, evt, obj):
328   - self.mouse_pressed = 1
  310 + self.left_pressed = 1
329 311 evt.StartPan()
330 312  
331 313 def OnZoomMove(self, evt, obj):
332   - if (self.mouse_pressed):
  314 + if (self.left_pressed or self.right_pressed):
333 315 evt.Dolly()
334 316 evt.OnRightButtonDown()
335 317  
336   - def OnZoomClick(self, evt, obj):
337   - self.mouse_pressed = 1
  318 + def OnZoomLeftClick(self, evt, obj):
  319 + self.left_pressed = 1
338 320 evt.StartDolly()
339   -
  321 +
340 322 def OnUnZoom(self, evt, obj = None):
341 323 mouse_x, mouse_y = self.interactor.GetLastEventPosition()
342 324 ren = self.interactor.FindPokedRenderer(mouse_x, mouse_y)
... ... @@ -347,23 +329,32 @@ class Viewer(wx.Panel):
347 329 self.interactor.Render()
348 330  
349 331 def OnSpinMove(self, evt, obj):
350   - if (self.mouse_pressed):
  332 + if (self.left_pressed):
351 333 evt.Spin()
352 334 evt.OnRightButtonDown()
  335 + elif(self.right_pressed):
  336 + self.OnZoomMove(evt, obj)
  337 +
353 338  
354 339 def OnSpinClick(self, evt, obj):
355   - self.mouse_pressed = 1
  340 + self.left_pressed = 1
356 341 evt.StartSpin()
357 342  
358   - def OnReleaseModes(self, evt, obj):
359   - self.mouse_pressed = 0
  343 + def OnReleaseLeftButton(self, evt, obj):
  344 + self.left_pressed = 0
360 345 ps.Publisher().sendMessage('Update slice viewer')
  346 +
  347 + def OnReleaseRightButton(self, evt, obj):
  348 + self.right_pressed = 0
  349 + ps.Publisher().sendMessage('Update slice viewer')
  350 +
  351 +
361 352  
362   - def OnEnterInteractor(self, obj, evt):
  353 + def OnEnterInteractor(self, evt, obj):
363 354 #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK))
364 355 pass
365 356  
366   - def OnLeaveInteractor(self, obj, evt):
  357 + def OnLeaveInteractor(self, evt, obj):
367 358 for slice_data in self.slice_data_list:
368 359 slice_data.cursor.Show(0)
369 360 self.interactor.Render()
... ... @@ -546,14 +537,14 @@ class Viewer(wx.Panel):
546 537 self.interactor.Render()
547 538 #self.cursor = cursor
548 539  
549   - def OnMouseClick(self, obj, evt_vtk):
550   - self.mouse_pressed = 1
  540 + def OnMouseClick(self, evt, obj):
  541 + self.left_pressed = 1
551 542  
552   - def OnMouseRelease(self, obj, evt_vtk):
553   - self.mouse_pressed = 0
  543 + def OnMouseRelease(self, evt, obj):
  544 + self.left_pressed = 0
554 545  
555   - def OnBrushClick(self, obj, evt_vtk):
556   - self.mouse_pressed = 1
  546 + def OnBrushClick(self, evt, obj):
  547 + self.left_pressed = 1
557 548  
558 549 mouse_x, mouse_y = self.interactor.GetEventPosition()
559 550 render = self.interactor.FindPokedRenderer(mouse_x, mouse_y)
... ... @@ -581,41 +572,48 @@ class Viewer(wx.Panel):
581 572 ps.Publisher().sendMessage('Update slice viewer')
582 573 ps.Publisher().sendMessage('Update slice viewer')
583 574  
584   - def OnBrushMove(self, obj, evt_vtk):
585   - mouse_x, mouse_y = self.interactor.GetEventPosition()
586   - render = self.interactor.FindPokedRenderer(mouse_x, mouse_y)
587   - slice_data = self.get_slice_data(render)
588   -
589   - # TODO: Improve!
590   - for i in self.slice_data_list:
591   - i.cursor.Show(0)
592   - slice_data.cursor.Show()
593   -
594   - self.pick.Pick(mouse_x, mouse_y, 0, render)
595   - coord = self.get_coordinate_cursor()
596   - slice_data.cursor.SetPosition(coord)
597   - slice_data.cursor.SetEditionPosition(
598   - self.get_coordinate_cursor_edition(slice_data))
599   - self.__update_cursor_position(slice_data, coord)
  575 + def OnBrushMove(self, evt, obj):
  576 +
  577 + if(self.right_pressed):
  578 + self.OnZoomLeftClick(evt, obj)
  579 + self.OnZoomMove(evt, obj)
  580 + else:
  581 + mouse_x, mouse_y = self.interactor.GetEventPosition()
  582 + render = self.interactor.FindPokedRenderer(mouse_x, mouse_y)
  583 + slice_data = self.get_slice_data(render)
  584 +
  585 + # TODO: Improve!
  586 + for i in self.slice_data_list:
  587 + i.cursor.Show(0)
  588 + slice_data.cursor.Show()
  589 +
  590 + self.pick.Pick(mouse_x, mouse_y, 0, render)
  591 + coord = self.get_coordinate_cursor()
  592 + slice_data.cursor.SetPosition(coord)
  593 + slice_data.cursor.SetEditionPosition(
  594 + self.get_coordinate_cursor_edition(slice_data))
  595 + self.__update_cursor_position(slice_data, coord)
  596 +
  597 + if self._brush_cursor_op == const.BRUSH_ERASE:
  598 + evt_msg = 'Erase mask pixel'
  599 + elif self._brush_cursor_op == const.BRUSH_DRAW:
  600 + evt_msg = 'Add mask pixel'
  601 + elif self._brush_cursor_op == const.BRUSH_THRESH:
  602 + evt_msg = 'Edit mask pixel'
  603 +
  604 + if (self.left_pressed):
  605 + pixels = itertools.ifilter(self.test_operation_position,
  606 + slice_data.cursor.GetPixels())
  607 + ps.Publisher().sendMessage(evt_msg, pixels)
  608 + ps.Publisher().sendMessage('Update slice viewer')
600 609  
601   - if self._brush_cursor_op == const.BRUSH_ERASE:
602   - evt_msg = 'Erase mask pixel'
603   - elif self._brush_cursor_op == const.BRUSH_DRAW:
604   - evt_msg = 'Add mask pixel'
605   - elif self._brush_cursor_op == const.BRUSH_THRESH:
606   - evt_msg = 'Edit mask pixel'
  610 + self.interactor.Render()
607 611  
608 612  
609   - if self.mouse_pressed:
610   - pixels = itertools.ifilter(self.test_operation_position,
611   - slice_data.cursor.GetPixels())
612   - ps.Publisher().sendMessage(evt_msg, pixels)
613   - ps.Publisher().sendMessage('Update slice viewer')
614   - self.interactor.Render()
615 613  
616   - def OnCrossMove(self, obj, evt_vtk):
  614 + def OnCrossMove(self, evt, obj):
617 615 # Update position in other slices
618   - if self.mouse_pressed:
  616 + if (self.left_pressed):
619 617 mouse_x, mouse_y = self.interactor.GetEventPosition()
620 618 renderer = self.slice_data_list[0].renderer
621 619 self.pick.Pick(mouse_x, mouse_y, self.slice_data_list[0].number, renderer)
... ... @@ -629,8 +627,11 @@ class Viewer(wx.Panel):
629 627 coord[1])
630 628 ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'),
631 629 coord[2])
632   -
633   - def OnCrossMouseClick(self, obj, evt_vtk):
  630 + elif(self.right_pressed):
  631 + self.OnZoomLeftClick(evt, obj)
  632 + self.OnZoomMove(evt, obj)
  633 +
  634 + def OnCrossMouseClick(self, evt, obj):
634 635 mouse_x, mouse_y = self.interactor.GetEventPosition()
635 636 renderer = self.slice_data_list[0].renderer
636 637 self.pick.Pick(mouse_x, mouse_y, self.slice_data_list[0].number, renderer)
... ... @@ -644,10 +645,10 @@ class Viewer(wx.Panel):
644 645 coord[1])
645 646 ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'),
646 647 coord[2])
647   - self.mouse_pressed = 1
  648 + self.left_pressed = 1
648 649  
649   - def OnCrossMouseRelease(self, obj, evt_vtk):
650   - self.mouse_pressed = 0
  650 + def OnCrossMouseRelease(self, evt, obj):
  651 + self.left_pressed = 0
651 652  
652 653 def get_slice_data(self, render):
653 654 for slice_data in self.slice_data_list:
... ... @@ -753,34 +754,6 @@ class Viewer(wx.Panel):
753 754 ps.Publisher().subscribe(self.ChangeBrushOperation,
754 755 'Set edition operation')
755 756  
756   - ###
757   - """
758   - ps.Publisher().subscribe(self.__set_mode_pan,
759   - ('Set interaction mode',
760   - const.MODE_MOVE))
761   - ps.Publisher().subscribe(self.__set_mode_editor,
762   - ('Set interaction mode',
763   - const.MODE_SLICE_EDITOR))
764   - ps.Publisher().subscribe(self.__set_mode_spin,
765   - ('Set interaction mode',
766   - const.MODE_ROTATE))
767   - ps.Publisher().subscribe(self.__set_mode_zoom,
768   - ('Set interaction mode',
769   - const.MODE_ZOOM))
770   - ps.Publisher().subscribe(self.__set_mode_zoom_select,
771   - ('Set interaction mode',
772   - const.MODE_ZOOM_SELECTION))
773   - ps.Publisher().subscribe(self.__set_mode_slice_scroll,
774   - ('Set interaction mode',
775   - const.MODE_SLICE_SCROLL))
776   - ps.Publisher().subscribe(self.__set_mode_window_level,
777   - ('Set interaction mode',
778   - const.MODE_WW_WL))
779   - ps.Publisher().subscribe(self.__set_mode_cross,
780   - ('Set interaction mode',
781   - const.MODE_SLICE_CROSS))
782   - """
783   -
784 757 ps.Publisher().subscribe(self.UpdateWindowLevelValue,\
785 758 'Update window level value')
786 759  
... ... @@ -794,9 +767,9 @@ class Viewer(wx.Panel):
794 767 'Set slice mode')
795 768  
796 769 def OnSetMode(self, pubsub_evt):
797   - mode = pubsub_evt.data
798   - self.mouse_pressed = 0
799   - self.append_mode(mode)
  770 + state = pubsub_evt.data
  771 + self.left_pressed = 0
  772 + self.SetState(state)
800 773  
801 774  
802 775 def ChangeBrushOperation(self, pubsub_evt):
... ... @@ -904,7 +877,7 @@ class Viewer(wx.Panel):
904 877  
905 878 self.EnableText()
906 879 # Insert cursor
907   - self.append_mode(const.SLICE_STATE_EDITOR)
  880 + self.SetState(const.SLICE_STATE_EDITOR)
908 881  
909 882 self.__build_cross_lines()
910 883  
... ...