Index: sansguiframe/src/sans/guiframe/data_panel.py
===================================================================
--- sansguiframe/src/sans/guiframe/data_panel.py	(revision 31f3222b5e03c26d936af4e6637585be2fbf0e07)
+++ sansguiframe/src/sans/guiframe/data_panel.py	(revision 176fbf1f8ef3e3792beda5301f634bcec50501fe)
@@ -364,14 +364,24 @@
                 wx.PostEvent(self.parent, 
                              NewBatchEvent(enable=True))
-      
+    
+    def _get_data_selection(self, event):  
+        """
+        Get data selection from the right click
+        """
+        selection = event.GetSelection()
+        id, _, _ = self.FindFocus().GetSelection().GetData()
+        data_list, theory_list = \
+                            self.parent._data_manager.get_by_id(id_list=[id])
+        if data_list:
+            data = data_list.values()[0]
+        else:
+            data = theory_list.values()[0][0]
+        return data
+    
     def on_edit_data(self, event):
         """
         Pop Up Data Editor
         """
-        selection = event.GetSelection()
-        id, _, _ = self.tree_ctrl.GetSelection().GetData()
-        data_list, _= self.parent._data_manager.get_by_id(id_list=[id])
-        
-        data = data_list.values()[0]
+        data = self._get_data_selection(event)
         from sans.guiframe.local_perspectives.plotting.masking \
             import MaskPanel as MaskDialog
@@ -380,4 +390,22 @@
         #self.panel.Bind(wx.EVT_CLOSE, self._draw_masked_model)
         panel.ShowModal()
+        
+    def on_save_as(self, event):
+        """
+        Save data as a file
+        """
+        data = self._get_data_selection(event)
+        path = None
+        default_name = data.name
+        if default_name.count('.') > 0:
+            default_name = default_name.split('.')[0]
+        default_name += "_out"
+        if self.parent != None:
+            if issubclass(data.__class__, Data1D):
+                self.parent.save_data1d(data, default_name)
+            elif issubclass(data.__class__, Data2D):
+                self.parent.save_data2d(data, default_name)
+            else:
+                print "unable to save this type of data"
         
     def layout_data_list(self):
@@ -389,13 +417,19 @@
         self.tree_ctrl = DataTreeCtrl(parent=self, style=wx.SUNKEN_BORDER)
         self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
-        self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_MENU, self.on_right_click)
+        self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_MENU, self.on_right_click_data)
         ## Create context menu for page
         self.data_menu = wx.Menu()
         id = wx.NewId()
+        name = "Save As"
+        msg = "Save Theory/Data as a file"
+        self.data_menu.Append(id, name, msg)
+        wx.EVT_MENU(self, id, self.on_save_as)
+    
+        self.editmask_id = wx.NewId()
         name = "Edit Mask"
-        msg = "Edit the current Data"
-        self.data_menu.Append(id, name, msg)
-        wx.EVT_MENU(self, id, self.on_edit_data)
-    
+        msg = "Edit Mask for the current 2D Data"
+        self.data_menu.Append(self.editmask_id, name, msg)
+        wx.EVT_MENU(self, self.editmask_id, self.on_edit_data)
+
         tree_ctrl_theory_label = wx.StaticText(self, -1, "Theory")
         tree_ctrl_theory_label.SetForegroundColour('blue')
@@ -404,4 +438,6 @@
         self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_CHECKING, 
                                                     self.on_check_item)
+        self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_MENU, 
+                                   self.on_right_click_theory)
         self.sizer1.Add(tree_ctrl_label, 0, wx.LEFT, 10)
         self.sizer1.Add(self.tree_ctrl, 1, wx.EXPAND|wx.ALL, 10)
@@ -409,12 +445,29 @@
         self.sizer1.Add(self.tree_ctrl_theory, 1, wx.EXPAND|wx.ALL, 10)
            
