Commit 3b526c229b4fe68b0a494dc68bc97642cb759852
Exists in
master
and in
37 other branches
Merge pull request #31 from tfmoraes/fixes_pre_beta5
Fixes some little issues before new version
Fixes:
Only accepts boolean operations when there 2 or more masks
Watershed and Editor new shortcuts
Better watershed progress dialog
Added a tool menu
Icons to MacOSX
Combobox problems with the surface indexes
Added an Ok and a Cancel button to the Watershed config dialog
Only showing editor and watershed brush when enter in the renderviewer
Showing
111 changed files
with
371 additions
and
251 deletions
Show diff stats
icons/3D_glasses.png
icons/3D_glasses_original.png
icons/Floppy.png
icons/annotation.png
icons/bool_difference.png
icons/bool_disjunction.png
icons/bool_intersection.png
icons/bool_union.png
icons/configuration.png
icons/connectivity_largest.png
icons/connectivity_manual.png
icons/connectivity_split_all.png
icons/cross.png
icons/cross_original.png
icons/data_duplicate.png
icons/data_new.png
icons/data_remove.png
icons/file_export.png
icons/file_from_internet.png
icons/file_from_internet_original.png
icons/file_import.png
icons/file_import_original.png
icons/file_open.png
icons/file_open_original.png
icons/file_save.png
icons/file_save_original.png
icons/it_IT.png
icons/layout_data_only.png
icons/layout_data_only_original.gif
icons/layout_data_only_original.png
icons/layout_full.png
icons/layout_full_original.gif
icons/layout_full_original.png
icons/mask.png
icons/mask_small.png
icons/measure_angle.png
icons/measure_angle_original.png
icons/measure_line.png
icons/measure_line_original.png
icons/object_add.png
icons/object_add_original.png
icons/object_remove.png
icons/object_remove_original.png
icons/print.png
icons/print_original.png
icons/redo_menu.png
icons/redo_original.png
icons/redo_small.png
icons/show_task.png
icons/show_task_min.png
icons/slice.png
icons/slice_original.png
icons/slice_plane.png
icons/slice_plane_original.png
icons/splash_de.png
icons/splash_de_DE.png
icons/splash_el_GR.png
icons/splash_en.png
icons/splash_es.png
icons/splash_fr.png
icons/splash_it_IT.png
icons/splash_ko.png
icons/splash_pt.png
icons/splash_zh_TW.png
icons/surface_export.png
icons/surface_export_original.png
icons/text.png
icons/text_inverted.png
icons/text_inverted_original.png
icons/text_original.png
icons/tool_annotation.png
icons/tool_annotation_original.png
icons/tool_contrast.png
icons/tool_contrast_original.png
icons/tool_photo.png
icons/tool_photo_original.png
icons/tool_rotate.png
icons/tool_rotate_original.png
icons/tool_translate.png
icons/tool_translate_original.png
icons/tool_zoom.png
icons/tool_zoom_in.png
icons/tool_zoom_in_original.png
icons/tool_zoom_original.png
icons/tool_zoom_out.png
icons/tool_zoom_out_original.png
icons/tool_zoom_select.png
icons/tool_zoom_select_original.png
icons/undo_menu.png
icons/undo_original.png
icons/undo_small.png
icons/view_back.png
icons/view_bottom.png
icons/view_front.png
icons/view_isometric.png
icons/view_left.png
icons/view_right.png
icons/view_top.png
icons/volume_raycasting.png
icons/volume_raycasting_original.png
invesalius/constants.py
| @@ -451,8 +451,10 @@ VTK_WARNING = 0 | @@ -451,8 +451,10 @@ VTK_WARNING = 0 | ||
| 451 | 451 | ||
| 452 | [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, | 452 | [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, |
| 453 | ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, | 453 | ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, |
| 454 | -ID_PRINT_SCREENSHOT, ID_EXIT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_PREFERENCES, | ||
| 455 | -ID_DICOM_NETWORK] = [wx.NewId() for number in range(14)] | 454 | +ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_PREFERENCES, |
| 455 | +ID_DICOM_NETWORK] = [wx.NewId() for number in range(13)] | ||
| 456 | +ID_EXIT = wx.ID_EXIT | ||
| 457 | +ID_ABOUT = wx.ID_ABOUT | ||
| 456 | 458 | ||
| 457 | 459 | ||
| 458 | [ID_EDIT_UNDO, ID_EDIT_REDO, ID_EDIT_LIST] =\ | 460 | [ID_EDIT_UNDO, ID_EDIT_REDO, ID_EDIT_LIST] =\ |
| @@ -464,7 +466,6 @@ ID_DICOM_NETWORK] = [wx.NewId() for number in range(14)] | @@ -464,7 +466,6 @@ ID_DICOM_NETWORK] = [wx.NewId() for number in range(14)] | ||
| 464 | [ID_VIEW_FULL, ID_VIEW_TEXT, ID_VIEW_3D_BACKGROUND] =\ | 466 | [ID_VIEW_FULL, ID_VIEW_TEXT, ID_VIEW_3D_BACKGROUND] =\ |
| 465 | [wx.NewId() for number in range(3)] | 467 | [wx.NewId() for number in range(3)] |
| 466 | 468 | ||
| 467 | -ID_ABOUT = wx.NewId() | ||
| 468 | ID_START = wx.NewId() | 469 | ID_START = wx.NewId() |
| 469 | 470 | ||
| 470 | ID_FLIP_X = wx.NewId() | 471 | ID_FLIP_X = wx.NewId() |
| @@ -476,6 +477,7 @@ ID_SWAP_XZ = wx.NewId() | @@ -476,6 +477,7 @@ ID_SWAP_XZ = wx.NewId() | ||
| 476 | ID_SWAP_YZ = wx.NewId() | 477 | ID_SWAP_YZ = wx.NewId() |
| 477 | 478 | ||
| 478 | ID_BOOLEAN_MASK = wx.NewId() | 479 | ID_BOOLEAN_MASK = wx.NewId() |
| 480 | +ID_CLEAN_MASK = wx.NewId() | ||
| 479 | 481 | ||
| 480 | #--------------------------------------------------------- | 482 | #--------------------------------------------------------- |
| 481 | STATE_DEFAULT = 1000 | 483 | STATE_DEFAULT = 1000 |
invesalius/data/mask.py
| @@ -285,6 +285,12 @@ class Mask(): | @@ -285,6 +285,12 @@ class Mask(): | ||
| 285 | shape = shape[0] + 1, shape[1] + 1, shape[2] + 1 | 285 | shape = shape[0] + 1, shape[1] + 1, shape[2] + 1 |
| 286 | self.matrix = numpy.memmap(self.temp_file, mode='w+', dtype='uint8', shape=shape) | 286 | self.matrix = numpy.memmap(self.temp_file, mode='w+', dtype='uint8', shape=shape) |
| 287 | 287 | ||
| 288 | + def clean(self): | ||
| 289 | + self.matrix[1:, 1:, 1:] = 0 | ||
| 290 | + self.matrix[0, :, :] = 1 | ||
| 291 | + self.matrix[:, 0, :] = 1 | ||
| 292 | + self.matrix[:, :, 0] = 1 | ||
| 293 | + | ||
| 288 | def copy(self, copy_name): | 294 | def copy(self, copy_name): |
| 289 | """ | 295 | """ |
| 290 | creates and return a copy from the mask instance. | 296 | creates and return a copy from the mask instance. |
invesalius/data/slice_.py
| @@ -142,6 +142,7 @@ class Slice(object): | @@ -142,6 +142,7 @@ class Slice(object): | ||
| 142 | Publisher.subscribe(self.__set_mask_name, 'Change mask name') | 142 | Publisher.subscribe(self.__set_mask_name, 'Change mask name') |
| 143 | Publisher.subscribe(self.__show_mask, 'Show mask') | 143 | Publisher.subscribe(self.__show_mask, 'Show mask') |
| 144 | Publisher.subscribe(self.__hide_current_mask, 'Hide current mask') | 144 | Publisher.subscribe(self.__hide_current_mask, 'Hide current mask') |
| 145 | + Publisher.subscribe(self.__clean_current_mask, 'Clean current mask') | ||
| 145 | 146 | ||
| 146 | Publisher.subscribe(self.__set_current_mask_threshold_limits, | 147 | Publisher.subscribe(self.__set_current_mask_threshold_limits, |
| 147 | 'Update threshold limits') | 148 | 'Update threshold limits') |
| @@ -211,6 +212,7 @@ class Slice(object): | @@ -211,6 +212,7 @@ class Slice(object): | ||
| 211 | buffer_.discard_vtk_mask() | 212 | buffer_.discard_vtk_mask() |
| 212 | buffer_.discard_mask() | 213 | buffer_.discard_mask() |
| 213 | 214 | ||
| 215 | + Publisher.sendMessage('Show mask', (item, 0)) | ||
| 214 | Publisher.sendMessage('Reload actual slice') | 216 | Publisher.sendMessage('Reload actual slice') |
| 215 | 217 | ||
| 216 | def OnDuplicateMasks(self, pubsub_evt): | 218 | def OnDuplicateMasks(self, pubsub_evt): |
| @@ -385,6 +387,15 @@ class Slice(object): | @@ -385,6 +387,15 @@ class Slice(object): | ||
| 385 | value = False | 387 | value = False |
| 386 | Publisher.sendMessage('Show mask', (index, value)) | 388 | Publisher.sendMessage('Show mask', (index, value)) |
| 387 | 389 | ||
| 390 | + def __clean_current_mask(self, pubsub_evt): | ||
| 391 | + if self.current_mask: | ||
| 392 | + self.current_mask.clean() | ||
| 393 | + for buffer_ in self.buffer_slices.values(): | ||
| 394 | + buffer_.discard_vtk_mask() | ||
| 395 | + buffer_.discard_mask() | ||
| 396 | + self.current_mask.clear_history() | ||
| 397 | + self.current_mask.was_edited = True | ||
| 398 | + | ||
| 388 | def create_temp_mask(self): | 399 | def create_temp_mask(self): |
| 389 | temp_file = tempfile.mktemp() | 400 | temp_file = tempfile.mktemp() |
| 390 | shape = self.matrix.shape | 401 | shape = self.matrix.shape |
| @@ -1012,6 +1023,7 @@ class Slice(object): | @@ -1012,6 +1023,7 @@ class Slice(object): | ||
| 1012 | 1023 | ||
| 1013 | if show: | 1024 | if show: |
| 1014 | self.current_mask = mask | 1025 | self.current_mask = mask |
| 1026 | + Publisher.sendMessage('Show mask', (mask.index, 1)) | ||
| 1015 | Publisher.sendMessage('Change mask selected', mask.index) | 1027 | Publisher.sendMessage('Change mask selected', mask.index) |
| 1016 | Publisher.sendMessage('Update slice viewer') | 1028 | Publisher.sendMessage('Update slice viewer') |
| 1017 | 1029 |
invesalius/data/styles.py
| @@ -57,7 +57,7 @@ WATERSHED_OPERATIONS = {_("Erase"): BRUSH_ERASE, | @@ -57,7 +57,7 @@ WATERSHED_OPERATIONS = {_("Erase"): BRUSH_ERASE, | ||
| 57 | _("Background"): BRUSH_BACKGROUND,} | 57 | _("Background"): BRUSH_BACKGROUND,} |
| 58 | 58 | ||
| 59 | def get_LUT_value(data, window, level): | 59 | def get_LUT_value(data, window, level): |
| 60 | - return np.piecewise(data, | 60 | + return np.piecewise(data, |
| 61 | [data <= (level - 0.5 - (window-1)/2), | 61 | [data <= (level - 0.5 - (window-1)/2), |
| 62 | data > (level - 0.5 + (window-1)/2)], | 62 | data > (level - 0.5 + (window-1)/2)], |
| 63 | [0, 255, lambda data: ((data - (level - 0.5))/(window-1) + 0.5)*(255-0)]) | 63 | [0, 255, lambda data: ((data - (level - 0.5))/(window-1) + 0.5)*(255-0)]) |
| @@ -100,8 +100,8 @@ class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage): | @@ -100,8 +100,8 @@ class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage): | ||
| 100 | 100 | ||
| 101 | class DefaultInteractorStyle(BaseImageInteractorStyle): | 101 | class DefaultInteractorStyle(BaseImageInteractorStyle): |
| 102 | """ | 102 | """ |
| 103 | - Interactor style responsible for Default functionalities: | ||
| 104 | - * Zoom moving mouse with right button pressed; | 103 | + Interactor style responsible for Default functionalities: |
| 104 | + * Zoom moving mouse with right button pressed; | ||
| 105 | * Change the slices with the scroll. | 105 | * Change the slices with the scroll. |
| 106 | """ | 106 | """ |
| 107 | def __init__(self, viewer): | 107 | def __init__(self, viewer): |
| @@ -129,10 +129,33 @@ class DefaultInteractorStyle(BaseImageInteractorStyle): | @@ -129,10 +129,33 @@ class DefaultInteractorStyle(BaseImageInteractorStyle): | ||
| 129 | evt.StartDolly() | 129 | evt.StartDolly() |
| 130 | 130 | ||
| 131 | def OnScrollForward(self, evt, obj): | 131 | def OnScrollForward(self, evt, obj): |
| 132 | - self.viewer.OnScrollForward() | 132 | + iren = self.viewer.interactor |
| 133 | + viewer = self.viewer | ||
| 134 | + if iren.GetShiftKey(): | ||
| 135 | + opacity = viewer.slice_.opacity + 0.1 | ||
| 136 | + if opacity <= 1: | ||
| 137 | + viewer.slice_.opacity = opacity | ||
| 138 | + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
| 139 | + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
| 140 | + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
| 141 | + Publisher.sendMessage('Reload actual slice') | ||
| 142 | + else: | ||
| 143 | + self.viewer.OnScrollForward() | ||
| 133 | 144 | ||
| 134 | def OnScrollBackward(self, evt, obj): | 145 | def OnScrollBackward(self, evt, obj): |
| 135 | - self.viewer.OnScrollBackward() | 146 | + iren = self.viewer.interactor |
| 147 | + viewer = self.viewer | ||
| 148 | + | ||
| 149 | + if iren.GetShiftKey(): | ||
| 150 | + opacity = viewer.slice_.opacity - 0.1 | ||
| 151 | + if opacity >= 0.1: | ||
| 152 | + viewer.slice_.opacity = opacity | ||
| 153 | + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
| 154 | + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
| 155 | + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
| 156 | + Publisher.sendMessage('Reload actual slice') | ||
| 157 | + else: | ||
| 158 | + self.viewer.OnScrollBackward() | ||
| 136 | 159 | ||
| 137 | 160 | ||
| 138 | class CrossInteractorStyle(DefaultInteractorStyle): | 161 | class CrossInteractorStyle(DefaultInteractorStyle): |
| @@ -182,7 +205,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -182,7 +205,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
| 182 | # Forcing focal point to be setted in the center of the pixel. | 205 | # Forcing focal point to be setted in the center of the pixel. |
| 183 | coord_cross = self.slice_actor.GetInput().GetPoint(position) | 206 | coord_cross = self.slice_actor.GetInput().GetPoint(position) |
| 184 | 207 | ||
| 185 | - coord = self.calcultate_scroll_position(position) | 208 | + coord = self.calcultate_scroll_position(position) |
| 186 | self.ScrollSlice(coord) | 209 | self.ScrollSlice(coord) |
| 187 | 210 | ||
| 188 | Publisher.sendMessage('Update cross position', coord_cross) | 211 | Publisher.sendMessage('Update cross position', coord_cross) |
| @@ -190,7 +213,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -190,7 +213,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
| 190 | coord_cross) | 213 | coord_cross) |
| 191 | Publisher.sendMessage('Set camera in volume', coord_cross) | 214 | Publisher.sendMessage('Set camera in volume', coord_cross) |
| 192 | Publisher.sendMessage('Render volume viewer') | 215 | Publisher.sendMessage('Render volume viewer') |
| 193 | - | 216 | + |
| 194 | iren.Render() | 217 | iren.Render() |
| 195 | 218 | ||
| 196 | 219 | ||
| @@ -292,7 +315,7 @@ class WWWLInteractorStyle(DefaultInteractorStyle): | @@ -292,7 +315,7 @@ class WWWLInteractorStyle(DefaultInteractorStyle): | ||
| 292 | const.WINDOW_LEVEL['Manual'] = (self.acum_achange_window,\ | 315 | const.WINDOW_LEVEL['Manual'] = (self.acum_achange_window,\ |
| 293 | self.acum_achange_level) | 316 | self.acum_achange_level) |
| 294 | Publisher.sendMessage('Check window and level other') | 317 | Publisher.sendMessage('Check window and level other') |
| 295 | - Publisher.sendMessage('Update window level value',(self.acum_achange_window, | 318 | + Publisher.sendMessage('Update window level value',(self.acum_achange_window, |
| 296 | self.acum_achange_level)) | 319 | self.acum_achange_level)) |
| 297 | #Necessary update the slice plane in the volume case exists | 320 | #Necessary update the slice plane in the volume case exists |
| 298 | Publisher.sendMessage('Update slice viewer') | 321 | Publisher.sendMessage('Update slice viewer') |
| @@ -339,7 +362,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle): | @@ -339,7 +362,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle): | ||
| 339 | slice_number = self.slice_data.number | 362 | slice_number = self.slice_data.number |
| 340 | self.picker.Pick(x, y, 0, render) | 363 | self.picker.Pick(x, y, 0, render) |
| 341 | x, y, z = self.picker.GetPickPosition() | 364 | x, y, z = self.picker.GetPickPosition() |
| 342 | - if self.picker.GetViewProp(): | 365 | + if self.picker.GetViewProp(): |
| 343 | Publisher.sendMessage("Add measurement point", | 366 | Publisher.sendMessage("Add measurement point", |
| 344 | ((x, y,z), const.LINEAR, | 367 | ((x, y,z), const.LINEAR, |
| 345 | ORIENTATIONS[self.orientation], | 368 | ORIENTATIONS[self.orientation], |
| @@ -383,7 +406,7 @@ class AngularMeasureInteractorStyle(DefaultInteractorStyle): | @@ -383,7 +406,7 @@ class AngularMeasureInteractorStyle(DefaultInteractorStyle): | ||
| 383 | slice_number = self.slice_data.number | 406 | slice_number = self.slice_data.number |
| 384 | self.picker.Pick(x, y, 0, render) | 407 | self.picker.Pick(x, y, 0, render) |
| 385 | x, y, z = self.picker.GetPickPosition() | 408 | x, y, z = self.picker.GetPickPosition() |
| 386 | - if self.picker.GetViewProp(): | 409 | + if self.picker.GetViewProp(): |
| 387 | Publisher.sendMessage("Add measurement point", | 410 | Publisher.sendMessage("Add measurement point", |
| 388 | ((x, y,z), const.ANGULAR, | 411 | ((x, y,z), const.ANGULAR, |
| 389 | ORIENTATIONS[self.orientation], | 412 | ORIENTATIONS[self.orientation], |
| @@ -434,7 +457,7 @@ class SpinInteractorStyle(DefaultInteractorStyle): | @@ -434,7 +457,7 @@ class SpinInteractorStyle(DefaultInteractorStyle): | ||
| 434 | ren = iren.FindPokedRenderer(mouse_x, mouse_y) | 457 | ren = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 435 | cam = ren.GetActiveCamera() | 458 | cam = ren.GetActiveCamera() |
| 436 | if (self.left_pressed): | 459 | if (self.left_pressed): |
| 437 | - self.viewer.UpdateTextDirection(cam) | 460 | + self.viewer.UpdateTextDirection(cam) |
| 438 | obj.Spin() | 461 | obj.Spin() |
| 439 | obj.OnRightButtonDown() | 462 | obj.OnRightButtonDown() |
| 440 | 463 | ||
| @@ -456,7 +479,7 @@ class ZoomInteractorStyle(DefaultInteractorStyle): | @@ -456,7 +479,7 @@ class ZoomInteractorStyle(DefaultInteractorStyle): | ||
| 456 | """ | 479 | """ |
| 457 | def __init__(self, viewer): | 480 | def __init__(self, viewer): |
| 458 | DefaultInteractorStyle.__init__(self, viewer) | 481 | DefaultInteractorStyle.__init__(self, viewer) |
| 459 | - | 482 | + |
| 460 | self.viewer = viewer | 483 | self.viewer = viewer |
| 461 | 484 | ||
| 462 | self.AddObserver("MouseMoveEvent", self.OnZoomMoveLeft) | 485 | self.AddObserver("MouseMoveEvent", self.OnZoomMoveLeft) |
| @@ -532,6 +555,14 @@ class ChangeSliceInteractorStyle(DefaultInteractorStyle): | @@ -532,6 +555,14 @@ class ChangeSliceInteractorStyle(DefaultInteractorStyle): | ||
| 532 | self.last_position = position[1] | 555 | self.last_position = position[1] |
| 533 | 556 | ||
| 534 | 557 | ||
| 558 | +class EditorConfig(object): | ||
| 559 | + __metaclass__= utils.Singleton | ||
| 560 | + def __init__(self): | ||
| 561 | + self.operation = const.BRUSH_THRESH | ||
| 562 | + self.cursor_type = const.BRUSH_CIRCLE | ||
| 563 | + self.cursor_size = const.BRUSH_SIZE | ||
| 564 | + | ||
| 565 | + | ||
| 535 | class EditorInteractorStyle(DefaultInteractorStyle): | 566 | class EditorInteractorStyle(DefaultInteractorStyle): |
| 536 | def __init__(self, viewer): | 567 | def __init__(self, viewer): |
| 537 | DefaultInteractorStyle.__init__(self, viewer) | 568 | DefaultInteractorStyle.__init__(self, viewer) |
| @@ -539,6 +570,8 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -539,6 +570,8 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 539 | self.viewer = viewer | 570 | self.viewer = viewer |
| 540 | self.orientation = self.viewer.orientation | 571 | self.orientation = self.viewer.orientation |
| 541 | 572 | ||
| 573 | + self.config = EditorConfig() | ||
| 574 | + | ||
| 542 | self.picker = vtk.vtkWorldPointPicker() | 575 | self.picker = vtk.vtkWorldPointPicker() |
| 543 | 576 | ||
| 544 | self.AddObserver("EnterEvent", self.OnEnterInteractor) | 577 | self.AddObserver("EnterEvent", self.OnEnterInteractor) |
| @@ -553,13 +586,55 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -553,13 +586,55 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 553 | self.AddObserver("MouseWheelForwardEvent",self.EOnScrollForward) | 586 | self.AddObserver("MouseWheelForwardEvent",self.EOnScrollForward) |
| 554 | self.AddObserver("MouseWheelBackwardEvent", self.EOnScrollBackward) | 587 | self.AddObserver("MouseWheelBackwardEvent", self.EOnScrollBackward) |
| 555 | 588 | ||
| 589 | + Publisher.subscribe(self.set_bsize, 'Set edition brush size') | ||
| 590 | + Publisher.subscribe(self.set_bformat, 'Set brush format') | ||
| 591 | + Publisher.subscribe(self.set_boperation, 'Set edition operation') | ||
| 592 | + | ||
| 593 | + self._set_cursor() | ||
| 594 | + self.viewer.slice_data.cursor.Show(0) | ||
| 595 | + | ||
| 596 | + def CleanUp(self): | ||
| 597 | + Publisher.unsubscribe(self.set_bsize, 'Set edition brush size') | ||
| 598 | + Publisher.unsubscribe(self.set_bformat, 'Set brush format') | ||
| 599 | + Publisher.unsubscribe(self.set_boperation, 'Set edition operation') | ||
| 600 | + | ||
| 601 | + def set_bsize(self, pubsub_evt): | ||
| 602 | + size = pubsub_evt.data | ||
| 603 | + self.config.cursor_size = size | ||
| 604 | + self.viewer.slice_data.cursor.SetSize(size) | ||
| 605 | + | ||
| 606 | + def set_bformat(self, pubsub_evt): | ||
| 607 | + self.config.cursor_type = pubsub_evt.data | ||
| 608 | + self._set_cursor() | ||
| 609 | + | ||
| 610 | + def set_boperation(self, pubsub_evt): | ||
| 611 | + self.config.operation = pubsub_evt.data | ||
| 612 | + | ||
| 613 | + def _set_cursor(self): | ||
| 614 | + if self.config.cursor_type == const.BRUSH_SQUARE: | ||
| 615 | + cursor = ca.CursorRectangle() | ||
| 616 | + elif self.config.cursor_type == const.BRUSH_CIRCLE: | ||
| 617 | + cursor = ca.CursorCircle() | ||
| 618 | + | ||
| 619 | + cursor.SetOrientation(self.orientation) | ||
| 620 | + n = self.viewer.slice_data.number | ||
| 621 | + coordinates = {"SAGITAL": [n, 0, 0], | ||
| 622 | + "CORONAL": [0, n, 0], | ||
| 623 | + "AXIAL": [0, 0, n]} | ||
| 624 | + cursor.SetPosition(coordinates[self.orientation]) | ||
| 625 | + spacing = self.viewer.slice_.spacing | ||
| 626 | + cursor.SetSpacing(spacing) | ||
| 627 | + cursor.SetColour(self.viewer._brush_cursor_colour) | ||
| 628 | + cursor.SetSize(self.config.cursor_size) | ||
| 629 | + self.viewer.slice_data.SetCursor(cursor) | ||
| 630 | + | ||
| 556 | def OnEnterInteractor(self, obj, evt): | 631 | def OnEnterInteractor(self, obj, evt): |
| 557 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 632 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 558 | return | 633 | return |
| 559 | self.viewer.slice_data.cursor.Show() | 634 | self.viewer.slice_data.cursor.Show() |
| 560 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | 635 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) |
| 561 | self.viewer.interactor.Render() | 636 | self.viewer.interactor.Render() |
| 562 | - | 637 | + |
| 563 | def OnLeaveInteractor(self, obj, evt): | 638 | def OnLeaveInteractor(self, obj, evt): |
| 564 | self.viewer.slice_data.cursor.Show(0) | 639 | self.viewer.slice_data.cursor.Show(0) |
| 565 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 640 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
| @@ -569,11 +644,10 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -569,11 +644,10 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 569 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 644 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 570 | return | 645 | return |
| 571 | 646 | ||
| 572 | - | ||
| 573 | viewer = self.viewer | 647 | viewer = self.viewer |
| 574 | iren = viewer.interactor | 648 | iren = viewer.interactor |
| 575 | 649 | ||
| 576 | - operation = viewer._brush_cursor_op | 650 | + operation = self.config.operation |
| 577 | if operation == const.BRUSH_THRESH: | 651 | if operation == const.BRUSH_THRESH: |
| 578 | if iren.GetControlKey(): | 652 | if iren.GetControlKey(): |
| 579 | if iren.GetShiftKey(): | 653 | if iren.GetShiftKey(): |
| @@ -590,7 +664,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -590,7 +664,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 590 | operation = const.BRUSH_ERASE | 664 | operation = const.BRUSH_ERASE |
| 591 | 665 | ||
| 592 | viewer._set_editor_cursor_visibility(1) | 666 | viewer._set_editor_cursor_visibility(1) |
| 593 | - | 667 | + |
| 594 | mouse_x, mouse_y = iren.GetEventPosition() | 668 | mouse_x, mouse_y = iren.GetEventPosition() |
| 595 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 669 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 596 | slice_data = viewer.get_slice_data(render) | 670 | slice_data = viewer.get_slice_data(render) |
| @@ -601,10 +675,10 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -601,10 +675,10 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 601 | slice_data.cursor.Show() | 675 | slice_data.cursor.Show() |
| 602 | 676 | ||
| 603 | self.picker.Pick(mouse_x, mouse_y, 0, render) | 677 | self.picker.Pick(mouse_x, mouse_y, 0, render) |
| 604 | - | 678 | + |
| 605 | coord = self.get_coordinate_cursor() | 679 | coord = self.get_coordinate_cursor() |
| 606 | position = slice_data.actor.GetInput().FindPoint(coord) | 680 | position = slice_data.actor.GetInput().FindPoint(coord) |
| 607 | - | 681 | + |
| 608 | if position != -1: | 682 | if position != -1: |
| 609 | coord = slice_data.actor.GetInput().GetPoint(position) | 683 | coord = slice_data.actor.GetInput().GetPoint(position) |
| 610 | 684 | ||
| @@ -630,12 +704,12 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -630,12 +704,12 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 630 | iren = viewer.interactor | 704 | iren = viewer.interactor |
| 631 | 705 | ||
| 632 | viewer._set_editor_cursor_visibility(1) | 706 | viewer._set_editor_cursor_visibility(1) |
| 633 | - | 707 | + |
| 634 | mouse_x, mouse_y = iren.GetEventPosition() | 708 | mouse_x, mouse_y = iren.GetEventPosition() |
| 635 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 709 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 636 | slice_data = viewer.get_slice_data(render) | 710 | slice_data = viewer.get_slice_data(render) |
| 637 | 711 | ||
| 638 | - operation = viewer._brush_cursor_op | 712 | + operation = self.config.operation |
| 639 | if operation == const.BRUSH_THRESH: | 713 | if operation == const.BRUSH_THRESH: |
| 640 | if iren.GetControlKey(): | 714 | if iren.GetControlKey(): |
| 641 | if iren.GetShiftKey(): | 715 | if iren.GetShiftKey(): |
| @@ -656,12 +730,12 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -656,12 +730,12 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 656 | #i.cursor.Show(0) | 730 | #i.cursor.Show(0) |
| 657 | 731 | ||
| 658 | self.picker.Pick(mouse_x, mouse_y, 0, render) | 732 | self.picker.Pick(mouse_x, mouse_y, 0, render) |
| 659 | - | 733 | + |
| 660 | #if (self.pick.GetViewProp()): | 734 | #if (self.pick.GetViewProp()): |
| 661 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | 735 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) |
| 662 | #else: | 736 | #else: |
| 663 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 737 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
| 664 | - | 738 | + |
| 665 | coord = self.get_coordinate_cursor() | 739 | coord = self.get_coordinate_cursor() |
| 666 | position = viewer.slice_data.actor.GetInput().FindPoint(coord) | 740 | position = viewer.slice_data.actor.GetInput().FindPoint(coord) |
| 667 | 741 | ||
| @@ -672,7 +746,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -672,7 +746,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 672 | coord = slice_data.actor.GetInput().GetPoint(position) | 746 | coord = slice_data.actor.GetInput().GetPoint(position) |
| 673 | slice_data.cursor.SetPosition(coord) | 747 | slice_data.cursor.SetPosition(coord) |
| 674 | #self.__update_cursor_position(slice_data, coord) | 748 | #self.__update_cursor_position(slice_data, coord) |
| 675 | - | 749 | + |
| 676 | if (self.left_pressed): | 750 | if (self.left_pressed): |
| 677 | cursor = slice_data.cursor | 751 | cursor = slice_data.cursor |
| 678 | position = slice_data.actor.GetInput().FindPoint(coord) | 752 | position = slice_data.actor.GetInput().FindPoint(coord) |
| @@ -680,7 +754,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -680,7 +754,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 680 | 754 | ||
| 681 | if position < 0: | 755 | if position < 0: |
| 682 | position = viewer.calculate_matrix_position(coord) | 756 | position = viewer.calculate_matrix_position(coord) |
| 683 | - | 757 | + |
| 684 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), | 758 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), |
| 685 | position, radius, self.orientation) | 759 | position, radius, self.orientation) |
| 686 | # TODO: To create a new function to reload images to viewer. | 760 | # TODO: To create a new function to reload images to viewer. |
| @@ -698,32 +772,35 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -698,32 +772,35 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 698 | 772 | ||
| 699 | def EOnScrollForward(self, evt, obj): | 773 | def EOnScrollForward(self, evt, obj): |
| 700 | iren = self.viewer.interactor | 774 | iren = self.viewer.interactor |
| 775 | + viewer = self.viewer | ||
| 701 | if iren.GetControlKey(): | 776 | if iren.GetControlKey(): |
| 702 | mouse_x, mouse_y = iren.GetEventPosition() | 777 | mouse_x, mouse_y = iren.GetEventPosition() |
| 703 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 778 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 704 | slice_data = self.viewer.get_slice_data(render) | 779 | slice_data = self.viewer.get_slice_data(render) |
| 705 | cursor = slice_data.cursor | 780 | cursor = slice_data.cursor |
| 706 | size = cursor.radius * 2 | 781 | size = cursor.radius * 2 |
| 782 | + size += 1 | ||
| 707 | 783 | ||
| 708 | - if size < 100: | ||
| 709 | - Publisher.sendMessage('Set edition brush size', size + 1) | 784 | + if size <= 100: |
| 785 | + Publisher.sendMessage('Set edition brush size', size) | ||
| 710 | cursor.SetPosition(cursor.position) | 786 | cursor.SetPosition(cursor.position) |
| 711 | self.viewer.interactor.Render() | 787 | self.viewer.interactor.Render() |
| 712 | - | ||
| 713 | else: | 788 | else: |
| 714 | self.OnScrollForward(obj, evt) | 789 | self.OnScrollForward(obj, evt) |
| 715 | 790 | ||
| 716 | def EOnScrollBackward(self, evt, obj): | 791 | def EOnScrollBackward(self, evt, obj): |
| 717 | iren = self.viewer.interactor | 792 | iren = self.viewer.interactor |
| 793 | + viewer = self.viewer | ||
| 718 | if iren.GetControlKey(): | 794 | if iren.GetControlKey(): |
| 719 | mouse_x, mouse_y = iren.GetEventPosition() | 795 | mouse_x, mouse_y = iren.GetEventPosition() |
| 720 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 796 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 721 | slice_data = self.viewer.get_slice_data(render) | 797 | slice_data = self.viewer.get_slice_data(render) |
| 722 | cursor = slice_data.cursor | 798 | cursor = slice_data.cursor |
| 723 | size = cursor.radius * 2 | 799 | size = cursor.radius * 2 |
| 800 | + size -= 1 | ||
| 724 | 801 | ||
| 725 | if size > 0: | 802 | if size > 0: |
| 726 | - Publisher.sendMessage('Set edition brush size', size - 1) | 803 | + Publisher.sendMessage('Set edition brush size', size) |
| 727 | cursor.SetPosition(cursor.position) | 804 | cursor.SetPosition(cursor.position) |
| 728 | self.viewer.interactor.Render() | 805 | self.viewer.interactor.Render() |
| 729 | else: | 806 | else: |
| @@ -742,41 +819,29 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -742,41 +819,29 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 742 | return x, y, z | 819 | return x, y, z |
| 743 | 820 | ||
| 744 | 821 | ||
| 745 | -class WatershedProgressWindow(wx.Frame): | ||
| 746 | - def __init__(self, process, parent=None): | ||
| 747 | - wx.Frame.__init__(self, parent, -1) | 822 | +class WatershedProgressWindow(object): |
| 823 | + def __init__(self, process): | ||
| 748 | self.process = process | 824 | self.process = process |
| 749 | - self._build_gui() | ||
| 750 | - self._bind_wx_events() | ||
| 751 | - self.timer = wx.Timer(self) | ||
| 752 | - self.timer.Start(1000) | ||
| 753 | - | ||
| 754 | - def _build_gui(self): | ||
| 755 | - self.gauge = wx.Gauge(self, -1, 100) | ||
| 756 | - self.btn_cancel = wx.Button(self, wx.ID_CANCEL) | ||
| 757 | - | ||
| 758 | - sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 759 | - sizer.Add(wx.StaticText(self, -1, _("Applying watershed"))) | ||
| 760 | - sizer.Add(self.gauge, 0, wx.EXPAND) | ||
| 761 | - sizer.Add(self.btn_cancel, 0, wx.ALIGN_LEFT) | ||
| 762 | - | ||
| 763 | - self.SetSizer(sizer) | ||
| 764 | - sizer.Fit(self) | ||
| 765 | - self.Layout() | ||
| 766 | - | ||
| 767 | - def __del__(self): | ||
| 768 | - self.timer.Stop() | ||
| 769 | - | ||
| 770 | - def _bind_wx_events(self): | ||
| 771 | - self.Bind(wx.EVT_TIMER, self.TimeHandler) | ||
| 772 | - self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_cancel) | ||
| 773 | - | ||
| 774 | - def on_cancel(self, evt): | ||
| 775 | - self.timer.Stop() | 825 | + self.title = "InVesalius 3" |
| 826 | + self.msg = _("Applying watershed ...") | ||
| 827 | + self.style = wx.PD_APP_MODAL | wx.PD_APP_MODAL | wx.PD_CAN_ABORT | ||
| 828 | + | ||
| 829 | + self.dlg = wx.ProgressDialog(self.title, | ||
| 830 | + self.msg, | ||
| 831 | + parent = None, | ||
| 832 | + style = self.style) | ||
| 833 | + | ||
| 834 | + self.dlg.Bind(wx.EVT_BUTTON, self.Cancel) | ||
| 835 | + self.dlg.Show() | ||
| 836 | + | ||
| 837 | + def Cancel(self, evt): | ||
| 776 | self.process.terminate() | 838 | self.process.terminate() |
| 777 | 839 | ||
| 778 | - def TimeHandler(self, evt): | ||
| 779 | - self.gauge.Pulse() | 840 | + def Update(self): |
| 841 | + self.dlg.Pulse() | ||
| 842 | + | ||
| 843 | + def Close(self): | ||
| 844 | + self.dlg.Destroy() | ||
| 780 | 845 | ||
| 781 | 846 | ||
| 782 | class WatershedConfig(object): | 847 | class WatershedConfig(object): |
| @@ -851,6 +916,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -851,6 +916,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 851 | Publisher.subscribe(self.set_bformat, 'Set watershed brush format') | 916 | Publisher.subscribe(self.set_bformat, 'Set watershed brush format') |
| 852 | 917 | ||
| 853 | self._set_cursor() | 918 | self._set_cursor() |
| 919 | + self.viewer.slice_data.cursor.Show(0) | ||
| 854 | 920 | ||
| 855 | def SetUp(self): | 921 | def SetUp(self): |
| 856 | mask = self.viewer.slice_.current_mask.matrix | 922 | mask = self.viewer.slice_.current_mask.matrix |
| @@ -898,7 +964,6 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -898,7 +964,6 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 898 | cursor.SetColour(self.viewer._brush_cursor_colour) | 964 | cursor.SetColour(self.viewer._brush_cursor_colour) |
| 899 | cursor.SetSize(self.config.cursor_size) | 965 | cursor.SetSize(self.config.cursor_size) |
| 900 | self.viewer.slice_data.SetCursor(cursor) | 966 | self.viewer.slice_data.SetCursor(cursor) |
| 901 | - self.viewer.interactor.Render() | ||
| 902 | 967 | ||
| 903 | def set_bsize(self, pubsub_evt): | 968 | def set_bsize(self, pubsub_evt): |
| 904 | size = pubsub_evt.data | 969 | size = pubsub_evt.data |
| @@ -913,42 +978,50 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -913,42 +978,50 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 913 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 978 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 914 | return | 979 | return |
| 915 | self.viewer.slice_data.cursor.Show() | 980 | self.viewer.slice_data.cursor.Show() |
| 916 | - #self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | 981 | + self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) |
| 917 | self.viewer.interactor.Render() | 982 | self.viewer.interactor.Render() |
| 918 | - | 983 | + |
| 919 | def OnLeaveInteractor(self, obj, evt): | 984 | def OnLeaveInteractor(self, obj, evt): |
| 920 | self.viewer.slice_data.cursor.Show(0) | 985 | self.viewer.slice_data.cursor.Show(0) |
| 921 | - #self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 986 | + self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
| 922 | self.viewer.interactor.Render() | 987 | self.viewer.interactor.Render() |
| 923 | 988 | ||
| 924 | def WOnScrollBackward(self, obj, evt): | 989 | def WOnScrollBackward(self, obj, evt): |
| 990 | + iren = self.viewer.interactor | ||
| 925 | viewer = self.viewer | 991 | viewer = self.viewer |
| 926 | - iren = viewer.interactor | ||
| 927 | if iren.GetControlKey(): | 992 | if iren.GetControlKey(): |
| 928 | - if viewer.slice_.opacity > 0: | ||
| 929 | - viewer.slice_.opacity -= 0.1 | ||
| 930 | - self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
| 931 | - self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
| 932 | - self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
| 933 | - viewer.OnScrollBar() | 993 | + mouse_x, mouse_y = iren.GetEventPosition() |
| 994 | + render = iren.FindPokedRenderer(mouse_x, mouse_y) | ||
| 995 | + slice_data = self.viewer.get_slice_data(render) | ||
| 996 | + cursor = slice_data.cursor | ||
| 997 | + size = cursor.radius * 2 | ||
| 998 | + size -= 1 | ||
| 999 | + | ||
| 1000 | + if size > 0: | ||
| 1001 | + Publisher.sendMessage('Set watershed brush size', size) | ||
| 1002 | + cursor.SetPosition(cursor.position) | ||
| 1003 | + self.viewer.interactor.Render() | ||
| 934 | else: | 1004 | else: |
| 935 | self.OnScrollBackward(obj, evt) | 1005 | self.OnScrollBackward(obj, evt) |
| 936 | 1006 | ||
| 937 | - | ||
| 938 | def WOnScrollForward(self, obj, evt): | 1007 | def WOnScrollForward(self, obj, evt): |
| 1008 | + iren = self.viewer.interactor | ||
| 939 | viewer = self.viewer | 1009 | viewer = self.viewer |
| 940 | - iren = viewer.interactor | ||
| 941 | if iren.GetControlKey(): | 1010 | if iren.GetControlKey(): |
| 942 | - if viewer.slice_.opacity < 1: | ||
| 943 | - viewer.slice_.opacity += 0.1 | ||
| 944 | - self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
| 945 | - self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
| 946 | - self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
| 947 | - viewer.OnScrollBar() | 1011 | + mouse_x, mouse_y = iren.GetEventPosition() |
| 1012 | + render = iren.FindPokedRenderer(mouse_x, mouse_y) | ||
| 1013 | + slice_data = self.viewer.get_slice_data(render) | ||
| 1014 | + cursor = slice_data.cursor | ||
| 1015 | + size = cursor.radius * 2 | ||
| 1016 | + size += 1 | ||
| 1017 | + | ||
| 1018 | + if size <= 100: | ||
| 1019 | + Publisher.sendMessage('Set watershed brush size', size) | ||
| 1020 | + cursor.SetPosition(cursor.position) | ||
| 1021 | + self.viewer.interactor.Render() | ||
| 948 | else: | 1022 | else: |
| 949 | self.OnScrollForward(obj, evt) | 1023 | self.OnScrollForward(obj, evt) |
| 950 | 1024 | ||
| 951 | - | ||
| 952 | def OnBrushClick(self, obj, evt): | 1025 | def OnBrushClick(self, obj, evt): |
| 953 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 1026 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 954 | return | 1027 | return |
| @@ -957,7 +1030,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -957,7 +1030,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 957 | iren = viewer.interactor | 1030 | iren = viewer.interactor |
| 958 | 1031 | ||
| 959 | viewer._set_editor_cursor_visibility(1) | 1032 | viewer._set_editor_cursor_visibility(1) |
| 960 | - | 1033 | + |
| 961 | mouse_x, mouse_y = iren.GetEventPosition() | 1034 | mouse_x, mouse_y = iren.GetEventPosition() |
| 962 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 1035 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 963 | slice_data = viewer.get_slice_data(render) | 1036 | slice_data = viewer.get_slice_data(render) |
| @@ -968,10 +1041,10 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -968,10 +1041,10 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 968 | slice_data.cursor.Show() | 1041 | slice_data.cursor.Show() |
| 969 | 1042 | ||
| 970 | self.picker.Pick(mouse_x, mouse_y, 0, render) | 1043 | self.picker.Pick(mouse_x, mouse_y, 0, render) |
| 971 | - | 1044 | + |
| 972 | coord = self.get_coordinate_cursor() | 1045 | coord = self.get_coordinate_cursor() |
| 973 | position = slice_data.actor.GetInput().FindPoint(coord) | 1046 | position = slice_data.actor.GetInput().FindPoint(coord) |
| 974 | - | 1047 | + |
| 975 | if position != -1: | 1048 | if position != -1: |
| 976 | coord = slice_data.actor.GetInput().GetPoint(position) | 1049 | coord = slice_data.actor.GetInput().GetPoint(position) |
| 977 | 1050 | ||
| @@ -1017,7 +1090,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1017,7 +1090,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1017 | iren = viewer.interactor | 1090 | iren = viewer.interactor |
| 1018 | 1091 | ||
| 1019 | viewer._set_editor_cursor_visibility(1) | 1092 | viewer._set_editor_cursor_visibility(1) |
| 1020 | - | 1093 | + |
| 1021 | mouse_x, mouse_y = iren.GetEventPosition() | 1094 | mouse_x, mouse_y = iren.GetEventPosition() |
| 1022 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 1095 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 1023 | slice_data = viewer.get_slice_data(render) | 1096 | slice_data = viewer.get_slice_data(render) |
| @@ -1027,12 +1100,12 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1027,12 +1100,12 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1027 | #i.cursor.Show(0) | 1100 | #i.cursor.Show(0) |
| 1028 | 1101 | ||
| 1029 | self.picker.Pick(mouse_x, mouse_y, 0, render) | 1102 | self.picker.Pick(mouse_x, mouse_y, 0, render) |
| 1030 | - | 1103 | + |
| 1031 | #if (self.pick.GetViewProp()): | 1104 | #if (self.pick.GetViewProp()): |
| 1032 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | 1105 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) |
| 1033 | #else: | 1106 | #else: |
| 1034 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 1107 | #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
| 1035 | - | 1108 | + |
| 1036 | coord = self.get_coordinate_cursor() | 1109 | coord = self.get_coordinate_cursor() |
| 1037 | position = viewer.slice_data.actor.GetInput().FindPoint(coord) | 1110 | position = viewer.slice_data.actor.GetInput().FindPoint(coord) |
| 1038 | 1111 | ||
| @@ -1043,7 +1116,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1043,7 +1116,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1043 | coord = slice_data.actor.GetInput().GetPoint(position) | 1116 | coord = slice_data.actor.GetInput().GetPoint(position) |
| 1044 | slice_data.cursor.SetPosition(coord) | 1117 | slice_data.cursor.SetPosition(coord) |
| 1045 | #self.__update_cursor_position(slice_data, coord) | 1118 | #self.__update_cursor_position(slice_data, coord) |
| 1046 | - | 1119 | + |
| 1047 | if (self.left_pressed): | 1120 | if (self.left_pressed): |
| 1048 | cursor = slice_data.cursor | 1121 | cursor = slice_data.cursor |
| 1049 | position = slice_data.actor.GetInput().FindPoint(coord) | 1122 | position = slice_data.actor.GetInput().FindPoint(coord) |
| @@ -1104,7 +1177,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1104,7 +1177,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1104 | 1177 | ||
| 1105 | ww = self.viewer.slice_.window_width | 1178 | ww = self.viewer.slice_.window_width |
| 1106 | wl = self.viewer.slice_.window_level | 1179 | wl = self.viewer.slice_.window_level |
| 1107 | - | 1180 | + |
| 1108 | if BRUSH_BACKGROUND in markers and BRUSH_FOREGROUND in markers: | 1181 | if BRUSH_BACKGROUND in markers and BRUSH_FOREGROUND in markers: |
| 1109 | #w_algorithm = WALGORITHM[self.config.algorithm] | 1182 | #w_algorithm = WALGORITHM[self.config.algorithm] |
| 1110 | bstruct = generate_binary_structure(2, CON2D[self.config.con_2d]) | 1183 | bstruct = generate_binary_structure(2, CON2D[self.config.con_2d]) |
| @@ -1146,9 +1219,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1146,9 +1219,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1146 | 1219 | ||
| 1147 | self.viewer.slice_.current_mask.was_edited = True | 1220 | self.viewer.slice_.current_mask.was_edited = True |
| 1148 | self.viewer.slice_.current_mask.clear_history() | 1221 | self.viewer.slice_.current_mask.clear_history() |
| 1149 | - Publisher.sendMessage('Reload actual slice') | ||
| 1150 | - else: | ||
| 1151 | - self.viewer.OnScrollBar(update3D=False) | 1222 | + Publisher.sendMessage('Reload actual slice') |
| 1152 | 1223 | ||
| 1153 | def get_coordinate_cursor(self): | 1224 | def get_coordinate_cursor(self): |
| 1154 | # Find position | 1225 | # Find position |
| @@ -1253,18 +1324,14 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1253,18 +1324,14 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
| 1253 | self.config.use_ww_wl, wl, ww, q)) | 1324 | self.config.use_ww_wl, wl, ww, q)) |
| 1254 | 1325 | ||
| 1255 | wp = WatershedProgressWindow(p) | 1326 | wp = WatershedProgressWindow(p) |
| 1256 | - wp.Center(wx.BOTH) | ||
| 1257 | - wp.Show() | ||
| 1258 | - wp.MakeModal() | ||
| 1259 | - | ||
| 1260 | p.start() | 1327 | p.start() |
| 1261 | 1328 | ||
| 1262 | while q.empty() and p.is_alive(): | 1329 | while q.empty() and p.is_alive(): |
| 1263 | time.sleep(0.5) | 1330 | time.sleep(0.5) |
| 1331 | + wp.Update() | ||
| 1264 | wx.Yield() | 1332 | wx.Yield() |
| 1265 | 1333 | ||
| 1266 | - wp.MakeModal(False) | ||
| 1267 | - wp.Destroy() | 1334 | + wp.Close() |
| 1268 | del wp | 1335 | del wp |
| 1269 | 1336 | ||
| 1270 | if q.empty(): | 1337 | if q.empty(): |
invesalius/data/surface.py
| @@ -84,7 +84,7 @@ class Surface(): | @@ -84,7 +84,7 @@ class Surface(): | ||
| 84 | #plist_filepath = os.path.join(dir_temp, filename + '.plist') | 84 | #plist_filepath = os.path.join(dir_temp, filename + '.plist') |
| 85 | temp_plist = tempfile.mktemp() | 85 | temp_plist = tempfile.mktemp() |
| 86 | plistlib.writePlist(surface, temp_plist) | 86 | plistlib.writePlist(surface, temp_plist) |
| 87 | - | 87 | + |
| 88 | filelist[temp_plist] = plist_filename | 88 | filelist[temp_plist] = plist_filename |
| 89 | 89 | ||
| 90 | return plist_filename | 90 | return plist_filename |
| @@ -145,7 +145,7 @@ class SurfaceManager(): | @@ -145,7 +145,7 @@ class SurfaceManager(): | ||
| 145 | Publisher.subscribe(self.OnDuplicate, "Duplicate surfaces") | 145 | Publisher.subscribe(self.OnDuplicate, "Duplicate surfaces") |
| 146 | Publisher.subscribe(self.OnRemove,"Remove surfaces") | 146 | Publisher.subscribe(self.OnRemove,"Remove surfaces") |
| 147 | Publisher.subscribe(self.UpdateSurfaceInterpolation, 'Update Surface Interpolation') | 147 | Publisher.subscribe(self.UpdateSurfaceInterpolation, 'Update Surface Interpolation') |
| 148 | - | 148 | + |
| 149 | def OnDuplicate(self, pubsub_evt): | 149 | def OnDuplicate(self, pubsub_evt): |
| 150 | selected_items = pubsub_evt.data | 150 | selected_items = pubsub_evt.data |
| 151 | proj = prj.Project() | 151 | proj = prj.Project() |
| @@ -155,7 +155,7 @@ class SurfaceManager(): | @@ -155,7 +155,7 @@ class SurfaceManager(): | ||
| 155 | # compute copy name | 155 | # compute copy name |
| 156 | name = original_surface.name | 156 | name = original_surface.name |
| 157 | names_list = [surface_dict[i].name for i in surface_dict.keys()] | 157 | names_list = [surface_dict[i].name for i in surface_dict.keys()] |
| 158 | - new_name = utl.next_copy_name(name, names_list) | 158 | + new_name = utl.next_copy_name(name, names_list) |
| 159 | # create new mask | 159 | # create new mask |
| 160 | self.CreateSurfaceFromPolydata(polydata = original_surface.polydata, | 160 | self.CreateSurfaceFromPolydata(polydata = original_surface.polydata, |
| 161 | overwrite = False, | 161 | overwrite = False, |
| @@ -221,7 +221,7 @@ class SurfaceManager(): | @@ -221,7 +221,7 @@ class SurfaceManager(): | ||
| 221 | index_list.append(index) | 221 | index_list.append(index) |
| 222 | #self.ShowActor(index, True) | 222 | #self.ShowActor(index, True) |
| 223 | 223 | ||
| 224 | - Publisher.sendMessage('Show multiple surfaces', (index_list, True)) | 224 | + Publisher.sendMessage('Show multiple surfaces', (index_list, True)) |
| 225 | 225 | ||
| 226 | def OnLargestSurface(self, pubsub_evt): | 226 | def OnLargestSurface(self, pubsub_evt): |
| 227 | """ | 227 | """ |
| @@ -329,7 +329,8 @@ class SurfaceManager(): | @@ -329,7 +329,8 @@ class SurfaceManager(): | ||
| 329 | surface.colour, surface.volume, | 329 | surface.colour, surface.volume, |
| 330 | surface.transparency)) | 330 | surface.transparency)) |
| 331 | self.last_surface_index = index | 331 | self.last_surface_index = index |
| 332 | - self.ShowActor(index, True) | 332 | + if surface.is_shown: |
| 333 | + self.ShowActor(index, True) | ||
| 333 | 334 | ||
| 334 | def OnLoadSurfaceDict(self, pubsub_evt): | 335 | def OnLoadSurfaceDict(self, pubsub_evt): |
| 335 | surface_dict = pubsub_evt.data | 336 | surface_dict = pubsub_evt.data |
| @@ -388,10 +389,10 @@ class SurfaceManager(): | @@ -388,10 +389,10 @@ class SurfaceManager(): | ||
| 388 | matrix = slice_.matrix | 389 | matrix = slice_.matrix |
| 389 | filename_img = slice_.matrix_filename | 390 | filename_img = slice_.matrix_filename |
| 390 | spacing = slice_.spacing | 391 | spacing = slice_.spacing |
| 391 | - | 392 | + |
| 392 | algorithm = surface_parameters['method']['algorithm'] | 393 | algorithm = surface_parameters['method']['algorithm'] |
| 393 | options = surface_parameters['method']['options'] | 394 | options = surface_parameters['method']['options'] |
| 394 | - | 395 | + |
| 395 | surface_name = surface_parameters['options']['name'] | 396 | surface_name = surface_parameters['options']['name'] |
| 396 | quality = surface_parameters['options']['quality'] | 397 | quality = surface_parameters['options']['quality'] |
| 397 | fill_holes = surface_parameters['options']['fill'] | 398 | fill_holes = surface_parameters['options']['fill'] |
| @@ -425,7 +426,7 @@ class SurfaceManager(): | @@ -425,7 +426,7 @@ class SurfaceManager(): | ||
| 425 | pipeline_size += 1 | 426 | pipeline_size += 1 |
| 426 | if keep_largest: | 427 | if keep_largest: |
| 427 | pipeline_size += 1 | 428 | pipeline_size += 1 |
| 428 | - | 429 | + |
| 429 | ## Update progress value in GUI | 430 | ## Update progress value in GUI |
| 430 | UpdateProgress = vu.ShowProgress(pipeline_size) | 431 | UpdateProgress = vu.ShowProgress(pipeline_size) |
| 431 | UpdateProgress(0, _("Creating 3D surface...")) | 432 | UpdateProgress(0, _("Creating 3D surface...")) |
| @@ -438,7 +439,7 @@ class SurfaceManager(): | @@ -438,7 +439,7 @@ class SurfaceManager(): | ||
| 438 | flip_image = True | 439 | flip_image = True |
| 439 | 440 | ||
| 440 | n_processors = multiprocessing.cpu_count() | 441 | n_processors = multiprocessing.cpu_count() |
| 441 | - | 442 | + |
| 442 | pipe_in, pipe_out = multiprocessing.Pipe() | 443 | pipe_in, pipe_out = multiprocessing.Pipe() |
| 443 | o_piece = 1 | 444 | o_piece = 1 |
| 444 | piece_size = 2000 | 445 | piece_size = 2000 |
| @@ -455,7 +456,7 @@ class SurfaceManager(): | @@ -455,7 +456,7 @@ class SurfaceManager(): | ||
| 455 | mask.temp_file, | 456 | mask.temp_file, |
| 456 | mask.matrix.shape, | 457 | mask.matrix.shape, |
| 457 | mask.matrix.dtype, | 458 | mask.matrix.dtype, |
| 458 | - spacing, | 459 | + spacing, |
| 459 | mode, min_value, max_value, | 460 | mode, min_value, max_value, |
| 460 | decimate_reduction, | 461 | decimate_reduction, |
| 461 | smooth_relaxation_factor, | 462 | smooth_relaxation_factor, |
| @@ -642,7 +643,7 @@ class SurfaceManager(): | @@ -642,7 +643,7 @@ class SurfaceManager(): | ||
| 642 | polydata.SetSource(None) | 643 | polydata.SetSource(None) |
| 643 | polydata.DebugOn() | 644 | polydata.DebugOn() |
| 644 | del filled_polydata | 645 | del filled_polydata |
| 645 | - | 646 | + |
| 646 | normals = vtk.vtkPolyDataNormals() | 647 | normals = vtk.vtkPolyDataNormals() |
| 647 | normals.ReleaseDataFlagOn() | 648 | normals.ReleaseDataFlagOn() |
| 648 | normals_ref = weakref.ref(normals) | 649 | normals_ref = weakref.ref(normals) |
| @@ -741,19 +742,19 @@ class SurfaceManager(): | @@ -741,19 +742,19 @@ class SurfaceManager(): | ||
| 741 | (surface.index, surface.name, | 742 | (surface.index, surface.name, |
| 742 | surface.colour, surface.volume, | 743 | surface.colour, surface.volume, |
| 743 | surface.transparency)) | 744 | surface.transparency)) |
| 744 | - | 745 | + |
| 745 | #When you finalize the progress. The bar is cleaned. | 746 | #When you finalize the progress. The bar is cleaned. |
| 746 | UpdateProgress = vu.ShowProgress(1) | 747 | UpdateProgress = vu.ShowProgress(1) |
| 747 | UpdateProgress(0, _("Ready")) | 748 | UpdateProgress(0, _("Ready")) |
| 748 | Publisher.sendMessage('Update status text in GUI', _("Ready")) | 749 | Publisher.sendMessage('Update status text in GUI', _("Ready")) |
| 749 | - | 750 | + |
| 750 | Publisher.sendMessage('End busy cursor') | 751 | Publisher.sendMessage('End busy cursor') |
| 751 | del actor | 752 | del actor |
| 752 | 753 | ||
| 753 | def UpdateSurfaceInterpolation(self, pub_evt): | 754 | def UpdateSurfaceInterpolation(self, pub_evt): |
| 754 | interpolation = int(ses.Session().surface_interpolation) | 755 | interpolation = int(ses.Session().surface_interpolation) |
| 755 | key_actors = self.actors_dict.keys() | 756 | key_actors = self.actors_dict.keys() |
| 756 | - | 757 | + |
| 757 | for key in self.actors_dict: | 758 | for key in self.actors_dict: |
| 758 | self.actors_dict[key].GetProperty().SetInterpolation(interpolation) | 759 | self.actors_dict[key].GetProperty().SetInterpolation(interpolation) |
| 759 | Publisher.sendMessage('Render volume viewer') | 760 | Publisher.sendMessage('Render volume viewer') |
invesalius/data/viewer_slice.py
| @@ -62,6 +62,7 @@ class ContourMIPConfig(wx.Panel): | @@ -62,6 +62,7 @@ class ContourMIPConfig(wx.Panel): | ||
| 62 | wx.Panel.__init__(self, prnt) | 62 | wx.Panel.__init__(self, prnt) |
| 63 | self.mip_size_spin = wx.SpinCtrl(self, -1, min=1, max=240, | 63 | self.mip_size_spin = wx.SpinCtrl(self, -1, min=1, max=240, |
| 64 | initial=const.PROJECTION_MIP_SIZE) | 64 | initial=const.PROJECTION_MIP_SIZE) |
| 65 | + self.mip_size_spin.SetValue(const.PROJECTION_MIP_SIZE) | ||
| 65 | self.mip_size_spin.SetToolTip(wx.ToolTip(_("Number of slices used to compound the visualization."))) | 66 | self.mip_size_spin.SetToolTip(wx.ToolTip(_("Number of slices used to compound the visualization."))) |
| 66 | w, h = self.mip_size_spin.GetTextExtent('M') | 67 | w, h = self.mip_size_spin.GetTextExtent('M') |
| 67 | self.mip_size_spin.SetMinSize((5 * w + 10, -1)) | 68 | self.mip_size_spin.SetMinSize((5 * w + 10, -1)) |
| @@ -525,12 +526,6 @@ class Viewer(wx.Panel): | @@ -525,12 +526,6 @@ class Viewer(wx.Panel): | ||
| 525 | ren.GetActiveCamera().Zoom(1.0) | 526 | ren.GetActiveCamera().Zoom(1.0) |
| 526 | self.interactor.Render() | 527 | self.interactor.Render() |
| 527 | 528 | ||
| 528 | - def ChangeBrushSize(self, pubsub_evt): | ||
| 529 | - size = pubsub_evt.data | ||
| 530 | - self._brush_cursor_size = size | ||
| 531 | - #for slice_data in self.slice_data_list: | ||
| 532 | - self.slice_data.cursor.SetSize(size) | ||
| 533 | - | ||
| 534 | def ChangeBrushColour(self, pubsub_evt): | 529 | def ChangeBrushColour(self, pubsub_evt): |
| 535 | vtk_colour = pubsub_evt.data[3] | 530 | vtk_colour = pubsub_evt.data[3] |
| 536 | self._brush_cursor_colour = vtk_colour | 531 | self._brush_cursor_colour = vtk_colour |
| @@ -545,27 +540,6 @@ class Viewer(wx.Panel): | @@ -545,27 +540,6 @@ class Viewer(wx.Panel): | ||
| 545 | if self.slice_data.cursor: | 540 | if self.slice_data.cursor: |
| 546 | self.slice_data.cursor.SetColour(colour_vtk) | 541 | self.slice_data.cursor.SetColour(colour_vtk) |
| 547 | 542 | ||
| 548 | - def ChangeBrushActor(self, pubsub_evt): | ||
| 549 | - brush_type = pubsub_evt.data | ||
| 550 | - slice_data = self.slice_data | ||
| 551 | - self._brush_cursor_type = brush_type | ||
| 552 | - | ||
| 553 | - if brush_type == const.BRUSH_SQUARE: | ||
| 554 | - cursor = ca.CursorRectangle() | ||
| 555 | - elif brush_type == const.BRUSH_CIRCLE: | ||
| 556 | - cursor = ca.CursorCircle() | ||
| 557 | - | ||
| 558 | - cursor.SetOrientation(self.orientation) | ||
| 559 | - coordinates = {"SAGITAL": [slice_data.number, 0, 0], | ||
| 560 | - "CORONAL": [0, slice_data.number, 0], | ||
| 561 | - "AXIAL": [0, 0, slice_data.number]} | ||
| 562 | - cursor.SetPosition(coordinates[self.orientation]) | ||
| 563 | - cursor.SetSpacing(self.slice_.spacing) | ||
| 564 | - cursor.SetColour(self._brush_cursor_colour) | ||
| 565 | - cursor.SetSize(self._brush_cursor_size) | ||
| 566 | - slice_data.SetCursor(cursor) | ||
| 567 | - self.interactor.Render() | ||
| 568 | - | ||
| 569 | def Navigation(self, pubsub_evt): | 543 | def Navigation(self, pubsub_evt): |
| 570 | # Get point from base change | 544 | # Get point from base change |
| 571 | x, y, z = pubsub_evt.data | 545 | x, y, z = pubsub_evt.data |
| @@ -700,14 +674,8 @@ class Viewer(wx.Panel): | @@ -700,14 +674,8 @@ class Viewer(wx.Panel): | ||
| 700 | Publisher.subscribe(self.Navigation, | 674 | Publisher.subscribe(self.Navigation, |
| 701 | 'Co-registered Points') | 675 | 'Co-registered Points') |
| 702 | ### | 676 | ### |
| 703 | - Publisher.subscribe(self.ChangeBrushSize, | ||
| 704 | - 'Set edition brush size') | ||
| 705 | Publisher.subscribe(self.ChangeBrushColour, | 677 | Publisher.subscribe(self.ChangeBrushColour, |
| 706 | 'Add mask') | 678 | 'Add mask') |
| 707 | - Publisher.subscribe(self.ChangeBrushActor, | ||
| 708 | - 'Set brush format') | ||
| 709 | - Publisher.subscribe(self.ChangeBrushOperation, | ||
| 710 | - 'Set edition operation') | ||
| 711 | 679 | ||
| 712 | Publisher.subscribe(self.UpdateWindowLevelValue, | 680 | Publisher.subscribe(self.UpdateWindowLevelValue, |
| 713 | 'Update window level value') | 681 | 'Update window level value') |
| @@ -833,9 +801,6 @@ class Viewer(wx.Panel): | @@ -833,9 +801,6 @@ class Viewer(wx.Panel): | ||
| 833 | if (state != const.SLICE_STATE_EDITOR): | 801 | if (state != const.SLICE_STATE_EDITOR): |
| 834 | Publisher.sendMessage('Set interactor default cursor') | 802 | Publisher.sendMessage('Set interactor default cursor') |
| 835 | 803 | ||
| 836 | - def ChangeBrushOperation(self, pubsub_evt): | ||
| 837 | - self._brush_cursor_op = pubsub_evt.data | ||
| 838 | - | ||
| 839 | def __bind_events_wx(self): | 804 | def __bind_events_wx(self): |
| 840 | self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar) | 805 | self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar) |
| 841 | self.scroll.Bind(wx.EVT_SCROLL_THUMBTRACK, self.OnScrollBarRelease) | 806 | self.scroll.Bind(wx.EVT_SCROLL_THUMBTRACK, self.OnScrollBarRelease) |
invesalius/gui/default_tasks.py
| @@ -230,10 +230,6 @@ class UpperTaskPanel(wx.Panel): | @@ -230,10 +230,6 @@ class UpperTaskPanel(wx.Panel): | ||
| 230 | wx.DefaultSize,FPB_DEFAULT_STYLE, | 230 | wx.DefaultSize,FPB_DEFAULT_STYLE, |
| 231 | fpb.FPB_SINGLE_FOLD) | 231 | fpb.FPB_SINGLE_FOLD) |
| 232 | 232 | ||
| 233 | - sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 234 | - sizer.Add(fold_panel, 1, wx.GROW|wx.EXPAND) | ||
| 235 | - self.SetSizer(sizer) | ||
| 236 | - | ||
| 237 | image_list = wx.ImageList(16,16) | 233 | image_list = wx.ImageList(16,16) |
| 238 | image_list.Add(GetExpandedIconBitmap()) | 234 | image_list.Add(GetExpandedIconBitmap()) |
| 239 | image_list.Add(GetCollapsedIconBitmap()) | 235 | image_list.Add(GetCollapsedIconBitmap()) |
| @@ -288,6 +284,10 @@ class UpperTaskPanel(wx.Panel): | @@ -288,6 +284,10 @@ class UpperTaskPanel(wx.Panel): | ||
| 288 | fold_panel.Expand(fold_panel.GetFoldPanel(0)) | 284 | fold_panel.Expand(fold_panel.GetFoldPanel(0)) |
| 289 | self.fold_panel = fold_panel | 285 | self.fold_panel = fold_panel |
| 290 | 286 | ||
| 287 | + sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 288 | + sizer.Add(fold_panel, 1, wx.GROW|wx.EXPAND) | ||
| 289 | + self.SetSizerAndFit(sizer) | ||
| 290 | + | ||
| 291 | self.SetStateProjectClose() | 291 | self.SetStateProjectClose() |
| 292 | self.__bind_events() | 292 | self.__bind_events() |
| 293 | 293 |
invesalius/gui/dialogs.py
| @@ -104,7 +104,7 @@ class ResizeImageDialog(wx.Dialog): | @@ -104,7 +104,7 @@ class ResizeImageDialog(wx.Dialog): | ||
| 104 | pos=wx.DefaultPosition, | 104 | pos=wx.DefaultPosition, |
| 105 | style=wx.DEFAULT_DIALOG_STYLE) | 105 | style=wx.DEFAULT_DIALOG_STYLE) |
| 106 | self.PostCreate(pre) | 106 | self.PostCreate(pre) |
| 107 | - | 107 | + |
| 108 | lbl_message = wx.StaticText(self, -1, _("InVesalius is running on a 32-bit operating system or has insufficient memory. \nIf you want to work with 3D surfaces or volume rendering, \nit is recommended to reduce the medical images resolution.")) | 108 | lbl_message = wx.StaticText(self, -1, _("InVesalius is running on a 32-bit operating system or has insufficient memory. \nIf you want to work with 3D surfaces or volume rendering, \nit is recommended to reduce the medical images resolution.")) |
| 109 | icon = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32,32)) | 109 | icon = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32,32)) |
| 110 | bmp = wx.StaticBitmap(self, -1, icon) | 110 | bmp = wx.StaticBitmap(self, -1, icon) |
| @@ -143,7 +143,7 @@ class ResizeImageDialog(wx.Dialog): | @@ -143,7 +143,7 @@ class ResizeImageDialog(wx.Dialog): | ||
| 143 | sizer_general.Fit(self) | 143 | sizer_general.Fit(self) |
| 144 | self.Layout() | 144 | self.Layout() |
| 145 | self.Centre() | 145 | self.Centre() |
| 146 | - | 146 | + |
| 147 | def SetValue(self, value): | 147 | def SetValue(self, value): |
| 148 | self.num_ctrl_porcent.SetValue(value) | 148 | self.num_ctrl_porcent.SetValue(value) |
| 149 | 149 | ||
| @@ -611,7 +611,7 @@ class NewMask(wx.Dialog): | @@ -611,7 +611,7 @@ class NewMask(wx.Dialog): | ||
| 611 | thresh_min, thresh_max = project.threshold_modes[_("Bone")] | 611 | thresh_min, thresh_max = project.threshold_modes[_("Bone")] |
| 612 | original_colour = random.choice(const.MASK_COLOUR) | 612 | original_colour = random.choice(const.MASK_COLOUR) |
| 613 | self.colour = original_colour | 613 | self.colour = original_colour |
| 614 | - colour = [255*i for i in original_colour] | 614 | + colour = [255*i for i in original_colour] |
| 615 | colour.append(100) | 615 | colour.append(100) |
| 616 | gradient = grad.GradientSlider(self, -1, int(bound_min), | 616 | gradient = grad.GradientSlider(self, -1, int(bound_min), |
| 617 | int(bound_max), | 617 | int(bound_max), |
| @@ -673,7 +673,7 @@ class NewMask(wx.Dialog): | @@ -673,7 +673,7 @@ class NewMask(wx.Dialog): | ||
| 673 | proj = prj.Project() | 673 | proj = prj.Project() |
| 674 | if thresh in proj.threshold_modes.values(): | 674 | if thresh in proj.threshold_modes.values(): |
| 675 | preset_name = proj.threshold_modes.get_key(thresh)[0] | 675 | preset_name = proj.threshold_modes.get_key(thresh)[0] |
| 676 | - index = self.thresh_list.index(preset_name) | 676 | + index = self.thresh_list.index(preset_name) |
| 677 | self.combo_thresh.SetSelection(index) | 677 | self.combo_thresh.SetSelection(index) |
| 678 | else: | 678 | else: |
| 679 | index = self.thresh_list.index(_("Custom")) | 679 | index = self.thresh_list.index(_("Custom")) |
| @@ -790,14 +790,14 @@ def ShowAboutDialog(parent): | @@ -790,14 +790,14 @@ def ShowAboutDialog(parent): | ||
| 790 | "Dimitris Glezos", | 790 | "Dimitris Glezos", |
| 791 | "Eugene Liscio", | 791 | "Eugene Liscio", |
| 792 | u"Frédéric Lopez", | 792 | u"Frédéric Lopez", |
| 793 | - "Javier de Lima Moreno" | 793 | + "Javier de Lima Moreno", |
| 794 | "Nikos Korkakakis", | 794 | "Nikos Korkakakis", |
| 795 | "Massimo Crisantemo", | 795 | "Massimo Crisantemo", |
| 796 | "Raul Bolliger Neto", | 796 | "Raul Bolliger Neto", |
| 797 | "Sebastian Hilbert", | 797 | "Sebastian Hilbert", |
| 798 | "Semarang Pari"] | 798 | "Semarang Pari"] |
| 799 | 799 | ||
| 800 | - #info.DocWriters = ["Fabio Francisco da Silva (PT)"] | 800 | + #info.DocWriters = ["Fabio Francisco da Silva (PT)"] |
| 801 | 801 | ||
| 802 | info.Artists = ["Otavio Henrique Junqueira Amorim"] | 802 | info.Artists = ["Otavio Henrique Junqueira Amorim"] |
| 803 | 803 | ||
| @@ -1101,7 +1101,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): | @@ -1101,7 +1101,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): | ||
| 1101 | import constants as const | 1101 | import constants as const |
| 1102 | import data.surface as surface | 1102 | import data.surface as surface |
| 1103 | import project as prj | 1103 | import project as prj |
| 1104 | - | 1104 | + |
| 1105 | wx.Panel.__init__(self, parent, ID) | 1105 | wx.Panel.__init__(self, parent, ID) |
| 1106 | 1106 | ||
| 1107 | # LINE 1: Surface name | 1107 | # LINE 1: Surface name |
| @@ -1151,7 +1151,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): | @@ -1151,7 +1151,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): | ||
| 1151 | flag_link = wx.EXPAND|wx.GROW|wx.ALL | 1151 | flag_link = wx.EXPAND|wx.GROW|wx.ALL |
| 1152 | flag_button = wx.ALL | wx.EXPAND| wx.GROW | 1152 | flag_button = wx.ALL | wx.EXPAND| wx.GROW |
| 1153 | 1153 | ||
| 1154 | - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=10, vgap=5) | 1154 | + fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=10, vgap=5) |
| 1155 | fixed_sizer.AddGrowableCol(0, 1) | 1155 | fixed_sizer.AddGrowableCol(0, 1) |
| 1156 | fixed_sizer.AddMany([ (label_surface, 1, flag_link, 0), | 1156 | fixed_sizer.AddMany([ (label_surface, 1, flag_link, 0), |
| 1157 | (text, 1, flag_button, 0), | 1157 | (text, 1, flag_button, 0), |
| @@ -1208,7 +1208,7 @@ class CAOptions(wx.Panel): | @@ -1208,7 +1208,7 @@ class CAOptions(wx.Panel): | ||
| 1208 | def __init__(self, parent): | 1208 | def __init__(self, parent): |
| 1209 | wx.Panel.__init__(self, parent, -1) | 1209 | wx.Panel.__init__(self, parent, -1) |
| 1210 | self._build_widgets() | 1210 | self._build_widgets() |
| 1211 | - | 1211 | + |
| 1212 | def _build_widgets(self): | 1212 | def _build_widgets(self): |
| 1213 | sb = wx.StaticBox(self, -1, _('Options')) | 1213 | sb = wx.StaticBox(self, -1, _('Options')) |
| 1214 | self.angle = floatspin.FloatSpin(self, -1, value=0.7, min_val=0.0, | 1214 | self.angle = floatspin.FloatSpin(self, -1, value=0.7, min_val=0.0, |
| @@ -1222,7 +1222,7 @@ class CAOptions(wx.Panel): | @@ -1222,7 +1222,7 @@ class CAOptions(wx.Panel): | ||
| 1222 | self.min_weight = floatspin.FloatSpin(self, -1, value=0.2, min_val=0.0, | 1222 | self.min_weight = floatspin.FloatSpin(self, -1, value=0.2, min_val=0.0, |
| 1223 | max_val=1.0, increment=0.1, | 1223 | max_val=1.0, increment=0.1, |
| 1224 | digits=1) | 1224 | digits=1) |
| 1225 | - | 1225 | + |
| 1226 | self.steps = wx.SpinCtrl(self, -1, value='10', min=1, max=100) | 1226 | self.steps = wx.SpinCtrl(self, -1, value='10', min=1, max=100) |
| 1227 | 1227 | ||
| 1228 | layout_sizer = wx.FlexGridSizer(rows=4, cols=2, hgap=5, vgap=5) | 1228 | layout_sizer = wx.FlexGridSizer(rows=4, cols=2, hgap=5, vgap=5) |
| @@ -1285,7 +1285,7 @@ class SurfaceMethodPanel(wx.Panel): | @@ -1285,7 +1285,7 @@ class SurfaceMethodPanel(wx.Panel): | ||
| 1285 | self.SetSizer(self.main_sizer) | 1285 | self.SetSizer(self.main_sizer) |
| 1286 | self.Layout() | 1286 | self.Layout() |
| 1287 | self.Fit() | 1287 | self.Fit() |
| 1288 | - | 1288 | + |
| 1289 | if self.mask_edited: | 1289 | if self.mask_edited: |
| 1290 | self.cb_types.SetValue(_(u'Context aware smoothing')) | 1290 | self.cb_types.SetValue(_(u'Context aware smoothing')) |
| 1291 | self.ca_options.Enable() | 1291 | self.ca_options.Enable() |
| @@ -1324,9 +1324,9 @@ class SurfaceMethodPanel(wx.Panel): | @@ -1324,9 +1324,9 @@ class SurfaceMethodPanel(wx.Panel): | ||
| 1324 | algorithm = self.GetAlgorithmSelected() | 1324 | algorithm = self.GetAlgorithmSelected() |
| 1325 | options = self.GetOptions() | 1325 | options = self.GetOptions() |
| 1326 | 1326 | ||
| 1327 | - return {"algorithm": algorithm, | 1327 | + return {"algorithm": algorithm, |
| 1328 | "options": options} | 1328 | "options": options} |
| 1329 | - | 1329 | + |
| 1330 | def ReloadMethodsOptions(self): | 1330 | def ReloadMethodsOptions(self): |
| 1331 | self.cb_types.Clear() | 1331 | self.cb_types.Clear() |
| 1332 | self.cb_types.AppendItems([i for i in sorted(self.alg_types) | 1332 | self.cb_types.AppendItems([i for i in sorted(self.alg_types) |
| @@ -1388,32 +1388,37 @@ class ClutImagedataDialog(wx.Dialog): | @@ -1388,32 +1388,37 @@ class ClutImagedataDialog(wx.Dialog): | ||
| 1388 | if gen_evt: | 1388 | if gen_evt: |
| 1389 | self.clut_widget._generate_event() | 1389 | self.clut_widget._generate_event() |
| 1390 | 1390 | ||
| 1391 | - | ||
| 1392 | -class WatershedOptions(wx.Panel): | ||
| 1393 | - def __init__(self, parent): | 1391 | + |
| 1392 | +class WatershedOptionsPanel(wx.Panel): | ||
| 1393 | + def __init__(self, parent, config): | ||
| 1394 | wx.Panel.__init__(self, parent) | 1394 | wx.Panel.__init__(self, parent) |
| 1395 | - | 1395 | + |
| 1396 | self.algorithms = ("Watershed", "Watershed IFT") | 1396 | self.algorithms = ("Watershed", "Watershed IFT") |
| 1397 | self.con2d_choices = (4, 8) | 1397 | self.con2d_choices = (4, 8) |
| 1398 | self.con3d_choices = (6, 18, 26) | 1398 | self.con3d_choices = (6, 18, 26) |
| 1399 | 1399 | ||
| 1400 | + self.config = config | ||
| 1401 | + | ||
| 1400 | self._init_gui() | 1402 | self._init_gui() |
| 1401 | - self._bind_events() | ||
| 1402 | 1403 | ||
| 1403 | def _init_gui(self): | 1404 | def _init_gui(self): |
| 1404 | self.choice_algorithm = wx.RadioBox(self, -1, "Algorithm", | 1405 | self.choice_algorithm = wx.RadioBox(self, -1, "Algorithm", |
| 1405 | - choices=("Watershed", "Watershed IFT"), | 1406 | + choices=self.algorithms, |
| 1406 | style=wx.NO_BORDER | wx.HORIZONTAL) | 1407 | style=wx.NO_BORDER | wx.HORIZONTAL) |
| 1408 | + self.choice_algorithm.SetSelection(self.algorithms.index(self.config.algorithm)) | ||
| 1407 | 1409 | ||
| 1408 | self.choice_2dcon = wx.RadioBox(self, -1, "2D", | 1410 | self.choice_2dcon = wx.RadioBox(self, -1, "2D", |
| 1409 | choices=[str(i) for i in self.con2d_choices], | 1411 | choices=[str(i) for i in self.con2d_choices], |
| 1410 | style=wx.NO_BORDER | wx.HORIZONTAL) | 1412 | style=wx.NO_BORDER | wx.HORIZONTAL) |
| 1413 | + self.choice_2dcon.SetSelection(self.con2d_choices.index(self.config.con_2d)) | ||
| 1411 | 1414 | ||
| 1412 | self.choice_3dcon = wx.RadioBox(self, -1, "3D", | 1415 | self.choice_3dcon = wx.RadioBox(self, -1, "3D", |
| 1413 | choices=[str(i) for i in self.con3d_choices], | 1416 | choices=[str(i) for i in self.con3d_choices], |
| 1414 | style=wx.NO_BORDER | wx.HORIZONTAL) | 1417 | style=wx.NO_BORDER | wx.HORIZONTAL) |
| 1418 | + self.choice_3dcon.SetSelection(self.con3d_choices.index(self.config.con_3d)) | ||
| 1415 | 1419 | ||
| 1416 | self.gaussian_size = wx.SpinCtrl(self, -1, "", min=1, max=10) | 1420 | self.gaussian_size = wx.SpinCtrl(self, -1, "", min=1, max=10) |
| 1421 | + self.gaussian_size.SetValue(self.config.mg_size) | ||
| 1417 | 1422 | ||
| 1418 | box_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Conectivity"), wx.VERTICAL) | 1423 | box_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Conectivity"), wx.VERTICAL) |
| 1419 | box_sizer.Add(self.choice_2dcon, 0, wx.ALIGN_CENTER_VERTICAL,2) | 1424 | box_sizer.Add(self.choice_2dcon, 0, wx.ALIGN_CENTER_VERTICAL,2) |
| @@ -1432,47 +1437,52 @@ class WatershedOptions(wx.Panel): | @@ -1432,47 +1437,52 @@ class WatershedOptions(wx.Panel): | ||
| 1432 | sizer.Fit(self) | 1437 | sizer.Fit(self) |
| 1433 | self.Layout() | 1438 | self.Layout() |
| 1434 | 1439 | ||
| 1435 | - def _bind_events(self): | ||
| 1436 | - self.choice_algorithm.Bind(wx.EVT_RADIOBOX, self.OnSetAlgorithm) | ||
| 1437 | - self.gaussian_size.Bind(wx.EVT_SPINCTRL, self.OnSetGaussianSize) | ||
| 1438 | - self.choice_2dcon.Bind(wx.EVT_RADIOBOX, self.OnSetCon2D) | ||
| 1439 | - self.choice_3dcon.Bind(wx.EVT_RADIOBOX, self.OnSetCon3D) | ||
| 1440 | - | ||
| 1441 | - def OnSetAlgorithm(self, evt): | ||
| 1442 | - v = self.algorithms[evt.GetInt()] | ||
| 1443 | - Publisher.sendMessage("Set watershed algorithm", v) | ||
| 1444 | - | ||
| 1445 | - def OnSetGaussianSize(self, evt): | ||
| 1446 | - v = self.gaussian_size.GetValue() | ||
| 1447 | - Publisher.sendMessage("Set watershed gaussian size", v) | ||
| 1448 | - | ||
| 1449 | - def OnSetCon2D(self, evt): | ||
| 1450 | - v = self.con2d_choices[evt.GetInt()] | ||
| 1451 | - Publisher.sendMessage("Set watershed 2d con", v) | ||
| 1452 | - | ||
| 1453 | - def OnSetCon3D(self, evt): | ||
| 1454 | - v = self.con3d_choices[evt.GetInt()] | ||
| 1455 | - Publisher.sendMessage("Set watershed 3d con", v) | 1440 | + def apply_options(self): |
| 1441 | + self.config.algorithm = self.algorithms[self.choice_algorithm.GetSelection()] | ||
| 1442 | + self.config.con_2d = self.con2d_choices[self.choice_2dcon.GetSelection()] | ||
| 1443 | + self.config.con_3d = self.con3d_choices[self.choice_3dcon.GetSelection()] | ||
| 1444 | + self.config.mg_size = self.gaussian_size.GetValue() | ||
| 1456 | 1445 | ||
| 1457 | 1446 | ||
| 1458 | class WatershedOptionsDialog(wx.Dialog): | 1447 | class WatershedOptionsDialog(wx.Dialog): |
| 1459 | - def __init__(self): | 1448 | + def __init__(self, config): |
| 1460 | pre = wx.PreDialog() | 1449 | pre = wx.PreDialog() |
| 1461 | pre.Create(wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) | 1450 | pre.Create(wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) |
| 1462 | self.PostCreate(pre) | 1451 | self.PostCreate(pre) |
| 1463 | 1452 | ||
| 1453 | + self.config = config | ||
| 1454 | + | ||
| 1464 | self._init_gui() | 1455 | self._init_gui() |
| 1465 | 1456 | ||
| 1466 | def _init_gui(self): | 1457 | def _init_gui(self): |
| 1467 | - wop = WatershedOptions(self) | 1458 | + wop = WatershedOptionsPanel(self, self.config) |
| 1459 | + self.wop = wop | ||
| 1460 | + | ||
| 1461 | + sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 1462 | + | ||
| 1463 | + btn_ok = wx.Button(self, wx.ID_OK) | ||
| 1464 | + btn_ok.SetDefault() | ||
| 1465 | + | ||
| 1466 | + btn_cancel = wx.Button(self, wx.ID_CANCEL) | ||
| 1467 | + | ||
| 1468 | + btnsizer = wx.StdDialogButtonSizer() | ||
| 1469 | + btnsizer.AddButton(btn_ok) | ||
| 1470 | + btnsizer.AddButton(btn_cancel) | ||
| 1471 | + btnsizer.Realize() | ||
| 1468 | 1472 | ||
| 1469 | - sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 1470 | sizer.Add(wop, 0, wx.EXPAND) | 1473 | sizer.Add(wop, 0, wx.EXPAND) |
| 1474 | + sizer.Add(btnsizer, 0, wx.EXPAND) | ||
| 1475 | + sizer.AddSpacer(5) | ||
| 1471 | 1476 | ||
| 1472 | self.SetSizer(sizer) | 1477 | self.SetSizer(sizer) |
| 1473 | sizer.Fit(self) | 1478 | sizer.Fit(self) |
| 1474 | self.Layout() | 1479 | self.Layout() |
| 1475 | 1480 | ||
| 1481 | + btn_ok.Bind(wx.EVT_BUTTON, self.OnOk) | ||
| 1482 | + | ||
| 1483 | + def OnOk(self, evt): | ||
| 1484 | + self.wop.apply_options() | ||
| 1485 | + evt.Skip() | ||
| 1476 | 1486 | ||
| 1477 | class MaskBooleanDialog(wx.Dialog): | 1487 | class MaskBooleanDialog(wx.Dialog): |
| 1478 | def __init__(self, masks): | 1488 | def __init__(self, masks): |
| @@ -1500,7 +1510,7 @@ class MaskBooleanDialog(wx.Dialog): | @@ -1500,7 +1510,7 @@ class MaskBooleanDialog(wx.Dialog): | ||
| 1500 | 1510 | ||
| 1501 | icon_folder = '../icons/' | 1511 | icon_folder = '../icons/' |
| 1502 | op_choices = ((_(u"Union"), const.BOOLEAN_UNION, 'bool_union.png'), | 1512 | op_choices = ((_(u"Union"), const.BOOLEAN_UNION, 'bool_union.png'), |
| 1503 | - (_(u"Difference"), const.BOOLEAN_DIFF, 'bool_difference.png'), | 1513 | + (_(u"Difference"), const.BOOLEAN_DIFF, 'bool_difference.png'), |
| 1504 | (_(u"Intersection"), const.BOOLEAN_AND, 'bool_intersection.png'), | 1514 | (_(u"Intersection"), const.BOOLEAN_AND, 'bool_intersection.png'), |
| 1505 | (_(u"Exclusive disjunction"), const.BOOLEAN_XOR, 'bool_disjunction.png')) | 1515 | (_(u"Exclusive disjunction"), const.BOOLEAN_XOR, 'bool_disjunction.png')) |
| 1506 | self.op_boolean = wx.combo.BitmapComboBox(self, -1, op_choices[0][0], choices=[]) | 1516 | self.op_boolean = wx.combo.BitmapComboBox(self, -1, op_choices[0][0], choices=[]) |
invesalius/gui/frame.py
| @@ -51,7 +51,7 @@ class MessageWatershed(wx.PopupWindow): | @@ -51,7 +51,7 @@ class MessageWatershed(wx.PopupWindow): | ||
| 51 | def __init__(self, prnt, msg): | 51 | def __init__(self, prnt, msg): |
| 52 | wx.PopupWindow.__init__(self, prnt, -1) | 52 | wx.PopupWindow.__init__(self, prnt, -1) |
| 53 | self.txt = wx.StaticText(self, -1, msg) | 53 | self.txt = wx.StaticText(self, -1, msg) |
| 54 | - | 54 | + |
| 55 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) | 55 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) |
| 56 | self.sizer.Add(self.txt, 1, wx.EXPAND) | 56 | self.sizer.Add(self.txt, 1, wx.EXPAND) |
| 57 | self.SetSizer(self.sizer) | 57 | self.SetSizer(self.sizer) |
| @@ -81,10 +81,10 @@ class Frame(wx.Frame): | @@ -81,10 +81,10 @@ class Frame(wx.Frame): | ||
| 81 | self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO)) | 81 | self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO)) |
| 82 | 82 | ||
| 83 | self.mw = None | 83 | self.mw = None |
| 84 | - | 84 | + |
| 85 | if sys.platform != 'darwin': | 85 | if sys.platform != 'darwin': |
| 86 | self.Maximize() | 86 | self.Maximize() |
| 87 | - | 87 | + |
| 88 | self.sizeChanged = True | 88 | self.sizeChanged = True |
| 89 | #Necessary update AUI (statusBar in special) | 89 | #Necessary update AUI (statusBar in special) |
| 90 | #when maximized in the Win 7 and XP | 90 | #when maximized in the Win 7 and XP |
| @@ -381,12 +381,12 @@ class Frame(wx.Frame): | @@ -381,12 +381,12 @@ class Frame(wx.Frame): | ||
| 381 | elif id == const.ID_START: | 381 | elif id == const.ID_START: |
| 382 | self.ShowGettingStarted() | 382 | self.ShowGettingStarted() |
| 383 | elif id == const.ID_PREFERENCES: | 383 | elif id == const.ID_PREFERENCES: |
| 384 | - self.ShowPreferences() | 384 | + self.ShowPreferences() |
| 385 | elif id == const.ID_DICOM_NETWORK: | 385 | elif id == const.ID_DICOM_NETWORK: |
| 386 | - self.ShowRetrieveDicomPanel() | 386 | + self.ShowRetrieveDicomPanel() |
| 387 | elif id in (const.ID_FLIP_X, const.ID_FLIP_Y, const.ID_FLIP_Z): | 387 | elif id in (const.ID_FLIP_X, const.ID_FLIP_Y, const.ID_FLIP_Z): |
| 388 | - axis = {const.ID_FLIP_X: 2, | ||
| 389 | - const.ID_FLIP_Y: 1, | 388 | + axis = {const.ID_FLIP_X: 2, |
| 389 | + const.ID_FLIP_Y: 1, | ||
| 390 | const.ID_FLIP_Z: 0}[id] | 390 | const.ID_FLIP_Z: 0}[id] |
| 391 | self.FlipVolume(axis) | 391 | self.FlipVolume(axis) |
| 392 | elif id in (const.ID_SWAP_XY, const.ID_SWAP_XZ, const.ID_SWAP_YZ): | 392 | elif id in (const.ID_SWAP_XY, const.ID_SWAP_XZ, const.ID_SWAP_YZ): |
| @@ -401,6 +401,8 @@ class Frame(wx.Frame): | @@ -401,6 +401,8 @@ class Frame(wx.Frame): | ||
| 401 | 401 | ||
| 402 | elif id == const.ID_BOOLEAN_MASK: | 402 | elif id == const.ID_BOOLEAN_MASK: |
| 403 | self.OnMaskBoolean() | 403 | self.OnMaskBoolean() |
| 404 | + elif id == const.ID_CLEAN_MASK: | ||
| 405 | + self.OnCleanMask() | ||
| 404 | 406 | ||
| 405 | def OnSize(self, evt): | 407 | def OnSize(self, evt): |
| 406 | """ | 408 | """ |
| @@ -429,10 +431,10 @@ class Frame(wx.Frame): | @@ -429,10 +431,10 @@ class Frame(wx.Frame): | ||
| 429 | if self.preferences.ShowModal() == wx.ID_OK: | 431 | if self.preferences.ShowModal() == wx.ID_OK: |
| 430 | values = self.preferences.GetPreferences() | 432 | values = self.preferences.GetPreferences() |
| 431 | self.preferences.Close() | 433 | self.preferences.Close() |
| 432 | - | 434 | + |
| 433 | ses.Session().rendering = values[const.RENDERING] | 435 | ses.Session().rendering = values[const.RENDERING] |
| 434 | ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION] | 436 | ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION] |
| 435 | - ses.Session().language = values[const.LANGUAGE] | 437 | + ses.Session().language = values[const.LANGUAGE] |
| 436 | 438 | ||
| 437 | Publisher.sendMessage('Remove Volume') | 439 | Publisher.sendMessage('Remove Volume') |
| 438 | Publisher.sendMessage('Reset Reaycasting') | 440 | Publisher.sendMessage('Reset Reaycasting') |
| @@ -479,7 +481,7 @@ class Frame(wx.Frame): | @@ -479,7 +481,7 @@ class Frame(wx.Frame): | ||
| 479 | Show save as dialog. | 481 | Show save as dialog. |
| 480 | """ | 482 | """ |
| 481 | Publisher.sendMessage('Show save dialog', True) | 483 | Publisher.sendMessage('Show save dialog', True) |
| 482 | - | 484 | + |
| 483 | def ShowAnalyzeImporter(self): | 485 | def ShowAnalyzeImporter(self): |
| 484 | """ | 486 | """ |
| 485 | Show save as dialog. | 487 | Show save as dialog. |
| @@ -488,12 +490,12 @@ class Frame(wx.Frame): | @@ -488,12 +490,12 @@ class Frame(wx.Frame): | ||
| 488 | 490 | ||
| 489 | def FlipVolume(self, axis): | 491 | def FlipVolume(self, axis): |
| 490 | Publisher.sendMessage('Flip volume', axis) | 492 | Publisher.sendMessage('Flip volume', axis) |
| 491 | - Publisher.sendMessage('Reload actual slice') | 493 | + Publisher.sendMessage('Reload actual slice') |
| 492 | 494 | ||
| 493 | def SwapAxes(self, axes): | 495 | def SwapAxes(self, axes): |
| 494 | Publisher.sendMessage('Swap volume axes', axes) | 496 | Publisher.sendMessage('Swap volume axes', axes) |
| 495 | Publisher.sendMessage('Update scroll') | 497 | Publisher.sendMessage('Update scroll') |
| 496 | - Publisher.sendMessage('Reload actual slice') | 498 | + Publisher.sendMessage('Reload actual slice') |
| 497 | 499 | ||
| 498 | def OnUndo(self): | 500 | def OnUndo(self): |
| 499 | print "Undo" | 501 | print "Undo" |
| @@ -503,11 +505,13 @@ class Frame(wx.Frame): | @@ -503,11 +505,13 @@ class Frame(wx.Frame): | ||
| 503 | print "Redo" | 505 | print "Redo" |
| 504 | Publisher.sendMessage('Redo edition') | 506 | Publisher.sendMessage('Redo edition') |
| 505 | 507 | ||
| 506 | - | ||
| 507 | def OnMaskBoolean(self): | 508 | def OnMaskBoolean(self): |
| 508 | print "Mask boolean" | 509 | print "Mask boolean" |
| 509 | Publisher.sendMessage('Show boolean dialog') | 510 | Publisher.sendMessage('Show boolean dialog') |
| 510 | - | 511 | + |
| 512 | + def OnCleanMask(self): | ||
| 513 | + Publisher.sendMessage('Clean current mask') | ||
| 514 | + Publisher.sendMessage('Reload actual slice') | ||
| 511 | 515 | ||
| 512 | # ------------------------------------------------------------------ | 516 | # ------------------------------------------------------------------ |
| 513 | # ------------------------------------------------------------------ | 517 | # ------------------------------------------------------------------ |
| @@ -546,12 +550,18 @@ class MenuBar(wx.MenuBar): | @@ -546,12 +550,18 @@ class MenuBar(wx.MenuBar): | ||
| 546 | sub(self.OnEnableUndo, "Enable undo") | 550 | sub(self.OnEnableUndo, "Enable undo") |
| 547 | sub(self.OnEnableRedo, "Enable redo") | 551 | sub(self.OnEnableRedo, "Enable redo") |
| 548 | 552 | ||
| 553 | + sub(self.OnAddMask, "Add mask") | ||
| 554 | + sub(self.OnRemoveMasks, "Remove masks") | ||
| 555 | + sub(self.OnShowMask, "Show mask") | ||
| 556 | + | ||
| 557 | + self.num_masks = 0 | ||
| 558 | + | ||
| 549 | def __init_items(self): | 559 | def __init_items(self): |
| 550 | """ | 560 | """ |
| 551 | Create all menu and submenus, and add them to self. | 561 | Create all menu and submenus, and add them to self. |
| 552 | """ | 562 | """ |
| 553 | # TODO: This definetely needs improvements... ;) | 563 | # TODO: This definetely needs improvements... ;) |
| 554 | - | 564 | + |
| 555 | #Import Others Files | 565 | #Import Others Files |
| 556 | others_file_menu = wx.Menu() | 566 | others_file_menu = wx.Menu() |
| 557 | others_file_menu.Append(const.ID_ANALYZE_IMPORT, "Analyze") | 567 | others_file_menu.Append(const.ID_ANALYZE_IMPORT, "Analyze") |
| @@ -594,7 +604,7 @@ class MenuBar(wx.MenuBar): | @@ -594,7 +604,7 @@ class MenuBar(wx.MenuBar): | ||
| 594 | file_edit = wx.Menu() | 604 | file_edit = wx.Menu() |
| 595 | #file_edit.AppendMenu(wx.NewId(), _('Flip'), flip_menu) | 605 | #file_edit.AppendMenu(wx.NewId(), _('Flip'), flip_menu) |
| 596 | #file_edit.AppendMenu(wx.NewId(), _('Swap axes'), swap_axes_menu) | 606 | #file_edit.AppendMenu(wx.NewId(), _('Swap axes'), swap_axes_menu) |
| 597 | - | 607 | + |
| 598 | 608 | ||
| 599 | d = const.ICON_DIR | 609 | d = const.ICON_DIR |
| 600 | if not(sys.platform == 'darwin'): | 610 | if not(sys.platform == 'darwin'): |
| @@ -620,10 +630,18 @@ class MenuBar(wx.MenuBar): | @@ -620,10 +630,18 @@ class MenuBar(wx.MenuBar): | ||
| 620 | #app(const.ID_EDIT_LIST, "Show Undo List...") | 630 | #app(const.ID_EDIT_LIST, "Show Undo List...") |
| 621 | ################################################################# | 631 | ################################################################# |
| 622 | 632 | ||
| 633 | + # Tool menu | ||
| 634 | + tools_menu = wx.Menu() | ||
| 635 | + | ||
| 623 | # Mask Menu | 636 | # Mask Menu |
| 624 | mask_menu = wx.Menu() | 637 | mask_menu = wx.Menu() |
| 625 | - mask_menu.Append(const.ID_BOOLEAN_MASK, _(u"Boolean operations")) | ||
| 626 | - file_edit.AppendMenu(-1, _(u"Mask"), mask_menu) | 638 | + self.bool_op_menu = mask_menu.Append(const.ID_BOOLEAN_MASK, _(u"Boolean operations")) |
| 639 | + self.bool_op_menu.Enable(False) | ||
| 640 | + | ||
| 641 | + self.clean_mask_menu = mask_menu.Append(const.ID_CLEAN_MASK, _(u"Clean Mask\tCtrl+Shift+A")) | ||
| 642 | + self.clean_mask_menu.Enable(False) | ||
| 643 | + | ||
| 644 | + tools_menu.AppendMenu(-1, _(u"Mask"), mask_menu) | ||
| 627 | 645 | ||
| 628 | 646 | ||
| 629 | # VIEW | 647 | # VIEW |
| @@ -666,13 +684,14 @@ class MenuBar(wx.MenuBar): | @@ -666,13 +684,14 @@ class MenuBar(wx.MenuBar): | ||
| 666 | help_menu.Append(const.ID_ABOUT, _("About...")) | 684 | help_menu.Append(const.ID_ABOUT, _("About...")) |
| 667 | #help_menu.Append(107, "Check For Updates Now...") | 685 | #help_menu.Append(107, "Check For Updates Now...") |
| 668 | 686 | ||
| 669 | - if platform.system() == 'Darwin': | ||
| 670 | - wx.App.SetMacAboutMenuItemId(const.ID_ABOUT) | ||
| 671 | - wx.App.SetMacExitMenuItemId(const.ID_EXIT) | 687 | + #if platform.system() == 'Darwin': |
| 688 | + #wx.App.SetMacAboutMenuItemId(const.ID_ABOUT) | ||
| 689 | + #wx.App.SetMacExitMenuItemId(const.ID_EXIT) | ||
| 672 | 690 | ||
| 673 | # Add all menus to menubar | 691 | # Add all menus to menubar |
| 674 | self.Append(file_menu, _("File")) | 692 | self.Append(file_menu, _("File")) |
| 675 | self.Append(file_edit, _("Edit")) | 693 | self.Append(file_edit, _("Edit")) |
| 694 | + self.Append(tools_menu, _(u"Tools")) | ||
| 676 | #self.Append(view_menu, "View") | 695 | #self.Append(view_menu, "View") |
| 677 | #self.Append(tools_menu, "Tools") | 696 | #self.Append(tools_menu, "Tools") |
| 678 | self.Append(options_menu, _("Options")) | 697 | self.Append(options_menu, _("Options")) |
| @@ -716,6 +735,20 @@ class MenuBar(wx.MenuBar): | @@ -716,6 +735,20 @@ class MenuBar(wx.MenuBar): | ||
| 716 | self.FindItemById(wx.ID_REDO).Enable(True) | 735 | self.FindItemById(wx.ID_REDO).Enable(True) |
| 717 | else: | 736 | else: |
| 718 | self.FindItemById(wx.ID_REDO).Enable(False) | 737 | self.FindItemById(wx.ID_REDO).Enable(False) |
| 738 | + | ||
| 739 | + def OnAddMask(self, pubsub_evt): | ||
| 740 | + self.num_masks += 1 | ||
| 741 | + self.bool_op_menu.Enable(self.num_masks >= 2) | ||
| 742 | + | ||
| 743 | + def OnRemoveMasks(self, pubsub_evt): | ||
| 744 | + self.num_masks -= len(pubsub_evt.data) | ||
| 745 | + self.bool_op_menu.Enable(self.num_masks >= 2) | ||
| 746 | + | ||
| 747 | + def OnShowMask(self, pubsub_evt): | ||
| 748 | + index, value = pubsub_evt.data | ||
| 749 | + self.clean_mask_menu.Enable(value) | ||
| 750 | + | ||
| 751 | + | ||
| 719 | # ------------------------------------------------------------------ | 752 | # ------------------------------------------------------------------ |
| 720 | # ------------------------------------------------------------------ | 753 | # ------------------------------------------------------------------ |
| 721 | # ------------------------------------------------------------------ | 754 | # ------------------------------------------------------------------ |
invesalius/gui/task_slice.py
| @@ -682,7 +682,7 @@ class EditionTools(wx.Panel): | @@ -682,7 +682,7 @@ class EditionTools(wx.Panel): | ||
| 682 | spin_brush_size = wx.SpinCtrl(self, -1, "", size=(width + 20, -1)) | 682 | spin_brush_size = wx.SpinCtrl(self, -1, "", size=(width + 20, -1)) |
| 683 | spin_brush_size.SetRange(1,100) | 683 | spin_brush_size.SetRange(1,100) |
| 684 | spin_brush_size.SetValue(const.BRUSH_SIZE) | 684 | spin_brush_size.SetValue(const.BRUSH_SIZE) |
| 685 | - spin_brush_size.Bind(wx.EVT_TEXT, self.OnBrushSize) | 685 | + spin_brush_size.Bind(wx.EVT_SPINCTRL, self.OnBrushSize) |
| 686 | self.spin = spin_brush_size | 686 | self.spin = spin_brush_size |
| 687 | 687 | ||
| 688 | combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), | 688 | combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), |
| @@ -740,6 +740,7 @@ class EditionTools(wx.Panel): | @@ -740,6 +740,7 @@ class EditionTools(wx.Panel): | ||
| 740 | 'Update threshold limits') | 740 | 'Update threshold limits') |
| 741 | Publisher.subscribe(self.ChangeMaskColour, 'Change mask colour') | 741 | Publisher.subscribe(self.ChangeMaskColour, 'Change mask colour') |
| 742 | Publisher.subscribe(self.SetGradientColour, 'Add mask') | 742 | Publisher.subscribe(self.SetGradientColour, 'Add mask') |
| 743 | + Publisher.subscribe(self._set_brush_size, 'Set edition brush size') | ||
| 743 | 744 | ||
| 744 | def ChangeMaskColour(self, pubsub_evt): | 745 | def ChangeMaskColour(self, pubsub_evt): |
| 745 | colour = pubsub_evt.data | 746 | colour = pubsub_evt.data |
| @@ -792,6 +793,10 @@ class EditionTools(wx.Panel): | @@ -792,6 +793,10 @@ class EditionTools(wx.Panel): | ||
| 792 | # Strangelly this is being called twice | 793 | # Strangelly this is being called twice |
| 793 | Publisher.sendMessage('Set edition brush size',self.spin.GetValue()) | 794 | Publisher.sendMessage('Set edition brush size',self.spin.GetValue()) |
| 794 | 795 | ||
| 796 | + def _set_brush_size(self, pubsub_evt): | ||
| 797 | + size = pubsub_evt.data | ||
| 798 | + self.spin.SetValue(size) | ||
| 799 | + | ||
| 795 | def OnComboBrushOp(self, evt): | 800 | def OnComboBrushOp(self, evt): |
| 796 | brush_op_id = evt.GetSelection() | 801 | brush_op_id = evt.GetSelection() |
| 797 | Publisher.sendMessage('Set edition operation', brush_op_id) | 802 | Publisher.sendMessage('Set edition operation', brush_op_id) |
| @@ -837,7 +842,7 @@ class WatershedTool(EditionTools): | @@ -837,7 +842,7 @@ class WatershedTool(EditionTools): | ||
| 837 | spin_brush_size = wx.SpinCtrl(self, -1, "", size=(width + 20, -1)) | 842 | spin_brush_size = wx.SpinCtrl(self, -1, "", size=(width + 20, -1)) |
| 838 | spin_brush_size.SetRange(1,100) | 843 | spin_brush_size.SetRange(1,100) |
| 839 | spin_brush_size.SetValue(const.BRUSH_SIZE) | 844 | spin_brush_size.SetValue(const.BRUSH_SIZE) |
| 840 | - spin_brush_size.Bind(wx.EVT_TEXT, self.OnBrushSize) | 845 | + spin_brush_size.Bind(wx.EVT_SPINCTRL, self.OnBrushSize) |
| 841 | self.spin = spin_brush_size | 846 | self.spin = spin_brush_size |
| 842 | 847 | ||
| 843 | combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), | 848 | combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), |
| @@ -897,6 +902,7 @@ class WatershedTool(EditionTools): | @@ -897,6 +902,7 @@ class WatershedTool(EditionTools): | ||
| 897 | self.SetAutoLayout(1) | 902 | self.SetAutoLayout(1) |
| 898 | 903 | ||
| 899 | self.__bind_events_wx() | 904 | self.__bind_events_wx() |
| 905 | + self.__bind_pubsub_evt() | ||
| 900 | 906 | ||
| 901 | 907 | ||
| 902 | def __bind_events_wx(self): | 908 | def __bind_events_wx(self): |
| @@ -907,6 +913,9 @@ class WatershedTool(EditionTools): | @@ -907,6 +913,9 @@ class WatershedTool(EditionTools): | ||
| 907 | self.btn_exp_watershed.Bind(wx.EVT_BUTTON, self.OnExpandWatershed) | 913 | self.btn_exp_watershed.Bind(wx.EVT_BUTTON, self.OnExpandWatershed) |
| 908 | self.btn_wconfig.Bind(wx.EVT_BUTTON, self.OnConfig) | 914 | self.btn_wconfig.Bind(wx.EVT_BUTTON, self.OnConfig) |
| 909 | 915 | ||
| 916 | + def __bind_pubsub_evt(self): | ||
| 917 | + Publisher.subscribe(self._set_brush_size, 'Set watershed brush size') | ||
| 918 | + | ||
| 910 | def ChangeMaskColour(self, pubsub_evt): | 919 | def ChangeMaskColour(self, pubsub_evt): |
| 911 | colour = pubsub_evt.data | 920 | colour = pubsub_evt.data |
| 912 | self.gradient_thresh.SetColour(colour) | 921 | self.gradient_thresh.SetColour(colour) |
| @@ -951,6 +960,10 @@ class WatershedTool(EditionTools): | @@ -951,6 +960,10 @@ class WatershedTool(EditionTools): | ||
| 951 | # Strangelly this is being called twice | 960 | # Strangelly this is being called twice |
| 952 | Publisher.sendMessage('Set watershed brush size',self.spin.GetValue()) | 961 | Publisher.sendMessage('Set watershed brush size',self.spin.GetValue()) |
| 953 | 962 | ||
| 963 | + def _set_brush_size(self, pubsub_evt): | ||
| 964 | + size = pubsub_evt.data | ||
| 965 | + self.spin.SetValue(size) | ||
| 966 | + | ||
| 954 | def OnComboBrushOp(self, evt): | 967 | def OnComboBrushOp(self, evt): |
| 955 | brush_op = self.combo_brush_op.GetValue() | 968 | brush_op = self.combo_brush_op.GetValue() |
| 956 | Publisher.sendMessage('Set watershed operation', brush_op) | 969 | Publisher.sendMessage('Set watershed operation', brush_op) |
| @@ -964,7 +977,9 @@ class WatershedTool(EditionTools): | @@ -964,7 +977,9 @@ class WatershedTool(EditionTools): | ||
| 964 | Publisher.sendMessage('Set use ww wl', value) | 977 | Publisher.sendMessage('Set use ww wl', value) |
| 965 | 978 | ||
| 966 | def OnConfig(self, evt): | 979 | def OnConfig(self, evt): |
| 967 | - dlg.WatershedOptionsDialog().Show() | 980 | + from data.styles import WatershedConfig |
| 981 | + config = WatershedConfig() | ||
| 982 | + dlg.WatershedOptionsDialog(config).Show() | ||
| 968 | 983 | ||
| 969 | def OnExpandWatershed(self, evt): | 984 | def OnExpandWatershed(self, evt): |
| 970 | Publisher.sendMessage('Expand watershed to 3D AXIAL') | 985 | Publisher.sendMessage('Expand watershed to 3D AXIAL') |
invesalius/gui/task_surface.py
| @@ -400,15 +400,14 @@ class SurfaceProperties(wx.Panel): | @@ -400,15 +400,14 @@ class SurfaceProperties(wx.Panel): | ||
| 400 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) | 400 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) |
| 401 | self.SetBackgroundColour(default_colour) | 401 | self.SetBackgroundColour(default_colour) |
| 402 | 402 | ||
| 403 | - self.surface_dict = utl.TwoWaysDictionary() | 403 | + self.surface_list = [] |
| 404 | 404 | ||
| 405 | ## LINE 1 | 405 | ## LINE 1 |
| 406 | 406 | ||
| 407 | # Combo related to mask naem | 407 | # Combo related to mask naem |
| 408 | - combo_surface_name = wx.ComboBox(self, -1, "", choices= | ||
| 409 | - self.surface_dict.keys() or ["", ], | 408 | + combo_surface_name = wx.ComboBox(self, -1, |
| 410 | style=wx.CB_DROPDOWN|wx.CB_READONLY) | 409 | style=wx.CB_DROPDOWN|wx.CB_READONLY) |
| 411 | - combo_surface_name.SetSelection(0) | 410 | + #combo_surface_name.SetSelection(0) |
| 412 | if sys.platform != 'win32': | 411 | if sys.platform != 'win32': |
| 413 | combo_surface_name.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) | 412 | combo_surface_name.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) |
| 414 | combo_surface_name.Bind(wx.EVT_COMBOBOX, self.OnComboName) | 413 | combo_surface_name.Bind(wx.EVT_COMBOBOX, self.OnComboName) |
| @@ -476,20 +475,23 @@ class SurfaceProperties(wx.Panel): | @@ -476,20 +475,23 @@ class SurfaceProperties(wx.Panel): | ||
| 476 | def OnRemoveSurfaces(self, pubsub_evt): | 475 | def OnRemoveSurfaces(self, pubsub_evt): |
| 477 | list_index = pubsub_evt.data | 476 | list_index = pubsub_evt.data |
| 478 | 477 | ||
| 479 | - old_dict = self.surface_dict | ||
| 480 | - new_dict = utl.TwoWaysDictionary() | ||
| 481 | - for index in list_index: | ||
| 482 | - self.combo_surface_name.Delete(index) | ||
| 483 | - | ||
| 484 | - for name in old_dict: | ||
| 485 | - if old_dict[name] < index: | ||
| 486 | - new_dict[name] = old_dict[name] | ||
| 487 | - if old_dict[name] > index: | ||
| 488 | - new_dict[name] = old_dict[name] -1 | ||
| 489 | - old_dict = new_dict | ||
| 490 | - self.surface_dict = new_dict | ||
| 491 | - | ||
| 492 | - | 478 | + old_dict = self.surface_list |
| 479 | + new_dict = [] | ||
| 480 | + i = 0 | ||
| 481 | + for n, (name, index) in enumerate(old_dict): | ||
| 482 | + if n not in list_index: | ||
| 483 | + new_dict.append([name, i]) | ||
| 484 | + i+=1 | ||
| 485 | + self.surface_list = new_dict | ||
| 486 | + | ||
| 487 | + s = self.combo_surface_name.GetSelection() | ||
| 488 | + self.combo_surface_name.SetItems([n[0] for n in self.surface_list]) | ||
| 489 | + | ||
| 490 | + if self.surface_list: | ||
| 491 | + if s in list_index: | ||
| 492 | + self.combo_surface_name.SetSelection(0) | ||
| 493 | + else: | ||
| 494 | + self.combo_surface_name.SetSelection(s) | ||
| 493 | 495 | ||
| 494 | def OnCloseProject(self, pubsub_evt): | 496 | def OnCloseProject(self, pubsub_evt): |
| 495 | self.CloseProject() | 497 | self.CloseProject() |
| @@ -501,32 +503,39 @@ class SurfaceProperties(wx.Panel): | @@ -501,32 +503,39 @@ class SurfaceProperties(wx.Panel): | ||
| 501 | 503 | ||
| 502 | def ChangeSurfaceName(self, pubsub_evt): | 504 | def ChangeSurfaceName(self, pubsub_evt): |
| 503 | index, name = pubsub_evt.data | 505 | index, name = pubsub_evt.data |
| 504 | - old_name = self.surface_dict.get_key(index) | ||
| 505 | - self.surface_dict.remove(old_name) | ||
| 506 | - self.surface_dict[name] = index | 506 | + self.surface_list[index][0] = name |
| 507 | self.combo_surface_name.SetString(index, name) | 507 | self.combo_surface_name.SetString(index, name) |
| 508 | - self.combo_surface_name.Refresh() | ||
| 509 | 508 | ||
| 510 | def InsertNewSurface(self, pubsub_evt): | 509 | def InsertNewSurface(self, pubsub_evt): |
| 511 | #not_update = len(pubsub_evt.data) == 5 | 510 | #not_update = len(pubsub_evt.data) == 5 |
| 512 | index = pubsub_evt.data[0] | 511 | index = pubsub_evt.data[0] |
| 513 | name = pubsub_evt.data[1] | 512 | name = pubsub_evt.data[1] |
| 514 | colour = [value*255 for value in pubsub_evt.data[2]] | 513 | colour = [value*255 for value in pubsub_evt.data[2]] |
| 515 | - overwrite = name in self.surface_dict.keys() | ||
| 516 | - #if index not in self.surface_dict.values(): | ||
| 517 | - if not overwrite or not self.surface_dict: | ||
| 518 | - self.surface_dict[name] = index | ||
| 519 | - index = self.combo_surface_name.Append(name) | 514 | + i = 0 |
| 515 | + print name, index, self.surface_list | ||
| 516 | + try: | ||
| 517 | + i = self.surface_list.index([name, index]) | ||
| 518 | + overwrite = True | ||
| 519 | + except ValueError: | ||
| 520 | + overwrite = False | ||
| 521 | + | ||
| 522 | + if overwrite: | ||
| 523 | + self.surface_list[i] = [name, index] | ||
| 524 | + else: | ||
| 525 | + self.surface_list.append([name, index]) | ||
| 526 | + i = len(self.surface_list) - 1 | ||
| 527 | + | ||
| 528 | + self.combo_surface_name.SetItems([n[0] for n in self.surface_list]) | ||
| 529 | + self.combo_surface_name.SetSelection(i) | ||
| 520 | transparency = 100*pubsub_evt.data[4] | 530 | transparency = 100*pubsub_evt.data[4] |
| 521 | self.button_colour.SetColour(colour) | 531 | self.button_colour.SetColour(colour) |
| 522 | self.slider_transparency.SetValue(transparency) | 532 | self.slider_transparency.SetValue(transparency) |
| 523 | - self.combo_surface_name.SetSelection(index) | ||
| 524 | Publisher.sendMessage('Update surface data', (index)) | 533 | Publisher.sendMessage('Update surface data', (index)) |
| 525 | 534 | ||
| 526 | def OnComboName(self, evt): | 535 | def OnComboName(self, evt): |
| 527 | surface_name = evt.GetString() | 536 | surface_name = evt.GetString() |
| 528 | surface_index = evt.GetSelection() | 537 | surface_index = evt.GetSelection() |
| 529 | - Publisher.sendMessage('Change surface selected', surface_index) | 538 | + Publisher.sendMessage('Change surface selected', self.surface_list[surface_index][1]) |
| 530 | 539 | ||
| 531 | def OnSelectColour(self, evt): | 540 | def OnSelectColour(self, evt): |
| 532 | colour = [value/255.0 for value in evt.GetValue()] | 541 | colour = [value/255.0 for value in evt.GetValue()] |