Commit bf2722383d09caf040fd9becd1bab29662a6ab97
1 parent
9a0892f4
Exists in
watershed
Applying threshold before starting watershed mode
Showing
4 changed files
with
225 additions
and
10 deletions
Show diff stats
invesalius/data/slice_.py
@@ -107,6 +107,7 @@ class Slice(object): | @@ -107,6 +107,7 @@ class Slice(object): | ||
107 | 107 | ||
108 | self.from_ = OTHER | 108 | self.from_ = OTHER |
109 | self.__bind_events() | 109 | self.__bind_events() |
110 | + self.opacity = 0.8 | ||
110 | self.qblend = {'AXIAL': {}, | 111 | self.qblend = {'AXIAL': {}, |
111 | 'CORONAL': {}, | 112 | 'CORONAL': {}, |
112 | 'SAGITAL': {}} | 113 | 'SAGITAL': {}} |
@@ -1181,6 +1182,19 @@ class Slice(object): | @@ -1181,6 +1182,19 @@ class Slice(object): | ||
1181 | m[mask == 254] = 254 | 1182 | m[mask == 254] = 254 |
1182 | return m.astype('uint8') | 1183 | return m.astype('uint8') |
1183 | 1184 | ||
1185 | + def do_threshold_to_all_slices(self): | ||
1186 | + mask = self.current_mask | ||
1187 | + | ||
1188 | + # This is very important. Do not use masks' imagedata. It would mess up | ||
1189 | + # surface quality event when using contour | ||
1190 | + #self.SetMaskThreshold(mask.index, threshold) | ||
1191 | + for n in xrange(1, mask.matrix.shape[0]): | ||
1192 | + if mask.matrix[n, 0, 0] == 0: | ||
1193 | + m = mask.matrix[n, 1:, 1:] | ||
1194 | + mask.matrix[n, 1:, 1:] = self.do_threshold_to_a_slice(self.matrix[n-1], m) | ||
1195 | + | ||
1196 | + mask.matrix.flush() | ||
1197 | + | ||
1184 | def do_colour_image(self, imagedata): | 1198 | def do_colour_image(self, imagedata): |
1185 | if self.from_ in (PLIST, WIDGET): | 1199 | if self.from_ in (PLIST, WIDGET): |
1186 | return imagedata | 1200 | return imagedata |
@@ -1216,8 +1230,10 @@ class Slice(object): | @@ -1216,8 +1230,10 @@ class Slice(object): | ||
1216 | lut_mask.SetNumberOfTableValues(256) | 1230 | lut_mask.SetNumberOfTableValues(256) |
1217 | lut_mask.SetTableValue(0, 0, 0, 0, 0.0) | 1231 | lut_mask.SetTableValue(0, 0, 0, 0, 0.0) |
1218 | lut_mask.SetTableValue(1, 0, 0, 0, 0.0) | 1232 | lut_mask.SetTableValue(1, 0, 0, 0, 0.0) |
1219 | - lut_mask.SetTableValue(254, r, g, b, 1.0) | ||
1220 | - lut_mask.SetTableValue(255, r, g, b, 1.0) | 1233 | + lut_mask.SetTableValue(2, 0, 0, 0, 0.0) |
1234 | + lut_mask.SetTableValue(253, r, g, b, self.opacity) | ||
1235 | + lut_mask.SetTableValue(254, r, g, b, self.opacity) | ||
1236 | + lut_mask.SetTableValue(255, r, g, b, self.opacity) | ||
1221 | lut_mask.SetRampToLinear() | 1237 | lut_mask.SetRampToLinear() |
1222 | lut_mask.Build() | 1238 | lut_mask.Build() |
1223 | # self.lut_mask = lut_mask | 1239 | # self.lut_mask = lut_mask |
invesalius/data/styles.py
@@ -674,11 +674,17 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -674,11 +674,17 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
674 | self.AddObserver("EnterEvent", self.OnEnterInteractor) | 674 | self.AddObserver("EnterEvent", self.OnEnterInteractor) |
675 | self.AddObserver("LeaveEvent", self.OnLeaveInteractor) | 675 | self.AddObserver("LeaveEvent", self.OnLeaveInteractor) |
676 | 676 | ||
677 | + self.RemoveObservers("MouseWheelForwardEvent") | ||
678 | + self.RemoveObservers("MouseWheelBackwardEvent") | ||
679 | + self.AddObserver("MouseWheelForwardEvent",self.WOnScrollForward) | ||
680 | + self.AddObserver("MouseWheelBackwardEvent", self.WOnScrollBackward) | ||
681 | + | ||
677 | self.AddObserver("LeftButtonPressEvent", self.OnBrushClick) | 682 | self.AddObserver("LeftButtonPressEvent", self.OnBrushClick) |
678 | self.AddObserver("LeftButtonReleaseEvent", self.OnBrushRelease) | 683 | self.AddObserver("LeftButtonReleaseEvent", self.OnBrushRelease) |
679 | self.AddObserver("MouseMoveEvent", self.OnBrushMove) | 684 | self.AddObserver("MouseMoveEvent", self.OnBrushMove) |
680 | 685 | ||
681 | def SetUp(self): | 686 | def SetUp(self): |
687 | + self.viewer.slice_.do_threshold_to_all_slices() | ||
682 | mask = self.viewer.slice_.current_mask.matrix | 688 | mask = self.viewer.slice_.current_mask.matrix |
683 | mask[0] = 1 | 689 | mask[0] = 1 |
684 | mask[:, 0, :] = 1 | 690 | mask[:, 0, :] = 1 |
@@ -687,6 +693,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -687,6 +693,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
687 | 693 | ||
688 | def CleanUp(self): | 694 | def CleanUp(self): |
689 | self._remove_mask() | 695 | self._remove_mask() |
696 | + self.viewer.slice_.qblend[self.orientation] = {} | ||
690 | 697 | ||
691 | def _create_mask(self): | 698 | def _create_mask(self): |
692 | if self.matrix is None: | 699 | if self.matrix is None: |
@@ -711,6 +718,35 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -711,6 +718,35 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
711 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 718 | self.viewer.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
712 | self.viewer.interactor.Render() | 719 | self.viewer.interactor.Render() |
713 | 720 | ||
721 | + def WOnScrollBackward(self, obj, evt): | ||
722 | + viewer = self.viewer | ||
723 | + iren = viewer.interactor | ||
724 | + if iren.GetControlKey(): | ||
725 | + if viewer.slice_.opacity > 0: | ||
726 | + viewer.slice_.opacity -= 0.1 | ||
727 | + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
728 | + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
729 | + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
730 | + viewer.OnScrollBar() | ||
731 | + else: | ||
732 | + self.OnScrollBackward(obj, evt) | ||
733 | + | ||
734 | + | ||
735 | + def WOnScrollForward(self, obj, evt): | ||
736 | + viewer = self.viewer | ||
737 | + iren = viewer.interactor | ||
738 | + print "AUIQ" | ||
739 | + if iren.GetControlKey(): | ||
740 | + if viewer.slice_.opacity < 1: | ||
741 | + viewer.slice_.opacity += 0.1 | ||
742 | + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() | ||
743 | + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() | ||
744 | + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() | ||
745 | + viewer.OnScrollBar() | ||
746 | + else: | ||
747 | + self.OnScrollForward(obj, evt) | ||
748 | + | ||
749 | + | ||
714 | def OnBrushClick(self, obj, evt): | 750 | def OnBrushClick(self, obj, evt): |
715 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 751 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
716 | return | 752 | return |
@@ -873,11 +909,17 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -873,11 +909,17 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
873 | wl = self.viewer.slice_.window_level | 909 | wl = self.viewer.slice_.window_level |
874 | 910 | ||
875 | #tmp_image = get_LUT_value(image, ww, wl).astype('uint16') | 911 | #tmp_image = get_LUT_value(image, ww, wl).astype('uint16') |
876 | - tmp_image = ndimage.morphological_gradient((image - image.min()).astype('uint16'), 5) | 912 | + tmp_image = ndimage.morphological_gradient(get_LUT_value(image, ww, wl).astype('uint16'), 5) |
877 | print tmp_image.dtype, tmp_image.min(), tmp_image.max() | 913 | print tmp_image.dtype, tmp_image.min(), tmp_image.max() |
878 | tmp_mask = watershed(tmp_image, markers) | 914 | tmp_mask = watershed(tmp_image, markers) |
879 | - mask[:] = 0 | ||
880 | - mask[tmp_mask == 1] = 255 | 915 | + |
916 | + if self.viewer.overwrite_mask: | ||
917 | + mask[:] = 0 | ||
918 | + mask[tmp_mask == 1] = 253 | ||
919 | + else: | ||
920 | + mask[(tmp_mask==2) & ((mask == 0) | (mask == 2) | (mask == 253))] = 2 | ||
921 | + mask[(tmp_mask==1) & ((mask == 0) | (mask == 2) | (mask == 253))] = 253 | ||
922 | + | ||
881 | self.viewer._flush_buffer = True | 923 | self.viewer._flush_buffer = True |
882 | self.viewer.OnScrollBar(update3D=False) | 924 | self.viewer.OnScrollBar(update3D=False) |
883 | 925 | ||
@@ -942,14 +984,14 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -942,14 +984,14 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
942 | index = index[abs(yi):,:] | 984 | index = index[abs(yi):,:] |
943 | yi = 0 | 985 | yi = 0 |
944 | if yf > mask.shape[0]: | 986 | if yf > mask.shape[0]: |
945 | - index = index[:index.shape[0]-(yf-image.shape[0]), :] | 987 | + index = index[:index.shape[0]-(yf-mask.shape[0]), :] |
946 | yf = mask.shape[0] | 988 | yf = mask.shape[0] |
947 | 989 | ||
948 | if xi < 0: | 990 | if xi < 0: |
949 | index = index[:,abs(xi):] | 991 | index = index[:,abs(xi):] |
950 | xi = 0 | 992 | xi = 0 |
951 | if xf > mask.shape[1]: | 993 | if xf > mask.shape[1]: |
952 | - index = index[:,:index.shape[1]-(xf-image.shape[1])] | 994 | + index = index[:,:index.shape[1]-(xf-mask.shape[1])] |
953 | xf = mask.shape[1] | 995 | xf = mask.shape[1] |
954 | 996 | ||
955 | # Verifying if the points is over the image array. | 997 | # Verifying if the points is over the image array. |
invesalius/data/viewer_slice.py
@@ -166,6 +166,8 @@ class Viewer(wx.Panel): | @@ -166,6 +166,8 @@ class Viewer(wx.Panel): | ||
166 | self.last_position_mouse_move = () | 166 | self.last_position_mouse_move = () |
167 | self.state = const.STATE_DEFAULT | 167 | self.state = const.STATE_DEFAULT |
168 | 168 | ||
169 | + self.overwrite_mask = False | ||
170 | + | ||
169 | # All renderers and image actors in this viewer | 171 | # All renderers and image actors in this viewer |
170 | self.slice_data_list = [] | 172 | self.slice_data_list = [] |
171 | self.slice_data = None | 173 | self.slice_data = None |
@@ -751,6 +753,8 @@ class Viewer(wx.Panel): | @@ -751,6 +753,8 @@ class Viewer(wx.Panel): | ||
751 | Publisher.subscribe(self.OnSetMIPInvert, 'Set MIP Invert %s' % self.orientation) | 753 | Publisher.subscribe(self.OnSetMIPInvert, 'Set MIP Invert %s' % self.orientation) |
752 | Publisher.subscribe(self.OnShowMIPInterface, 'Show MIP interface') | 754 | Publisher.subscribe(self.OnShowMIPInterface, 'Show MIP interface') |
753 | 755 | ||
756 | + Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask") | ||
757 | + | ||
754 | def SetDefaultCursor(self, pusub_evt): | 758 | def SetDefaultCursor(self, pusub_evt): |
755 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | 759 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) |
756 | 760 | ||
@@ -1247,7 +1251,10 @@ class Viewer(wx.Panel): | @@ -1247,7 +1251,10 @@ class Viewer(wx.Panel): | ||
1247 | self.mip_ctrls.Hide() | 1251 | self.mip_ctrls.Hide() |
1248 | self.GetSizer().Remove(self.mip_ctrls) | 1252 | self.GetSizer().Remove(self.mip_ctrls) |
1249 | self.Layout() | 1253 | self.Layout() |
1250 | - | 1254 | + |
1255 | + def OnSetOverwriteMask(self, pubsub_evt): | ||
1256 | + value = pubsub_evt.data | ||
1257 | + self.overwrite_mask = value | ||
1251 | 1258 | ||
1252 | def set_slice_number(self, index): | 1259 | def set_slice_number(self, index): |
1253 | inverted = self.mip_ctrls.inverted.GetValue() | 1260 | inverted = self.mip_ctrls.inverted.GetValue() |
invesalius/gui/task_slice.py
@@ -228,7 +228,7 @@ class InnerFoldPanel(wx.Panel): | @@ -228,7 +228,7 @@ class InnerFoldPanel(wx.Panel): | ||
228 | # parent panel. Perhaps we need to insert the item into the sizer also... | 228 | # parent panel. Perhaps we need to insert the item into the sizer also... |
229 | # Study this. | 229 | # Study this. |
230 | fold_panel = fpb.FoldPanelBar(self, -1, wx.DefaultPosition, | 230 | fold_panel = fpb.FoldPanelBar(self, -1, wx.DefaultPosition, |
231 | - (10, 190), 0,fpb.FPB_SINGLE_FOLD) | 231 | + (10, 220), 0,fpb.FPB_SINGLE_FOLD) |
232 | 232 | ||
233 | # Fold panel style | 233 | # Fold panel style |
234 | style = fpb.CaptionBarStyle() | 234 | style = fpb.CaptionBarStyle() |
@@ -706,6 +706,156 @@ class EditionTools(wx.Panel): | @@ -706,6 +706,156 @@ class EditionTools(wx.Panel): | ||
706 | 706 | ||
707 | 707 | ||
708 | class WatershedTool(EditionTools): | 708 | class WatershedTool(EditionTools): |
709 | - pass | 709 | + def __init__(self, parent): |
710 | + wx.Panel.__init__(self, parent, size=(50,240)) | ||
711 | + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) | ||
712 | + self.SetBackgroundColour(default_colour) | ||
713 | + | ||
714 | + ## LINE 1 | ||
715 | + text1 = wx.StaticText(self, -1, _("Choose brush type, size or operation:")) | ||
716 | + | ||
717 | + ## LINE 2 | ||
718 | + menu = wx.Menu() | ||
719 | + | ||
720 | + CIRCLE_BMP = wx.Bitmap("../icons/brush_circle.jpg", wx.BITMAP_TYPE_JPEG) | ||
721 | + item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle")) | ||
722 | + item.SetBitmap(CIRCLE_BMP) | ||
723 | + | ||
724 | + SQUARE_BMP = wx.Bitmap("../icons/brush_square.jpg", wx.BITMAP_TYPE_JPEG) | ||
725 | + item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square")) | ||
726 | + item2.SetBitmap(SQUARE_BMP) | ||
727 | + | ||
728 | + menu.AppendItem(item) | ||
729 | + menu.AppendItem(item2) | ||
730 | + | ||
731 | + bmp_brush_format = {const.BRUSH_CIRCLE: CIRCLE_BMP, | ||
732 | + const.BRUSH_SQUARE: SQUARE_BMP} | ||
733 | + selected_bmp = bmp_brush_format[const.DEFAULT_BRUSH_FORMAT] | ||
734 | + | ||
735 | + btn_brush_format = pbtn.PlateButton(self, wx.ID_ANY,"", selected_bmp, | ||
736 | + style=pbtn.PB_STYLE_SQUARE) | ||
737 | + btn_brush_format.SetMenu(menu) | ||
738 | + self.btn_brush_format = btn_brush_format | ||
739 | + | ||
740 | + spin_brush_size = wx.SpinCtrl(self, -1, "", (20, 50)) | ||
741 | + spin_brush_size.SetRange(1,100) | ||
742 | + spin_brush_size.SetValue(const.BRUSH_SIZE) | ||
743 | + spin_brush_size.Bind(wx.EVT_TEXT, self.OnBrushSize) | ||
744 | + self.spin = spin_brush_size | ||
745 | + | ||
746 | + combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), | ||
747 | + choices = const.BRUSH_OP_NAME, | ||
748 | + style = wx.CB_DROPDOWN|wx.CB_READONLY) | ||
749 | + combo_brush_op.SetSelection(const.DEFAULT_BRUSH_OP) | ||
750 | + if sys.platform != 'win32': | ||
751 | + combo_brush_op.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) | ||
752 | + self.combo_brush_op = combo_brush_op | ||
753 | + | ||
754 | + # Sizer which represents the second line | ||
755 | + line2 = wx.BoxSizer(wx.HORIZONTAL) | ||
756 | + line2.Add(btn_brush_format, 0, wx.EXPAND|wx.GROW|wx.TOP|wx.RIGHT, 0) | ||
757 | + line2.Add(spin_brush_size, 0, wx.RIGHT, 5) | ||
758 | + line2.Add(combo_brush_op, 1, wx.EXPAND|wx.TOP|wx.RIGHT|wx.LEFT, 5) | ||
759 | + | ||
760 | + ## LINE 3 | ||
761 | + text_thresh = wx.StaticText(self, -1, _("Brush threshold range:")) | ||
762 | + | ||
763 | + ## LINE 4 | ||
764 | + gradient_thresh = grad.GradientCtrl(self, -1, 0, 5000, 0, 5000, | ||
765 | + (0, 0, 255, 100)) | ||
766 | + self.gradient_thresh = gradient_thresh | ||
767 | + self.bind_evt_gradient = True | ||
768 | + | ||
769 | + # LINE 5 | ||
770 | + check_box = wx.CheckBox(self, -1, _("Overwrite mask")) | ||
771 | + self.check_box = check_box | ||
772 | + | ||
773 | + # Add lines into main sizer | ||
774 | + sizer = wx.BoxSizer(wx.VERTICAL) | ||
775 | + sizer.Add(text1, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | ||
776 | + sizer.Add(line2, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | ||
777 | + sizer.Add(text_thresh, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | ||
778 | + sizer.Add(gradient_thresh, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT| | ||
779 | + wx.BOTTOM, 6) | ||
780 | + sizer.Add(check_box, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | ||
781 | + sizer.Fit(self) | ||
782 | + | ||
783 | + self.SetSizer(sizer) | ||
784 | + self.Update() | ||
785 | + self.SetAutoLayout(1) | ||
786 | + | ||
787 | + self.__bind_events() | ||
788 | + self.__bind_events_wx() | ||
789 | + | ||
790 | + | ||
791 | + def __bind_events_wx(self): | ||
792 | + self.Bind(wx.EVT_MENU, self.OnMenu) | ||
793 | + self.Bind(grad.EVT_THRESHOLD_CHANGED, self.OnGradientChanged, | ||
794 | + self.gradient_thresh) | ||
795 | + self.combo_brush_op.Bind(wx.EVT_COMBOBOX, self.OnComboBrushOp) | ||
796 | + self.check_box.Bind(wx.EVT_CHECKBOX, self.OnCheckOverwriteMask) | ||
797 | + | ||
798 | + def __bind_events(self): | ||
799 | + Publisher.subscribe(self.SetThresholdBounds, | ||
800 | + 'Update threshold limits') | ||
801 | + Publisher.subscribe(self.ChangeMaskColour, 'Change mask colour') | ||
802 | + Publisher.subscribe(self.SetGradientColour, 'Add mask') | ||
803 | + | ||
804 | + def ChangeMaskColour(self, pubsub_evt): | ||
805 | + colour = pubsub_evt.data | ||
806 | + self.gradient_thresh.SetColour(colour) | ||
807 | + | ||
808 | + def SetGradientColour(self, pubsub_evt): | ||
809 | + vtk_colour = pubsub_evt.data[3] | ||
810 | + wx_colour = [c*255 for c in vtk_colour] | ||
811 | + self.gradient_thresh.SetColour(wx_colour) | ||
812 | + | ||
813 | + def SetThresholdValues(self, pubsub_evt): | ||
814 | + thresh_min, thresh_max = pubsub_evt.data | ||
815 | + self.bind_evt_gradient = False | ||
816 | + self.gradient_thresh.SetMinValue(thresh_min) | ||
817 | + self.gradient_thresh.SetMaxValue(thresh_max) | ||
818 | + self.bind_evt_gradient = True | ||
819 | + | ||
820 | + def SetThresholdBounds(self, pubsub_evt): | ||
821 | + thresh_min = pubsub_evt.data[0] | ||
822 | + thresh_max = pubsub_evt.data[1] | ||
823 | + self.gradient_thresh.SetMinRange(thresh_min) | ||
824 | + self.gradient_thresh.SetMaxRange(thresh_max) | ||
825 | + self.gradient_thresh.SetMinValue(thresh_min) | ||
826 | + self.gradient_thresh.SetMaxValue(thresh_max) | ||
827 | + | ||
828 | + def OnGradientChanged(self, evt): | ||
829 | + thresh_min = self.gradient_thresh.GetMinValue() | ||
830 | + thresh_max = self.gradient_thresh.GetMaxValue() | ||
831 | + if self.bind_evt_gradient: | ||
832 | + Publisher.sendMessage('Set edition threshold values', | ||
833 | + (thresh_min, thresh_max)) | ||
834 | + | ||
835 | + def OnMenu(self, evt): | ||
836 | + SQUARE_BMP = wx.Bitmap("../icons/brush_square.jpg", wx.BITMAP_TYPE_JPEG) | ||
837 | + CIRCLE_BMP = wx.Bitmap("../icons/brush_circle.jpg", wx.BITMAP_TYPE_JPEG) | ||
838 | + | ||
839 | + brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE, | ||
840 | + MENU_BRUSH_SQUARE: const.BRUSH_SQUARE} | ||
841 | + bitmap = {MENU_BRUSH_CIRCLE: CIRCLE_BMP, | ||
842 | + MENU_BRUSH_SQUARE: SQUARE_BMP} | ||
843 | + | ||
844 | + self.btn_brush_format.SetBitmap(bitmap[evt.GetId()]) | ||
845 | + | ||
846 | + Publisher.sendMessage('Set brush format', brush[evt.GetId()]) | ||
847 | + | ||
848 | + def OnBrushSize(self, evt): | ||
849 | + """ """ | ||
850 | + # FIXME: Using wx.EVT_SPINCTRL in MacOS it doesnt capture changes only | ||
851 | + # in the text ctrl - so we are capturing only changes on text | ||
852 | + # Strangelly this is being called twice | ||
853 | + Publisher.sendMessage('Set edition brush size',self.spin.GetValue()) | ||
710 | 854 | ||
855 | + def OnComboBrushOp(self, evt): | ||
856 | + brush_op_id = evt.GetSelection() | ||
857 | + Publisher.sendMessage('Set edition operation', brush_op_id) | ||
711 | 858 | ||
859 | + def OnCheckOverwriteMask(self, evt): | ||
860 | + value = self.check_box.GetValue() | ||
861 | + Publisher.sendMessage('Set overwrite mask', value) |