-           
-    def on_right_click(self, event):
+    def on_right_click_theory(self, event):
+        """
+        On click theory data
+        """
+        if self.data_menu is not None:
+            self.data_menu.Enable(self.editmask_id, False)
+            self.PopupMenu(self.data_menu) 
+                   
+    def on_right_click_data(self, event):
         """
         Allow Editing Data
         """
         selection = event.GetSelection()
-        _, data_class_name, _ = self.tree_ctrl.GetSelection().GetData()
-        if data_class_name == "Data2D" and self.data_menu is not None:
+        is_data = True
+        try:
+            id, data_class_name, _ = self.tree_ctrl.GetSelection().GetData()
+            data_list, _ = \
+                            self.parent._data_manager.get_by_id(id_list=[id])
+            if not data_list:
+                is_data = False
+        except:
+            return
+        if self.data_menu is not None:
+            menu_enable = (data_class_name == "Data2D" and is_data)
+            self.data_menu.Enable(self.editmask_id, menu_enable)
             self.PopupMenu(self.data_menu) 
         
Index: sansguiframe/src/sans/guiframe/gui_manager.py
===================================================================
--- sansguiframe/src/sans/guiframe/gui_manager.py	(revision e9f6979c1ae124c97106661b6fe49009adcc4d30)
+++ sansguiframe/src/sans/guiframe/gui_manager.py	(revision 176fbf1f8ef3e3792beda5301f634bcec50501fe)
@@ -2433,5 +2433,140 @@
         except:
             pass
-                          
+    
+    def save_data1d(self, data, fname):
+        """
+        Save data dialog
+        """
+        default_name = fname
+        wildcard = "Text files (*.txt)|*.txt|"\
+                    "CanSAS 1D files(*.xml)|*.xml" 
+        path = None
+        dlg = wx.FileDialog(self, "Choose a file",
+                            self._default_save_location,
+                            default_name, wildcard , wx.SAVE)
+       
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+            # ext_num = 0 for .txt, ext_num = 1 for .xml
+            # This is MAC Fix
+            ext_num = dlg.GetFilterIndex()
+            if ext_num == 0:
+                format = '.txt'
+            else:
+                format = '.xml'
+            path = os.path.splitext(path)[0] + format
+            mypath = os.path.basename(path)
+            
+            #TODO: This is bad design. The DataLoader is designed 
+            #to recognize extensions.
+            # It should be a simple matter of calling the .
+            #save(file, data, '.xml') method
+            # of the sans.dataloader.loader.Loader class.
+            from sans.dataloader.loader import  Loader
+            #Instantiate a loader 
+            loader = Loader() 
+            format = ".txt"
+            if os.path.splitext(mypath)[1].lower() == format:
+                # Make sure the ext included in the file name
+                # especially on MAC
+                fName = os.path.splitext(path)[0] + format
+                self._onsaveTXT(data, fName)
+            format = ".xml"
+            if os.path.splitext(mypath)[1].lower() == format:
+                # Make sure the ext included in the file name
+                # especially on MAC
+                fName = os.path.splitext(path)[0] + format
+                loader.save(fName, data, format)
+            try:
+                self._default_save_location = os.path.dirname(path)
+            except:
+                pass    
+        dlg.Destroy()
+        
+        
+    def _onsaveTXT(self, data, path):
+        """
+        Save file as txt  
+        :TODO: Refactor and remove this method. See TODO in _onSave.
+        """
+        if not path == None:
+            out = open(path, 'w')
+            has_errors = True
+            if data.dy == None or data.dy == []:
+                has_errors = False
+            # Sanity check
+            if has_errors:
+                try:
+                    if len(data.y) != len(data.dy):
+                        has_errors = False
+                except:
+                    has_errors = False
+            if has_errors:
+                if data.dx != None and data.dx != []:
+                    out.write("<X>   <Y>   <dY>   <dX>\n")
+                else:
+                    out.write("<X>   <Y>   <dY>\n")
+            else:
+                out.write("<X>   <Y>\n")
+                
+            for i in range(len(data.x)):
+                if has_errors:
+                    if data.dx != None and data.dx != []:
+                        out.write("%g  %g  %g  %g\n" % (data.x[i], 
+                                                    data.y[i],
+                                                    data.dy[i],
+                                                    data.dx[i]))
+                    else:
+                        out.write("%g  %g  %g\n" % (data.x[i], 
+                                                    data.y[i],
+                                                    data.dy[i]))
+                else:
+                    out.write("%g  %g\n" % (data.x[i], 
+                                            data.y[i]))
+            out.close()                   
+            
+    def save_data2d(self, data, fname):    
+        """
+        Save data2d dialog
+        """
+        default_name = fname
+        wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
+        dlg = wx.FileDialog(self, "Choose a file",
+                            self._default_save_location,
+                            default_name, wildcard , wx.SAVE)
+       
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+            # ext_num = 0 for .txt, ext_num = 1 for .xml
+            # This is MAC Fix
+            ext_num = dlg.GetFilterIndex()
+            if ext_num == 0:
+                format = '.dat'
+            else:
+                format = ''
+            path = os.path.splitext(path)[0] + format
+            mypath = os.path.basename(path)
+            
+            #TODO: This is bad design. The DataLoader is designed 
+            #to recognize extensions.
+            # It should be a simple matter of calling the .
+            #save(file, data, '.xml') method
+            # of the DataLoader.loader.Loader class.
+            from sans.dataloader.loader import  Loader
+            #Instantiate a loader 
+            loader = Loader() 
+
+            format = ".dat"
+            if os.path.splitext(mypath)[1].lower() == format:
+                # Make sure the ext included in the file name
+                # especially on MAC
+                fileName = os.path.splitext(path)[0] + format
+                loader.save(fileName, data, format)
+            try:
+                self._default_save_location = os.path.dirname(path)
+            except:
+                pass    
+        dlg.Destroy() 
+                     
     def set_current_perspective(self, perspective):
         """
Index: sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter1D.py
===================================================================
--- sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter1D.py	(revision 45b6bfb8b23ab73c5f17adbe65fb2478fb0f8c5e)
+++ sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter1D.py	(revision 176fbf1f8ef3e3792beda5301f634bcec50501fe)
@@ -608,117 +608,19 @@
         #self.graph.render(self)
         #self.subplot.figure.canvas.draw_idle()
-        
-        
-        
-    def _onsaveTXT(self, path):
-        """
-        Save file as txt
-            
-        :TODO: Refactor and remove this method. See TODO in _onSave.
+                       
+    def _onSave(self, evt):
+        """
+        Save a data set to a text file
+        
+        :param evt: Menu event
         
         """
         data = self.plots[self.graph.selected_plottable]
