From b35498fbb8ed2c0d26a9a33c631ccd4a75e67905 Mon Sep 17 00:00:00 2001 From: tatiana Date: Wed, 3 Feb 2010 13:32:18 +0000 Subject: [PATCH] ADD: Remove mask feature (#156) --- invesalius/data/slice_.py | 18 ++++++++++++++++-- invesalius/gui/data_notebook.py | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- invesalius/gui/task_slice.py | 30 ++++++++++++++---------------- 3 files changed, 165 insertions(+), 22 deletions(-) diff --git a/invesalius/data/slice_.py b/invesalius/data/slice_.py index ff7a991..16b18ef 100644 --- a/invesalius/data/slice_.py +++ b/invesalius/data/slice_.py @@ -93,6 +93,22 @@ class Slice(object): ps.Publisher().subscribe(self.OnEnableStyle, 'Enable style') ps.Publisher().subscribe(self.OnDisableStyle, 'Disable style') + ps.Publisher().subscribe(self.OnRemoveMasks, 'Remove masks') + + + def OnRemoveMasks(self, pubsub_evt): + selected_items = pubsub_evt.data + proj = Project() + for item in selected_items: + proj.RemoveMask(item) + + index = self.current_mask.index + if (proj.mask_dict) and (index in selected_items): + self.SelectCurrentMask(0) + elif not proj.mask_dict: + self.blend_filter.SetOpacity(1, 0) + self.blend_filter.Update() + ps.Publisher().sendMessage('Update slice viewer') def OnEnableStyle(self, pubsub_evt): @@ -157,8 +173,6 @@ class Slice(object): def __set_current_mask_threshold(self, evt_pubsub): session = ses.Session() - print session.project_status != const.PROJ_OPEN - print session.project_status #FIXME: find a better way to implement this if (self.num_gradient >= 2) or \ (session.project_status != const.PROJ_OPEN): diff --git a/invesalius/gui/data_notebook.py b/invesalius/gui/data_notebook.py index 4090445..e4ce67c 100644 --- a/invesalius/gui/data_notebook.py +++ b/invesalius/gui/data_notebook.py @@ -25,14 +25,21 @@ import Image import wx import wx.grid import wx.lib.flatnotebook as fnb +import wx.lib.platebtn as pbtn import wx.lib.pubsub as ps +import gui.dialogs as dlg import gui.widgets.listctrl as listmix + + +BTN_NEW, BTN_REMOVE, BTN_DUPLICATE = [wx.NewId() for i in xrange(3)] + # Panel that initializes notebook and related tabs class NotebookPanel(wx.Panel): def __init__(self, parent): - wx.Panel.__init__(self, parent, pos=wx.Point(0, 50), size=wx.Size(256, 140)) + wx.Panel.__init__(self, parent, pos=wx.Point(0, 50), + size=wx.Size(256, 160)) book = wx.Notebook(self, -1,style= wx.BK_DEFAULT) # TODO: check under Windows and Linux @@ -41,7 +48,7 @@ class NotebookPanel(wx.Panel): if sys.platform != 'win32': book.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) - book.AddPage(MasksListCtrlPanel(book), _("Masks")) + book.AddPage(MaskPage(book), _("Masks")) book.AddPage(SurfacesListCtrlPanel(book), _("Surfaces")) #book.AddPage(MeasuresListCtrlPanel(book), _("Measures")) #book.AddPage(AnnotationsListCtrlPanel(book), _("Annotations")) @@ -56,6 +63,103 @@ class NotebookPanel(wx.Panel): # TODO: insert icons bellow notebook + +class MaskPage(wx.Panel): + """ + Page related to mask items. + """ + def __init__(self, parent): + wx.Panel.__init__(self, parent, pos=wx.Point(0, 50), + size=wx.Size(256, 120)) + self.__init_gui() + + def __init_gui(self): + # listctrl were existing masks will be listed + self.listctrl = MasksListCtrlPanel(self, size=wx.Size(256, 80)) + # button control with tools (eg. remove, add new, etc) + self.buttonctrl = ButtonControlPanel(self) + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.listctrl, 0, wx.EXPAND) + sizer.Add(self.buttonctrl, 0, wx.EXPAND) + self.SetSizer(sizer) + self.Fit() + + +class ButtonControlPanel(wx.Panel): + """ + Button control panel that includes data notebook operations. + TODO: Enhace interface with parent class - it is really messed up + """ + def __init__(self, parent): + wx.Panel.__init__(self, parent, pos=wx.Point(0, 50), + size=wx.Size(256, 20)) + self.parent = parent + self.__init_gui() + + def __init_gui(self): + + # Bitmaps + BMP_NEW = wx.Bitmap("../icons/data_new.png", + wx.BITMAP_TYPE_PNG) + BMP_REMOVE = wx.Bitmap("../icons/data_remove.png", + wx.BITMAP_TYPE_PNG) + BMP_DUPLICATE = wx.Bitmap("../icons/data_duplicate.png", + wx.BITMAP_TYPE_PNG) + + # Plate buttons based on previous bitmaps + button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT + button_new = pbtn.PlateButton(self, BTN_NEW, "", + BMP_NEW, + style=button_style) + button_remove = pbtn.PlateButton(self, BTN_REMOVE, "", + BMP_REMOVE, + style=button_style) + button_duplicate = pbtn.PlateButton(self, BTN_DUPLICATE, "", + BMP_DUPLICATE, + style=button_style) + + # Add all controls to gui + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(button_new, 0, wx.GROW|wx.EXPAND|wx.LEFT, 10) + sizer.Add(button_remove, 0, wx.GROW|wx.EXPAND) + sizer.Add(button_duplicate, 0, wx.GROW|wx.EXPAND) + self.SetSizer(sizer) + self.Fit() + + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def OnButton(self, evt): + id = evt.GetId() + if id == BTN_NEW: + self.OnNew() + elif id == BTN_REMOVE: + self.OnRemove() + elif id == BTN_DUPLICATE: + self.OnDuplicate() + + def OnNew(self): + print "New" + #print self.parent.listctrl.GetSelected() + + def OnRemove(self): + print "Remove" + selected_items = self.parent.listctrl.GetSelected() + if selected_items: + for item in selected_items: + self.parent.listctrl.RemoveMask(item) + ps.Publisher().sendMessage('Remove masks', selected_items) + else: + dlg.MaskSelectionRequiredForRemoval() + + def OnDuplicate(self): + print "Duplicate" + selected_items = self.parent.listctrl.GetSelected() + if selected_items: + ps.Publisher().sendMessage('Duplicate masks', selected_items) + else: + dlg.MaskSelectionRequiredForDuplication() + class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, @@ -68,7 +172,6 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): wx.ListCtrl.__init__(self, parent, ID, pos, size, style=wx.LC_REPORT) listmix.TextEditMixin.__init__(self) self.mask_list_index = {} - self.mask_bmp_idx_to_name = {} self.__init_columns() self.__init_image_list() self.__bind_events_wx() @@ -91,7 +194,6 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): def OnCloseProject(self, pubsub_evt): self.DeleteAllItems() self.mask_list_index = {} - self.mask_bmp_idx_to_name = {} def OnChangeCurrentMask(self, pubsub_evt): @@ -195,6 +297,35 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): image_index = self.mask_list_index[index] self.imagelist.Replace(image_index, image) self.Refresh() + + def GetSelected(self): + """ + Return all items selected (highlighted). + """ + selected = [] + for index in self.mask_list_index: + if self.IsSelected(index): + selected.append(index) + # it is important to revert items order, so + # listctrl update is ok + selected.sort(reverse=True) + return selected + + def RemoveMask(self, index): + """ + Remove item given its index. + """ + # it is necessary to update internal dictionary + # that maps bitmap given item index + old_dict = self.mask_list_index + new_dict = {} + for i in old_dict: + if i < index: + new_dict[i] = old_dict[i] + if i > index: + new_dict[i-1] = old_dict[i] + self.mask_list_index = new_dict + self.DeleteItem(index) class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): diff --git a/invesalius/gui/task_slice.py b/invesalius/gui/task_slice.py index 138e70b..0680a43 100644 --- a/invesalius/gui/task_slice.py +++ b/invesalius/gui/task_slice.py @@ -26,6 +26,7 @@ import wx.lib.pubsub as ps import data.mask as mask import constants as const +import gui.dialogs as dlg import gui.widgets.gradient as grad import gui.widgets.foldpanelbar as fpb import widgets.colourselect as csel @@ -142,25 +143,16 @@ class InnerTaskPanel(wx.Panel): def OnButtonNextTask(self, evt): overwrite = self.check_box.IsChecked() - ps.Publisher().sendMessage('Create surface from index', + if self.GetMaskSelected() != -1: + ps.Publisher().sendMessage('Create surface from index', (self.GetMaskSelected(), overwrite)) + else: + dlg.InexistentMask() def OnLinkNewMask(self, evt=None): - dlg = wx.TextEntryDialog(self, _('Name of new mask:'), - _('InVesalius 3 - New mask')) - dlg.CenterOnScreen() - default_mask_name = const.MASK_NAME_PATTERN %(mask.Mask.general_index+2) - dlg.SetValue(default_mask_name) - - try: - op = dlg.ShowModal() == wx.ID_OK - except(wx._core.PyAssertionError): - print "win64 - wx._core.PyAssertionError" - op = True - - if (op): - mask_name = dlg.GetValue() + mask_name = dlg.NewMask() + if mask_name: ps.Publisher().sendMessage('Create new mask', mask_name) if evt: @@ -353,6 +345,7 @@ class MaskProperties(wx.Panel): 'Set threshold values in gradient') ps.Publisher().subscribe(self.SelectMaskName, 'Select mask name in combo') ps.Publisher().subscribe(self.ChangeMaskName, 'Change mask name') + ps.Publisher().subscribe(self.OnRemoveMasks, 'Remove masks') ps.Publisher().subscribe(self.OnCloseProject, 'Close project data') ps.Publisher().subscribe(self.SetThresholdValues2, 'Set threshold values') @@ -366,7 +359,12 @@ class MaskProperties(wx.Panel): n = self.combo_thresh.GetCount() for i in xrange(n-1, -1, -1): self.combo_thresh.Delete(i) - + + def OnRemoveMasks(self, pubsub_evt): + print "OnRemoveMasks" + list_index = pubsub_evt.data + for i in list_index: + self.combo_mask_name.Delete(i) def __bind_events_wx(self): self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, self.gradient) -- libgit2 0.21.2