Commit 241070c61f28e4eb224b7647f2071fb684446b96
Committed by
GitHub
1 parent
1f878946
Exists in
master
Go to slice dialog tool (#167)
Adds to the user the possibility of go to a slice typing the slice number
Showing
4 changed files
with
93 additions
and
2 deletions
Show diff stats
invesalius/constants.py
| @@ -98,6 +98,10 @@ SAGITAL = 3 | @@ -98,6 +98,10 @@ SAGITAL = 3 | ||
| 98 | VOLUME = 4 | 98 | VOLUME = 4 |
| 99 | SURFACE = 5 | 99 | SURFACE = 5 |
| 100 | 100 | ||
| 101 | +AXIAL_STR="AXIAL" | ||
| 102 | +CORONAL_STR="CORONAL" | ||
| 103 | +SAGITAL_STR="SAGITAL" | ||
| 104 | + | ||
| 101 | # Measure type | 105 | # Measure type |
| 102 | LINEAR = 6 | 106 | LINEAR = 6 |
| 103 | ANGULAR = 7 | 107 | ANGULAR = 7 |
| @@ -550,6 +554,8 @@ ID_CROP_MASK = wx.NewId() | @@ -550,6 +554,8 @@ ID_CROP_MASK = wx.NewId() | ||
| 550 | ID_CREATE_SURFACE = wx.NewId() | 554 | ID_CREATE_SURFACE = wx.NewId() |
| 551 | ID_CREATE_MASK = wx.NewId() | 555 | ID_CREATE_MASK = wx.NewId() |
| 552 | 556 | ||
| 557 | +ID_GOTO_SLICE = wx.NewId() | ||
| 558 | + | ||
| 553 | #--------------------------------------------------------- | 559 | #--------------------------------------------------------- |
| 554 | STATE_DEFAULT = 1000 | 560 | STATE_DEFAULT = 1000 |
| 555 | STATE_WL = 1001 | 561 | STATE_WL = 1001 |
invesalius/data/viewer_slice.py
| @@ -1263,6 +1263,11 @@ class Viewer(wx.Panel): | @@ -1263,6 +1263,11 @@ class Viewer(wx.Panel): | ||
| 1263 | else: | 1263 | else: |
| 1264 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) | 1264 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) |
| 1265 | 1265 | ||
| 1266 | + def SetFocus(self): | ||
| 1267 | + Publisher.sendMessage('Set viewer orientation focus', | ||
| 1268 | + orientation=self.orientation) | ||
| 1269 | + super().SetFocus() | ||
| 1270 | + | ||
| 1266 | def OnExportPicture(self, orientation, filename, filetype): | 1271 | def OnExportPicture(self, orientation, filename, filetype): |
| 1267 | dict = {"AXIAL": const.AXIAL, | 1272 | dict = {"AXIAL": const.AXIAL, |
| 1268 | "CORONAL": const.CORONAL, | 1273 | "CORONAL": const.CORONAL, |
invesalius/gui/dialogs.py
| @@ -3590,3 +3590,68 @@ class SurfaceProgressWindow(object): | @@ -3590,3 +3590,68 @@ class SurfaceProgressWindow(object): | ||
| 3590 | 3590 | ||
| 3591 | def Close(self): | 3591 | def Close(self): |
| 3592 | self.dlg.Destroy() | 3592 | self.dlg.Destroy() |
| 3593 | + | ||
| 3594 | + | ||
| 3595 | +class GoToDialog(wx.Dialog): | ||
| 3596 | + def __init__(self, title=_("Go to slice ..."), init_orientation=const.AXIAL_STR): | ||
| 3597 | + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) | ||
| 3598 | + self._init_gui(init_orientation) | ||
| 3599 | + | ||
| 3600 | + def _init_gui(self, init_orientation): | ||
| 3601 | + orientations = ( | ||
| 3602 | + (_("Axial"), const.AXIAL_STR), | ||
| 3603 | + (_("Coronal"), const.CORONAL_STR), | ||
| 3604 | + (_("Sagital"), const.SAGITAL_STR), | ||
| 3605 | + ) | ||
| 3606 | + self.goto_slice = wx.TextCtrl(self, -1, "") | ||
| 3607 | + self.goto_orientation = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN|wx.CB_READONLY) | ||
| 3608 | + cb_init = 0 | ||
| 3609 | + for n, orientation in enumerate(orientations): | ||
| 3610 | + self.goto_orientation.Append(*orientation) | ||
| 3611 | + if orientation[1] == init_orientation: | ||
| 3612 | + cb_init = n | ||
| 3613 | + self.goto_orientation.SetSelection(cb_init) | ||
| 3614 | + | ||
| 3615 | + btn_ok = wx.Button(self, wx.ID_OK) | ||
| 3616 | + btn_ok.SetHelpText("") | ||
| 3617 | + btn_ok.SetDefault() | ||
| 3618 | + | ||
| 3619 | + btn_cancel = wx.Button(self, wx.ID_CANCEL) | ||
| 3620 | + btn_cancel.SetHelpText("") | ||
| 3621 | + | ||
| 3622 | + btnsizer = wx.StdDialogButtonSizer() | ||
| 3623 | + btnsizer.AddButton(btn_ok) | ||
| 3624 | + btnsizer.AddButton(btn_cancel) | ||
| 3625 | + btnsizer.Realize() | ||
| 3626 | + | ||
| 3627 | + main_sizer = wx.BoxSizer(wx.VERTICAL) | ||
| 3628 | + | ||
| 3629 | + slice_sizer = wx.BoxSizer(wx.HORIZONTAL) | ||
| 3630 | + slice_sizer.Add(wx.StaticText(self, -1, _("Slice number"), style=wx.ALIGN_CENTER), 0, wx.ALIGN_CENTER|wx.RIGHT, 5) | ||
| 3631 | + slice_sizer.Add(self.goto_slice, 1, wx.EXPAND) | ||
| 3632 | + | ||
| 3633 | + main_sizer.Add((5, 5)) | ||
| 3634 | + main_sizer.Add(slice_sizer, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
| 3635 | + main_sizer.Add((5, 5)) | ||
| 3636 | + main_sizer.Add(self.goto_orientation, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
| 3637 | + main_sizer.Add((5, 5)) | ||
| 3638 | + main_sizer.Add(btnsizer, 0, wx.EXPAND) | ||
| 3639 | + main_sizer.Add((5, 5)) | ||
| 3640 | + | ||
| 3641 | + self.SetSizer(main_sizer) | ||
| 3642 | + main_sizer.Fit(self) | ||
| 3643 | + | ||
| 3644 | + btn_ok.Bind(wx.EVT_BUTTON, self.OnOk) | ||
| 3645 | + | ||
| 3646 | + def OnOk(self, evt): | ||
| 3647 | + try: | ||
| 3648 | + slice_number = int(self.goto_slice.GetValue()) | ||
| 3649 | + orientation = self.goto_orientation.GetClientData(self.goto_orientation.GetSelection()) | ||
| 3650 | + Publisher.sendMessage(("Set scroll position", orientation), index=slice_number) | ||
| 3651 | + except ValueError: | ||
| 3652 | + pass | ||
| 3653 | + self.Close() | ||
| 3654 | + | ||
| 3655 | + def Close(self): | ||
| 3656 | + wx.Dialog.Close(self) | ||
| 3657 | + self.Destroy() |
invesalius/gui/frame.py
| @@ -98,7 +98,7 @@ class Frame(wx.Frame): | @@ -98,7 +98,7 @@ class Frame(wx.Frame): | ||
| 98 | self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO)) | 98 | self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO)) |
| 99 | 99 | ||
| 100 | self.mw = None | 100 | self.mw = None |
| 101 | - | 101 | + self._last_viewer_orientation_focus = const.AXIAL_STR |
| 102 | 102 | ||
| 103 | if sys.platform != 'darwin': | 103 | if sys.platform != 'darwin': |
| 104 | self.Maximize() | 104 | self.Maximize() |
| @@ -153,6 +153,7 @@ class Frame(wx.Frame): | @@ -153,6 +153,7 @@ class Frame(wx.Frame): | ||
| 153 | sub(self._ShowImportBitmap, 'Show import bitmap panel in frame') | 153 | sub(self._ShowImportBitmap, 'Show import bitmap panel in frame') |
| 154 | sub(self._ShowTask, 'Show task panel') | 154 | sub(self._ShowTask, 'Show task panel') |
| 155 | sub(self._UpdateAUI, 'Update AUI') | 155 | sub(self._UpdateAUI, 'Update AUI') |
| 156 | + sub(self._UpdateViewerFocus, 'Set viewer orientation focus') | ||
| 156 | sub(self._Exit, 'Exit') | 157 | sub(self._Exit, 'Exit') |
| 157 | 158 | ||
| 158 | def __bind_events_wx(self): | 159 | def __bind_events_wx(self): |
| @@ -388,6 +389,10 @@ class Frame(wx.Frame): | @@ -388,6 +389,10 @@ class Frame(wx.Frame): | ||
| 388 | """ | 389 | """ |
| 389 | self.aui_manager.Update() | 390 | self.aui_manager.Update() |
| 390 | 391 | ||
| 392 | + def _UpdateViewerFocus(self, orientation): | ||
| 393 | + if orientation in (const.AXIAL_STR, const.CORONAL_STR, const.SAGITAL_STR): | ||
| 394 | + self._last_viewer_orientation_focus = orientation | ||
| 395 | + | ||
| 391 | def CloseProject(self): | 396 | def CloseProject(self): |
| 392 | Publisher.sendMessage('Close Project') | 397 | Publisher.sendMessage('Close Project') |
| 393 | 398 | ||
| @@ -456,6 +461,8 @@ class Frame(wx.Frame): | @@ -456,6 +461,8 @@ class Frame(wx.Frame): | ||
| 456 | self.OnUndo() | 461 | self.OnUndo() |
| 457 | elif id == wx.ID_REDO: | 462 | elif id == wx.ID_REDO: |
| 458 | self.OnRedo() | 463 | self.OnRedo() |
| 464 | + elif id == const.ID_GOTO_SLICE: | ||
| 465 | + self.OnGotoSlice() | ||
| 459 | 466 | ||
| 460 | elif id == const.ID_BOOLEAN_MASK: | 467 | elif id == const.ID_BOOLEAN_MASK: |
| 461 | self.OnMaskBoolean() | 468 | self.OnMaskBoolean() |
| @@ -683,6 +690,12 @@ class Frame(wx.Frame): | @@ -683,6 +690,12 @@ class Frame(wx.Frame): | ||
| 683 | def OnRedo(self): | 690 | def OnRedo(self): |
| 684 | Publisher.sendMessage('Redo edition') | 691 | Publisher.sendMessage('Redo edition') |
| 685 | 692 | ||
| 693 | + def OnGotoSlice(self): | ||
| 694 | + gt_dialog = dlg.GoToDialog(init_orientation=self._last_viewer_orientation_focus) | ||
| 695 | + gt_dialog.CenterOnParent() | ||
| 696 | + gt_dialog.ShowModal() | ||
| 697 | + self.Refresh() | ||
| 698 | + | ||
| 686 | def OnMaskBoolean(self): | 699 | def OnMaskBoolean(self): |
| 687 | Publisher.sendMessage('Show boolean dialog') | 700 | Publisher.sendMessage('Show boolean dialog') |
| 688 | 701 | ||
| @@ -755,7 +768,8 @@ class MenuBar(wx.MenuBar): | @@ -755,7 +768,8 @@ class MenuBar(wx.MenuBar): | ||
| 755 | const.ID_THRESHOLD_SEGMENTATION, | 768 | const.ID_THRESHOLD_SEGMENTATION, |
| 756 | const.ID_FLOODFILL_SEGMENTATION, | 769 | const.ID_FLOODFILL_SEGMENTATION, |
| 757 | const.ID_CREATE_SURFACE, | 770 | const.ID_CREATE_SURFACE, |
| 758 | - const.ID_CREATE_MASK] | 771 | + const.ID_CREATE_MASK, |
| 772 | + const.ID_GOTO_SLICE] | ||
| 759 | self.__init_items() | 773 | self.__init_items() |
| 760 | self.__bind_events() | 774 | self.__bind_events() |
| 761 | 775 | ||
| @@ -839,6 +853,7 @@ class MenuBar(wx.MenuBar): | @@ -839,6 +853,7 @@ class MenuBar(wx.MenuBar): | ||
| 839 | else: | 853 | else: |
| 840 | file_edit.Append(wx.ID_UNDO, _("Undo\tCtrl+Z")).Enable(False) | 854 | file_edit.Append(wx.ID_UNDO, _("Undo\tCtrl+Z")).Enable(False) |
| 841 | file_edit.Append(wx.ID_REDO, _("Redo\tCtrl+Y")).Enable(False) | 855 | file_edit.Append(wx.ID_REDO, _("Redo\tCtrl+Y")).Enable(False) |
| 856 | + file_edit.Append(const.ID_GOTO_SLICE, _("Go to slice ...\tCtrl+G")) | ||
| 842 | #app(const.ID_EDIT_LIST, "Show Undo List...") | 857 | #app(const.ID_EDIT_LIST, "Show Undo List...") |
| 843 | ################################################################# | 858 | ################################################################# |
| 844 | 859 |