-       
-        if not path == None:
-            out = open(path, 'w')
-            has_errors = True
-            if data.dy == None or data.dy == []:
-                has_errors = False
-            # Sanity check
-            if has_errors:
-                try:
-                    if len(data.y) != len(data.dy):
-                        has_errors = False
-                except:
-                    has_errors = False
-            if has_errors:
-                if data.dx != None and data.dx != []:
-                    out.write("<X>   <Y>   <dY>   <dX>\n")
-                else:
-                    out.write("<X>   <Y>   <dY>\n")
-            else:
-                out.write("<X>   <Y>\n")
-                
-            for i in range(len(data.x)):
-                if has_errors:
-                    if data.dx != None and data.dx != []:
-                        out.write("%g  %g  %g  %g\n" % (data.x[i], 
-                                                    data.y[i],
-                                                    data.dy[i],
-                                                    data.dx[i]))
-                    else:
-                        out.write("%g  %g  %g\n" % (data.x[i], 
-                                                    data.y[i],
-                                                    data.dy[i]))
-                else:
-                    out.write("%g  %g\n" % (data.x[i], 
-                                            data.y[i]))
-            out.close()                 
-            try:
-                self._default_save_location = os.path.dirname(path)
-                self.parent._default_save_location = self._default_save_location
-            except:
-                pass    
-                
-    def _onSave(self, evt):
-        """
-        Save a data set to a text file
-        
-        :param evt: Menu event
-        
-        """
-       
-        path = None
-        wildcard = "Text files (*.txt)|*.txt|"\
-                    "CanSAS 1D files(*.xml)|*.xml" 
-        default_name = self.plots[self.graph.selected_plottable].label
+        default_name = data.label
         if default_name.count('.') > 0:
             default_name = default_name.split('.')[0]
         default_name += "_out"
         if self.parent != None:
