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 | 98 | VOLUME = 4 |
| 99 | 99 | SURFACE = 5 |
| 100 | 100 | |
| 101 | +AXIAL_STR="AXIAL" | |
| 102 | +CORONAL_STR="CORONAL" | |
| 103 | +SAGITAL_STR="SAGITAL" | |
| 104 | + | |
| 101 | 105 | # Measure type |
| 102 | 106 | LINEAR = 6 |
| 103 | 107 | ANGULAR = 7 |
| ... | ... | @@ -550,6 +554,8 @@ ID_CROP_MASK = wx.NewId() |
| 550 | 554 | ID_CREATE_SURFACE = wx.NewId() |
| 551 | 555 | ID_CREATE_MASK = wx.NewId() |
| 552 | 556 | |
| 557 | +ID_GOTO_SLICE = wx.NewId() | |
| 558 | + | |
| 553 | 559 | #--------------------------------------------------------- |
| 554 | 560 | STATE_DEFAULT = 1000 |
| 555 | 561 | STATE_WL = 1001 | ... | ... |
invesalius/data/viewer_slice.py
| ... | ... | @@ -1263,6 +1263,11 @@ class Viewer(wx.Panel): |
| 1263 | 1263 | else: |
| 1264 | 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 | 1271 | def OnExportPicture(self, orientation, filename, filetype): |
| 1267 | 1272 | dict = {"AXIAL": const.AXIAL, |
| 1268 | 1273 | "CORONAL": const.CORONAL, | ... | ... |
invesalius/gui/dialogs.py
| ... | ... | @@ -3590,3 +3590,68 @@ class SurfaceProgressWindow(object): |
| 3590 | 3590 | |
| 3591 | 3591 | def Close(self): |
| 3592 | 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 | 98 | self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO)) |
| 99 | 99 | |
| 100 | 100 | self.mw = None |
| 101 | - | |
| 101 | + self._last_viewer_orientation_focus = const.AXIAL_STR | |
| 102 | 102 | |
| 103 | 103 | if sys.platform != 'darwin': |
| 104 | 104 | self.Maximize() |
| ... | ... | @@ -153,6 +153,7 @@ class Frame(wx.Frame): |
| 153 | 153 | sub(self._ShowImportBitmap, 'Show import bitmap panel in frame') |
| 154 | 154 | sub(self._ShowTask, 'Show task panel') |
| 155 | 155 | sub(self._UpdateAUI, 'Update AUI') |
| 156 | + sub(self._UpdateViewerFocus, 'Set viewer orientation focus') | |
| 156 | 157 | sub(self._Exit, 'Exit') |
| 157 | 158 | |
| 158 | 159 | def __bind_events_wx(self): |
| ... | ... | @@ -388,6 +389,10 @@ class Frame(wx.Frame): |
| 388 | 389 | """ |
| 389 | 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 | 396 | def CloseProject(self): |
| 392 | 397 | Publisher.sendMessage('Close Project') |
| 393 | 398 | |
| ... | ... | @@ -456,6 +461,8 @@ class Frame(wx.Frame): |
| 456 | 461 | self.OnUndo() |
| 457 | 462 | elif id == wx.ID_REDO: |
| 458 | 463 | self.OnRedo() |
| 464 | + elif id == const.ID_GOTO_SLICE: | |
| 465 | + self.OnGotoSlice() | |
| 459 | 466 | |
| 460 | 467 | elif id == const.ID_BOOLEAN_MASK: |
| 461 | 468 | self.OnMaskBoolean() |
| ... | ... | @@ -683,6 +690,12 @@ class Frame(wx.Frame): |
| 683 | 690 | def OnRedo(self): |
| 684 | 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 | 699 | def OnMaskBoolean(self): |
| 687 | 700 | Publisher.sendMessage('Show boolean dialog') |
| 688 | 701 | |
| ... | ... | @@ -755,7 +768,8 @@ class MenuBar(wx.MenuBar): |
| 755 | 768 | const.ID_THRESHOLD_SEGMENTATION, |
| 756 | 769 | const.ID_FLOODFILL_SEGMENTATION, |
| 757 | 770 | const.ID_CREATE_SURFACE, |
| 758 | - const.ID_CREATE_MASK] | |
| 771 | + const.ID_CREATE_MASK, | |
| 772 | + const.ID_GOTO_SLICE] | |
| 759 | 773 | self.__init_items() |
| 760 | 774 | self.__bind_events() |
| 761 | 775 | |
| ... | ... | @@ -839,6 +853,7 @@ class MenuBar(wx.MenuBar): |
| 839 | 853 | else: |
| 840 | 854 | file_edit.Append(wx.ID_UNDO, _("Undo\tCtrl+Z")).Enable(False) |
| 841 | 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 | 857 | #app(const.ID_EDIT_LIST, "Show Undo List...") |
| 843 | 858 | ################################################################# |
| 844 | 859 | ... | ... |