-            self._default_save_location = self.parent._default_save_location
-        dlg = wx.FileDialog(self, "Choose a file",
-                            self._default_save_location,
-                            default_name, wildcard , wx.SAVE)
-       
-        if dlg.ShowModal() == wx.ID_OK:
-            path = dlg.GetPath()
-            # ext_num = 0 for .txt, ext_num = 1 for .xml
-            # This is MAC Fix
-            ext_num = dlg.GetFilterIndex()
-            if ext_num == 0:
-                format = '.txt'
-            else:
-                format = '.xml'
-            path = os.path.splitext(path)[0] + format
-            mypath = os.path.basename(path)
-            
-            #TODO: This is bad design. The DataLoader is designed 
-            #to recognize extensions.
-            # It should be a simple matter of calling the .
-            #save(file, data, '.xml') method
-            # of the sans.dataloader.loader.Loader class.
-            from sans.dataloader.loader import  Loader
-            #Instantiate a loader 
-            loader = Loader() 
-            data = self.plots[self.graph.selected_plottable]
-            format = ".txt"
-            if os.path.splitext(mypath)[1].lower() == format:
-                # Make sure the ext included in the file name
-                # especially on MAC
-                fName = os.path.splitext(path)[0] + format
-                self._onsaveTXT(fName)
-            format = ".xml"
-            if os.path.splitext(mypath)[1].lower() == format:
-                # Make sure the ext included in the file name
-                # especially on MAC
-                fName = os.path.splitext(path)[0] + format
-                loader.save(fName, data, format)
-            try:
-                self._default_save_location = os.path.dirname(path)
-                self.parent._default_save_location = self._default_save_location
-            except:
-                pass    
-        dlg.Destroy()
+            self.parent.save_data1d(data, default_name)
 
     def _add_more_tool(self):
Index: sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter2D.py
===================================================================
--- sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter2D.py	(revision b837e1fea125dbd2d557bed6650b1937595a680e)
+++ sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter2D.py	(revision 176fbf1f8ef3e3792beda5301f634bcec50501fe)
@@ -757,44 +757,5 @@
         default_name += "_out"
         if id in self.action_ids:         
-            
             path = None
-            wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
-            dlg = wx.FileDialog(self, "Choose a file",
-                                self._default_save_location,
-                                default_name, wildcard , wx.SAVE)
-           
-            if dlg.ShowModal() == wx.ID_OK:
-                path = dlg.GetPath()
-                # ext_num = 0 for .txt, ext_num = 1 for .xml
-                # This is MAC Fix
-                ext_num = dlg.GetFilterIndex()
-                if ext_num == 0:
-                    format = '.dat'
-                else:
-                    format = ''
-                path = os.path.splitext(path)[0] + format
-                mypath = os.path.basename(path)
-                
-                #TODO: This is bad design. The DataLoader is designed 
-                #to recognize extensions.
-                # It should be a simple matter of calling the .
-                #save(file, data, '.xml') method
-                # of the DataLoader.loader.Loader class.
-                from sans.dataloader.loader import  Loader
-                #Instantiate a loader 
-                loader = Loader() 
-                data = self.data2D
-
-                format = ".dat"
-                if os.path.splitext(mypath)[1].lower() == format:
-                    # Make sure the ext included in the file name
-                    # especially on MAC
-                    fName = os.path.splitext(path)[0] + format
-                    loader.save(fName, data, format)
-                try:
-                    self._default_save_location = os.path.dirname(path)
-                    self.parent._default_save_location = \
-                                            self._default_save_location 
-                except:
-                    pass    
-            dlg.Destroy()
+            self.parent.save_data2d(self.data2D, default_name)
+        
