Index: src/sas/dataloader/data_info.py
===================================================================
--- src/sas/dataloader/data_info.py	(revision 7eaf9f21f295baa6e9594bfada6f9dde6baa5f67)
+++ src/sas/dataloader/data_info.py	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
@@ -26,11 +26,10 @@
 import math
 
-
 class plottable_sesans1D:
     """
     SESANS is a place holder for 1D SESANS plottables.
     
-    #TODO: This was directly copied from the plottables_1D.
-    #TODO: The class has not been updated from there.
+    #TODO: This was directly copied from the plottables_1D. Modified Somewhat.
+    #Class has been updated.
     """
     # The presence of these should be mutually
@@ -38,6 +37,8 @@
     x = None
     y = None
+    lam = None
     dx = None
     dy = None
+    dlam = None
     ## Slit smearing length
     dxl = None
@@ -51,16 +52,20 @@
     _yunit = ''
     
-    def __init__(self, x, y, dx=None, dy=None, dxl=None, dxw=None):
+    def __init__(self, x, y, lam, dx=None, dy=None, dlam=None):
+#        print "SESANS plottable working"
         self.x = numpy.asarray(x)
         self.y = numpy.asarray(y)
+        self.lam = numpy.asarray(lam)
         if dx is not None:
             self.dx = numpy.asarray(dx)
         if dy is not None:
             self.dy = numpy.asarray(dy)
-        if dxl is not None:
-            self.dxl = numpy.asarray(dxl)
-        if dxw is not None: 
-            self.dxw = numpy.asarray(dxw)
-
+        if dlam is not None:
+            self.dlam = numpy.asarray(dlam)
+#        if dxl is not None:
+#            self.dxl = numpy.asarray(dxl)
+#        if dxw is not None: 
+#            self.dxw = numpy.asarray(dxw)
+#        print "SESANS plottable init fin"
     def xaxis(self, label, unit):
         """
@@ -69,9 +74,15 @@
         self._xaxis = label
         self._xunit = unit
-        
+        print "xaxis active"
+        print label
+        print unit
     def yaxis(self, label, unit):
         """
         set the y axis label and unit
         """
+        print "yaxis active"
+        print label
+        print unit
+        
         self._yaxis = label
         self._yunit = unit
@@ -750,5 +761,85 @@
         """
         return self._perform_union(other)
-                
+  
+class SESANSData1D(plottable_sesans1D, DataInfo):
+    """
+    SESANS 1D data class
+    """
+    x_unit = 'nm'
+    y_unit = 'a.u.'
+    
+    def __init__(self, x=None, y=None, lam=None, dy=None, dx=None, dlam=None):
+#        print "dat init"
+        DataInfo.__init__(self)
+#        print "dat init fin"
+        plottable_sesans1D.__init__(self, x, y, lam, dx, dy, dlam)
+#        print "SESANSdata1D init"
+    def __str__(self):
+        """
+        Nice printout
+        """
+#        print "string printer active"
+        _str =  "%s\n" % DataInfo.__str__(self)
+    
+        _str += "Data:\n"
+        _str += "   Type:         %s\n" % self.__class__.__name__
+        _str += "   X-axis:       %s\t[%s]\n" % (self._xaxis, self._xunit)
+        _str += "   Y-axis:       %s\t[%s]\n" % (self._yaxis, self._yunit)
+        _str += "   Length:       %g\n" % len(self.x)
+#        print _str
+        return _str
+#
+#    def is_slit_smeared(self):
+#        """
+#        Check whether the data has slit smearing information
+#        
+#        :return: True is slit smearing info is present, False otherwise
+#        
+#        """
+#        def _check(v):
+#            if (v.__class__ == list or v.__class__ == numpy.ndarray) \
+#                and len(v) > 0 and min(v) > 0:
+#                return True
+#            
+#            return False
+#        
+#        return _check(self.dxl) or _check(self.dxw)
+        
+    def clone_without_data(self, length=0, clone=None):
+        """
+        Clone the current object, without copying the data (which
+        will be filled out by a subsequent operation).
+        The data arrays will be initialized to zero.
+        
+        :param length: length of the data array to be initialized
+        :param clone: if provided, the data will be copied to clone
+        """
+        from copy import deepcopy
+#        print " SESANS data 1D clone active"
+        if clone is None or not issubclass(clone.__class__, Data1D):
+            x  = numpy.zeros(length)
+            dx = numpy.zeros(length)
+            lam  = numpy.zeros(length)
+            dlam = numpy.zeros(length)
+            y  = numpy.zeros(length)
+            dy = numpy.zeros(length)
+            clone = Data1D(x, y, dx=dx, dy=dy)
+        
+        clone.title          = self.title
+        clone.run            = self.run
+        clone.filename       = self.filename
+        clone.instrument     = self.instrument
+        clone.notes          = deepcopy(self.notes)
+        clone.process        = deepcopy(self.process)
+        clone.detector       = deepcopy(self.detector)
+        clone.sample         = deepcopy(self.sample)
+        clone.source         = deepcopy(self.source)
+        clone.collimation    = deepcopy(self.collimation)
+        clone.trans_spectrum = deepcopy(self.trans_spectrum)
+        clone.meta_data      = deepcopy(self.meta_data)
+        clone.errors         = deepcopy(self.errors)
+#        print "SESANS Data 1Dclone done"
+        return clone
+              
 class Data1D(plottable_1D, DataInfo):
     """
@@ -991,80 +1082,4 @@
         
         
-class SESANSData1D(plottable_sesans1D, DataInfo):
-    """
-    SESANS 1D data class
-    """
-    x_unit = '1/A'
-    y_unit = '1/cm'
-    
-    def __init__(self, x, y, dx=None, dy=None):
-        DataInfo.__init__(self)
-        plottable_sesans1D.__init__(self, x, y, dx, dy)
-        
-    def __str__(self):
-        """
-        Nice printout
-        """
-        _str =  "%s\n" % DataInfo.__str__(self)
-    
-        _str += "Data:\n"
-        _str += "   Type:         %s\n" % self.__class__.__name__
-        _str += "   X-axis:       %s\t[%s]\n" % (self._xaxis, self._xunit)
-        _str += "   Y-axis:       %s\t[%s]\n" % (self._yaxis, self._yunit)
-        _str += "   Length:       %g\n" % len(self.x)
-
-        return _str
-
-    def is_slit_smeared(self):
-        """
-        Check whether the data has slit smearing information
-        
-        :return: True is slit smearing info is present, False otherwise
-        
-        """
-        def _check(v):
-            if (v.__class__ == list or v.__class__ == numpy.ndarray) \
-                and len(v) > 0 and min(v) > 0:
-                return True
-            
-            return False
-        
-        return _check(self.dxl) or _check(self.dxw)
-        
-    def clone_without_data(self, length=0, clone=None):
-        """
-        Clone the current object, without copying the data (which
-        will be filled out by a subsequent operation).
-        The data arrays will be initialized to zero.
-        
-        :param length: length of the data array to be initialized
-        :param clone: if provided, the data will be copied to clone
-        """
-        from copy import deepcopy
-        
-        if clone is None or not issubclass(clone.__class__, Data1D):
-            x  = numpy.zeros(length)
-            dx = numpy.zeros(length)
-            y  = numpy.zeros(length)
-            dy = numpy.zeros(length)
-            clone = Data1D(x, y, dx=dx, dy=dy)
-        
-        clone.title          = self.title
-        clone.run            = self.run
-        clone.filename       = self.filename
-        clone.instrument     = self.instrument
-        clone.notes          = deepcopy(self.notes)
-        clone.process        = deepcopy(self.process)
-        clone.detector       = deepcopy(self.detector)
-        clone.sample         = deepcopy(self.sample)
-        clone.source         = deepcopy(self.source)
-        clone.collimation    = deepcopy(self.collimation)
-        clone.trans_spectrum = deepcopy(self.trans_spectrum)
-        clone.meta_data      = deepcopy(self.meta_data)
-        clone.errors         = deepcopy(self.errors)
-        
-        return clone
-    
-    
 class Data2D(plottable_2D, DataInfo):
     """
Index: src/sas/dataloader/loader.py
===================================================================
--- src/sas/dataloader/loader.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/dataloader/loader.py	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
@@ -363,4 +363,5 @@
         :return: DataInfo object
         """
+        print self.__registry.extensions
         return self.__registry.load(file, format)
     
Index: src/sas/dataloader/readers/associations.py
===================================================================
--- src/sas/dataloader/readers/associations.py	(revision 5dfdfa7b1103a8dfb020e940cb1e38dcde633256)
+++ src/sas/dataloader/readers/associations.py	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
@@ -91,5 +91,6 @@
     #import tiff_reader
     import nexus_reader
-
+    import sesans_reader
+    registry_function(sesans_reader)
     registry_function(abs_reader)
     registry_function(ascii_reader)
Index: src/sas/dataloader/readers/defaults.json
===================================================================
--- src/sas/dataloader/readers/defaults.json	(revision 5dfdfa7b1103a8dfb020e940cb1e38dcde633256)
+++ src/sas/dataloader/readers/defaults.json	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
@@ -5,4 +5,8 @@
             "-extension":".xml",
             "-reader":"cansas_reader"
+         },
+         {
+            "-extension":".ses",
+            "-reader":"sesans_reader"
          },
          {
Index: src/sas/dataloader/readers/sesans_reader.py
===================================================================
--- src/sas/dataloader/readers/sesans_reader.py	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
+++ src/sas/dataloader/readers/sesans_reader.py	(revision 5e326a64f3587643c6a4cb468b4e95e5c900be9b)
@@ -0,0 +1,270 @@
+"""
+    SESANS reader
+"""
+
+import numpy
+import os
+from sas.dataloader.data_info import SESANSData1D
+
+# Check whether we have a converter available
+has_converter = True
+try:
+    from sas.data_util.nxsunit import Converter
+except:
+    has_converter = False
+_ZERO = 1e-16
+
+class Reader:
+    """
+    Class to load sesans files (6 columns).
+    """
+    ## File type
+    type_name = "SESANS"
+    
+    ## Wildcards
+    type = ["SESANS files (*.ses)|*.ses",
+            "SESANS files (*..sesans)|*.sesans"]
+    ## List of allowed extensions
+    ext = ['.ses', '.SES', '.sesans', '.SESANS']
+    
+    ## Flag to bypass extension check
+    allow_all = True
+    
+    def read(self, path):
+        
+#        print "reader triggered"
+        
+        """
+        Load data file
+        
+        :param path: file path
+        
+        :return: SESANSData1D object, or None
+        
+        :raise RuntimeError: when the file can't be opened
+        :raise ValueError: when the length of the data vectors are inconsistent
+        """
+        if os.path.isfile(path):
+            basename = os.path.basename(path)
+            _, extension = os.path.splitext(basename)
+            if self.allow_all or extension.lower() in self.ext:
+                try:
+                    # Read in binary mode since GRASP frequently has no-ascii
+                    # characters that brakes the open operation
+                    input_f = open(path,'rb')
+                except:
+                    raise  RuntimeError, "sesans_reader: cannot open %s" % path
+                buff = input_f.read()
+#                print buff
+                lines = buff.splitlines()
+#                print lines
+                #Jae could not find python universal line spliter:
+                #keep the below for now
+                # some ascii data has \r line separator,
+                # try it when the data is on only one long line
+#                if len(lines) < 2 :
+#                    lines = buff.split('\r')
+                 
+                x  = numpy.zeros(0)
+                y  = numpy.zeros(0)
+                dy = numpy.zeros(0)
+                lam  = numpy.zeros(0)
+                dlam = numpy.zeros(0)
+                dx = numpy.zeros(0)
+                
+               #temp. space to sort data
+                tx  = numpy.zeros(0)
+                ty  = numpy.zeros(0)
+                tdy = numpy.zeros(0)
+                tlam  = numpy.zeros(0)
+                tdlam = numpy.zeros(0)
+                tdx = numpy.zeros(0)
+#                print "all good"
+                output = SESANSData1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam)
+#                print output                
+                self.filename = output.filename = basename
+                
+                
+                data_conv_z = None
+                data_conv_P = None
+#                print "passing"
+                if has_converter == True and output.x_unit != 'A':
+                    data_conv_z = Converter('nm')
+                    # Test it
+                    data_conv_z(1.0, output.x_unit)
+#                    print data_conv_z
+#                    print data_conv_z(1.0, output.x_unit)
+                if has_converter == True and output.y_unit != ' ':
+                    data_conv_P = Converter('a.u.')
+                    # Test it
+                    data_conv_P(1.0, output.y_unit)
+#                    print data_conv_P
+#                    print data_conv_P(1.0, output.y_unit)
+                # The first good line of data will define whether
+                # we have 2-column or 3-column ascii
+#                print output.x_unit
+#                print output.y_unit
+                
+#                print "past output"
+                
+#                has_error_dx = None
+#                has_error_dy = None
+                
+#                #Initialize counters for data lines and header lines.
+#                is_data = False  # Has more than 5 lines
+#                # More than "5" lines of data is considered as actual
+#                # data unless that is the only data
+#                mum_data_lines = 5
+#                # To count # of current data candidate lines
+#                i = -1
+#                # To count total # of previous data candidate lines
+#                i1 = -1
+#                # To count # of header lines
+#                j = -1
+#                # Helps to count # of header lines
+#                j1 = -1
+#                #minimum required number of columns of data; ( <= 4).
+#                lentoks = 2
+                paramnames=[]
+                paramvals=[]
+                zvals=[]
+                dzvals=[]
+                lamvals=[]
+                dlamvals=[]
+                Pvals=[]
+                dPvals=[]
+#                print x
+#                print zvals
+                for line in lines:
+                    # Initial try for CSV (split on ,)
+#                    print line
+                    line=line.strip()
+#                    print line
+                    toks = line.split('\t')
+#                    print toks
+                    if len(toks)==2:
+                        paramnames.append(toks[0])
+#                        print paramnames
+                        paramvals.append(toks[1])
+#                        print paramvals
+                    if len(toks)>5:
+                        zvals.append(toks[0])
+                        dzvals.append(toks[1])
+                        lamvals.append(toks[2])
+                        dlamvals.append(toks[3])
+                        Pvals.append(toks[4])
+                        dPvals.append(toks[5])
+                    else:
+                        continue
+#                print varheaders
+#                print paramnames
+#                print paramvals
+#                print zvals  
+#                print len(zvals)
+                
+                x=[]
+                y=[]
+                lam=[]
+                dx=[]
+                dy=[]
+                dlam=[]
+                varheader=[zvals[0],dzvals[0],lamvals[0],dlamvals[0],Pvals[0],dPvals[0]]
+#                print varheader
+                valrange=range(len(zvals)-1)
+#                print valrange
+                for i in valrange:
+                    x.append(float(zvals[i+1]))
+                    y.append(float(Pvals[i+1]))
+                    lam.append(float(lamvals[i+1]))
+                    dy.append(float(dPvals[i+1]))
+                    dx.append(float(dzvals[i+1]))
+                    dlam.append(float(dlamvals[i+1]))
+                    
+                x,y,lam,dy,dx,dlam = [
+                   numpy.asarray(v, 'double')
+                   for v in (x,y,lam,dy,dx,dlam)
+                ]
+
+#                print x
+#                print y
+#                print dx
+#                print dy
+#                print len(x)
+#                print len(y)
+#                print len(dx)
+#                print len(dy)
+                
+                
+                input_f.close()
+                # Sanity check
+#                if has_error_dy == True and not len(y) == len(dy):
+#                    msg = "sesans_reader: y and dy have different length"
+#                    raise RuntimeError, msg
+#                if has_error_dx == True and not len(x) == len(dx):
+#                    msg = "sesans_reader: y and dy have different length"
+#                    raise RuntimeError, msg
+#                # If the data length is zero, consider this as
+#                # though we were not able to read the file.
+#                if len(x) == 0:
+#                    raise RuntimeError, "sesans_reader: could not load file"
+#                print "alive"
+                #Let's re-order the data to make cal.
+                # curve look better some cases
+#                ind = numpy.lexsort((ty, tx))
+#                for i in ind:
+#                    x[i] = tx[ind[i]]
+#                    y[i] = ty[ind[i]]
+#                    if has_error_dy == True:
+#                        dy[i] = tdy[ind[i]]
+#                    if has_error_dx == True:
+#                        dx[i] = tdx[ind[i]]
+                # Zeros in dx, dy
+#                if has_error_dx:
+#                    dx[dx == 0] = _ZERO
+#                if has_error_dy:
+#                    dy[dy == 0] = _ZERO
+                #Data
+                output.x = x #[x != 0]
+#                print output.x
+                output.y = y #[x != 0]
+#                print output.y
+#                output.dy = dy[x != 0] if has_error_dy == True\
+#                    else numpy.zeros(len(output.y))
+#                output.dx = dx[x != 0] if has_error_dx == True\
+#                    else numpy.zeros(len(output.x))
+                output.dy = dy
+                output.dx = dx
+                output.lam = lam
+                output.dlam = dlam
+
+
+#                print "still alive"                
+#                if data_conv_z is not None:
+#                    output.xaxis("\\rm{z}", output.x_unit)
+#                else:
+#                    output.xaxis("\\rm{z}", 'nm')
+#                if data_conv_P is not None:
+#                    output.yaxis("\\rm{P/P0}", output.y_unit)
+#                else:
+#                    output.yaxis("\\rm{P/P0}", "a.u.")
+                output.xaxis("\\rm{z}", 'A')   
+                output.yaxis("\\rm{P/P0}", " ")
+                # Store loading process information
+                output.meta_data['loader'] = self.type_name
+                output.sample.thickness = float(paramvals[6])
+                output.sample.name = paramvals[1]
+                output.sample.ID = paramvals[0]
+                output.sample.zacceptance=float(paramvals[7])
+#                print output                
+
+#                print "sesans_reader end"
+                
+                if len(output.x) < 1:
+                    raise RuntimeError, "%s is empty" % path
+#                print output
+                
+                return output
+            
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        return None
Index: src/sas/guiframe/media/graph_help.rst
===================================================================
--- src/sas/guiframe/media/graph_help.rst	(revision 3fd3d5a4a3e6ac116eb2c29ed70c05d4778d41e6)
+++ src/sas/guiframe/media/graph_help.rst	(revision 1394952b7caf92c44bda747fb4a54aa7117aa978)
@@ -286,6 +286,7 @@
 
 1D data can be saved in either ASCII text (.TXT) or CanSAS/SASXML (.XML) 
-formats (see 1D_Formats_). 2D data can only be saved in the NIST 2D format 
-(.DAT) (see 2D_Formats_).
+formats (see :ref:`1D_Formats`).
+
+2D data can only be saved in the NIST 2D format (.DAT) (see :ref:`2D_Formats`).
 
 .. _Linear_Fit:
Index: src/sas/guiframe/report_dialog.py
===================================================================
--- src/sas/guiframe/report_dialog.py	(revision e8bb5b62d717c7b44481a4b621030699e4efdaf4)
+++ src/sas/guiframe/report_dialog.py	(revision e8bb5b62d717c7b44481a4b621030699e4efdaf4)
@@ -0,0 +1,144 @@
+"""
+    Base class for reports. Child classes will need to implement
+    the onSave() method.
+"""
+import wx
+import logging
+import sys
+import wx.html as html
+
+ISPDF = False
+if sys.platform == "win32":
+    _STATICBOX_WIDTH = 450
+    PANEL_WIDTH = 500 
+    PANEL_HEIGHT = 700
+    FONT_VARIANT = 0
+    ISPDF = True
+elif sys.platform == "darwin":
+    _STATICBOX_WIDTH = 480
+    PANEL_WIDTH = 530
+    PANEL_HEIGHT = 700
+    FONT_VARIANT = 1
+    ISPDF = True
+
+class BaseReportDialog(wx.Dialog):
+    
+    def __init__(self, report_list, *args, **kwds):
+        """
+        Initialization. The parameters added to Dialog are:
+        
+        :param report_list: list of html_str, text_str, image for report
+        """
+        kwds["style"] = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE
+        super(BaseReportDialog, self).__init__(*args, **kwds)
+        kwds["image"] = 'Dynamic Image'
+
+        # title
+        self.SetTitle("Report")
+        # size
+        self.SetSize((720, 650))
+        # font size
+        self.SetWindowVariant(variant=FONT_VARIANT)
+        # check if tit is MAC
+        self.is_pdf = ISPDF
+        # report string
+        self.report_list = report_list
+        # wild card
+        # pdf supporting only on MAC
+        if self.is_pdf:
+            self.wild_card = ' PDF files (*.pdf)|*.pdf|'
+            self.index_offset = 0
+        else:
+            self.wild_card = ''
+            self.index_offset = 1
+        self.wild_card += 'HTML files (*.html)|*.html|'
+        self.wild_card += 'Text files (*.txt)|*.txt'
+
+    def _setup_layout(self):
+        """
+        Set up layout
+        """
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        
+        # buttons
+        button_close = wx.Button(self, wx.ID_OK, "Close")
+        button_close.SetToolTipString("Close this report window.")
+        hbox.Add(button_close)
+        button_close.SetFocus()
+
+        button_preview = wx.Button(self, wx.NewId(), "Preview")
+        button_preview.SetToolTipString("Print preview this report.")
+        button_preview.Bind(wx.EVT_BUTTON, self.onPreview,
+                            id=button_preview.GetId()) 
+        hbox.Add(button_preview)
+
+        button_print = wx.Button(self, wx.NewId(), "Print")
+        button_print.SetToolTipString("Print this report.")
+        button_print.Bind(wx.EVT_BUTTON, self.onPrint,
+                          id=button_print.GetId())
+        hbox.Add(button_print)
+        
+        button_save = wx.Button(self, wx.NewId(), "Save")
+        button_save.SetToolTipString("Save this report.")
+        button_save.Bind(wx.EVT_BUTTON, self.onSave, id=button_save.GetId())
+        hbox.Add(button_save)
+        
+        # panel for report page
+        vbox = wx.BoxSizer(wx.VERTICAL)
+        # html window
+        self.hwindow = html.HtmlWindow(self, style=wx.BORDER)
+        # set the html page with the report string
+        self.hwindow.SetPage(self.report_html)
+        
+        # add panels to boxsizers
+        vbox.Add(hbox)
+        vbox.Add(self.hwindow, 1, wx.EXPAND|wx.ALL,0)
+
+        self.SetSizer(vbox)
+        self.Centre()
+        self.Show(True)
+
+    def onPreview(self, event=None):
+        """
+        Preview
+        : event: Preview button event
+        """
+        previewh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
+        previewh.PreviewText(self.report_html)
+        
+    def onPrint(self, event=None):
+        """
+        Print
+        : event: Print button event
+        """
+        printh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
+        printh.PrintText(self.report_html)
+
+    def OnClose(self, event=None):
+        """
+        Close the Dialog
+        : event: Close button event
+        """
+        self.Close()
+    
+    def HTML2PDF(self, data, filename):
+        """
+        Create a PDF file from html source string.
+        Returns True is the file creation was successful. 
+        : data: html string
+        : filename: name of file to be saved
+        """
+        try:
+            from xhtml2pdf import pisa
+            # open output file for writing (truncated binary)
+            resultFile = open(filename, "w+b")
+            # convert HTML to PDF
+            pisaStatus = pisa.CreatePDF(data, dest=resultFile)
+            # close output file
+            resultFile.close()
+            self.Update()
+            return pisaStatus.err
+        except:
+            logging.error("Error creating pdf: %s" % sys.exc_value)
+        return False
+
Index: src/sas/models/media/model_functions.rst
===================================================================
--- src/sas/models/media/model_functions.rst	(revision 3342eb3a2a1850b10ffc3e6d58839a42ee512236)
+++ src/sas/models/media/model_functions.rst	(revision 7072ce6239234d337481e73082d58570af29eaf3)
@@ -10,5 +10,4 @@
 
 .. To do:
-.. Remove the 'This is xi' & 'This is zeta' lines before release!
 .. Add example parameters/plots for the CoreShellEllipsoidXTModel
 .. Add example parameters/plots for the RectangularPrism models
@@ -20,4 +19,6 @@
 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
 
+
+.. note::  The contents of this document are awaiting proof reading. Feb2015
 
 
@@ -169,4 +170,5 @@
 - RaspBerryModel_
 - CoreShellModel_ (including magnetic 2D version)
+- MicelleSphCoreModel_
 - CoreMultiShellModel_ (including magnetic 2D version)
 - Core2ndMomentModel_
@@ -3372,4 +3374,26 @@
 
 
+.. _MicelleSphCoreModel:
+
+**2.1.42. MicelleSphCoreModel**
+
+This model provides the form factor, *P(q)*, for a micelle with a spherical core 
+and Gaussian polymer chains attached to the surface.
+
+*2.1.42.1. Definition*
+
+The 1D scattering intensity for this model is calculated according to the equations given by Pedersen
+(Pedersen, 2000).
+
+*2.1.42.2. Validation of the MicelleSphCoreModel*
+
+This model has not yet been validated. Feb2015
+
+REFERENCES
+
+J Pedersen, *J. Appl. Cryst.*, 33 (2000) 637-640
+
+
+
 2.2 Shape-independent Functions
 -------------------------------
Index: src/sas/perspectives/calculator/help_panel.py
===================================================================
--- src/sas/perspectives/calculator/help_panel.py	(revision b9a5f0eb8e8cbff8f8d934bbfa4ea18168141e13)
+++ 	(revision )
@@ -1,130 +1,0 @@
-#!/usr/bin/python
-"""
-Help panel for calculator
-"""
-import os
-import wx
-import wx.html as html
-from wx.lib.splitter import MultiSplitterWindow
-import sas.perspectives.calculator as calculator
-
-
-class HelpWindow(wx.Frame):
-    """
-    """
-    def __init__(self, parent, id=-1, title="Tool Help", pageToOpen=None, 
-                                                    size=(700, 450)):
-        wx.Frame.__init__(self, parent, id, title, size=size)
-        """
-             contains help info
-        """
-        self.SetTitle(title) 
-        splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
-        rpanel = wx.Panel(splitter, -1)
-        self.lpanel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN)
-        
-        vbox = wx.BoxSizer(wx.VERTICAL)
-        header = wx.Panel(rpanel, -1)
-        header.SetBackgroundColour('#6666FF')
-        header.SetForegroundColour('WHITE')
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        st = wx.StaticText(header, -1, 'Contents', (5, 5))
-        font = st.GetFont()
-        font.SetPointSize(10)
-        st.SetFont(font)
-        hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
-        header.SetSizer(hbox)
-        vbox.Add(header, 0, wx.EXPAND)
-       
-        vboxl = wx.BoxSizer(wx.VERTICAL)
-        headerl = wx.Panel(self.lpanel, -1, size=(-1, 20))
-       
-        headerl.SetBackgroundColour('#6666FF')
-        headerl.SetForegroundColour('WHITE')
-        hboxl = wx.BoxSizer(wx.HORIZONTAL)
-        lst = wx.StaticText(headerl, -1, 'Menu', (5, 5))
-        fontl = lst.GetFont()
-        fontl.SetPointSize(10)
-        lst.SetFont(fontl)
-        hboxl.Add(lst, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
-        headerl.SetSizer(hboxl)
-        vboxl.Add(headerl, 0, wx.EXPAND)
-        self.lhelp = html.HtmlWindow(self.lpanel, -1, style=wx.NO_BORDER)
-        self.rhelp = html.HtmlWindow(rpanel, -1, style=wx.NO_BORDER, 
-                                     size=(500,-1))
-        if pageToOpen != None:
-            path = os.path.dirname(pageToOpen)
-            self.path = os.path.join(path, "gen_sas_help.html")
-        else:
-            self.path = calculator.get_data_path(media='media')
-       
-        page1 = """<html>
-            <body>
-             <p>Select topic on Menu</p>
-            </body>
-            </html>"""
-        self.rhelp.SetPage(page1)
-        page = """<html>
-            <body>
-            <ul>
-            <li><a href ="data_operator_help.html" 
-            target ="showframe">Data Operator</a><br></li>
-            <li><a href ="sld_calculator_help.html" 
-            target ="showframe">SLD Calculator</a><br></li>
-            <li><a href ="density_calculator_help.html" 
-            target ="showframe">Density Calculator</a><br></li>
-            <li><a href ="slit_calculator_help.html" 
-            target ="showframe">Slit Size Calculator</a><br></li>
-            <li><a href ="kiessig_calculator_help.html" 
-            target ="showframe">Kiessig Thickness Calculator</a><br></li>
-            <li><a href ="resolution_calculator_help.html" 
-            target ="showframe">Resolution Estimator</a><br></li>
-            <li><a href ="gen_sas_help.html" 
-            target ="showframe">Generic Scattering Calculator</a><br></li>
-            <li><a href ="pycrust_help.html" 
-            target ="showframe">Python Shell</a><br></li>
-            <li><a href ="load_image_help.html" 
-            target ="showframe">Image Viewer</a><br></li>
-            </ul>
-            </body>
-            </html>"""
-
-        self.lhelp.SetPage(page)
-        self.lhelp.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked)
-        if  pageToOpen != None:
-            self.rhelp.LoadPage(str(pageToOpen))
-        vbox.Add(self.rhelp, 1, wx.EXPAND)
-        vboxl.Add(self.lhelp, 1, wx.EXPAND)
-        rpanel.SetSizer(vbox)
-        self.lpanel.SetSizer(vboxl)
-        self.lpanel.SetFocus()
-        
-        vbox1 = wx.BoxSizer(wx.HORIZONTAL)
-        vbox1.Add(splitter, 1, wx.EXPAND)
-        splitter.AppendWindow(self.lpanel, 200)
-        splitter.AppendWindow(rpanel)
-        self.SetSizer(vbox1)
-        
-        self.splitter = splitter
-        self.Centre()
-        self.Show(True)
-        
-    def OnLinkClicked(self, event):
-        """
-            Function to diplay html page related to the hyperlinktext selected
-        """
-        link = event.GetLinkInfo().GetHref()
-        link = os.path.join(self.path, link)
-        self.rhelp.LoadPage(link)
-        
-        
-class ViewApp(wx.App):
-    def OnInit(self):
-        frame = HelpWindow(None, -1, 'HelpWindow')    
-        frame.Show(True)
-        self.SetTopWindow(frame)
-        return True
-        
-if __name__ == "__main__": 
-    app = ViewApp(0)
-    app.MainLoop()     
Index: src/sas/perspectives/calculator/image_viewer.py
===================================================================
--- src/sas/perspectives/calculator/image_viewer.py	(revision 7a04dbb34bb699a5460b3ad23209d05b641f3265)
+++ src/sas/perspectives/calculator/image_viewer.py	(revision d90f91bd16ef019bd8af5b7140db6f2cb7587f1d)
@@ -16,4 +16,6 @@
 from sas.dataloader.data_info import Detector
 from sas.dataloader.manipulations import reader2D_converter
+from sas.guiframe.documentation_window import DocumentationWindow
+
 _BOX_WIDTH = 60
 IS_WIN = True
@@ -59,5 +61,4 @@
                 plot_frame = ImageFrame(parent, -1, basename, img)
                 plot_frame.Show(False)
-                #plot_frame.im_show(img)
                 ax = plot_frame.plotpanel
                 if not is_png:
@@ -73,5 +74,4 @@
             except:
                 print "parent", parent
-                raise
                 err_msg += "Failed to load '%s'.\n"% basename
         if err_msg:
@@ -80,5 +80,4 @@
             else:
                 print err_msg
-
         
     def choose_data_file(self, location=None):
@@ -86,24 +85,9 @@
         Open a file dialog to allow loading a file
         """
-        parent = self.parent
         path = None
         if location == None:
             location = os.getcwd()
-        wlist = ''
-        elist = ["All images (*.png, *.bmp, *.gif, *.jpg, *.tif, *.tiff) | \
-                *.png; *.bmp; *.gif; *.jpg; *.tif; *.tiff", 
-                "PNG files (*.PNG, *.png) | *.png", 
-                "BMP files (*.BMP, *.bmp) | *.bmp", 
-                "GIF files (*.GIF, *.gif) | *.gif",
-                "JPG files (*.JPG, *.jpg) | *.jpg",
-                "TIF files (*.TIF, *.tif) | *.tif",
-                "TIFF files (*.TIFF, *.tiff) | *.tiff"]
-        if not IS_WIN:
-            del elist[0]
-        elist.append("All files (*.*) | *.*")
-        wlist = '|'.join(elist)        
-        style = wx.OPEN|wx.FD_MULTIPLE
-        dlg = wx.FileDialog(parent, "Image Viewer: Choose a image file", 
-                            location, "", wlist, style=style)
+        dlg = wx.FileDialog(self.parent, "Image Viewer: Choose a image file", 
+                            location, "", "", style=wx.FD_OPEN|wx.FD_MULTIPLE)
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPaths()
@@ -156,26 +140,17 @@
 
     def on_help(self, event):    
-        """
-        Image Viewer help panel
-        """
-        from sas.perspectives.calculator.help_panel import  HelpWindow
-        # Get models help model_function path
-        import sas.perspectives.calculator as calmedia
-
-        media = calmedia.get_data_path(media='media')
-        path = os.path.join(media,"load_image_help.html") 
-        name = "Image Viewer"
-        frame = HelpWindow(self, -1, title=' Help: Image Viewer',  
-                           pageToOpen=path, size=(640, 450))   
-        try: 
-            frame.splitter.DetachWindow(frame.lpanel)
-            # Display only the right side one
-            frame.lpanel.Hide() 
-            frame.Show(True)
-        except:
-            frame.Destroy() 
-            msg = 'Display Error\n'
-            info = "Info"
-            wx.MessageBox(msg, info)
+        """       
+        Bring up Image Viewer Documentation from the image viewer window 
+        whenever the help menu item "how to" is clicked. Calls 
+        DocumentationWindow with the path of the location within the
+        documentation tree (after /doc/ ....".  
+        
+        :param evt: Triggers on clicking "how to" in help menu
+        """
+                
+        _TreeLocation = "user/perspectives/calculator/image_viewer_help.html"
+        _doc_viewer = DocumentationWindow(self, -1, \
+             _TreeLocation,"Image Viewer Help")
+        
             
 class SetDialog(wx.Dialog):
Index: src/sas/perspectives/calculator/media/data_operator_help.rst
===================================================================
--- src/sas/perspectives/calculator/media/data_operator_help.rst	(revision 98b30b46ac241d857a5698740991daae2c25c3c2)
+++ src/sas/perspectives/calculator/media/data_operator_help.rst	(revision 684fadea996acb945349f183745ff53188353534)
@@ -9,9 +9,10 @@
 Description
 -----------
-This dialog panel provides arithmetic operations between two data sets (the 
-last data set could be a number).
 
-When data1 and data2 are selected, their x (or qx and qy for 2D) value(s)
-must match with each other.
+This tool permits arithmetic operations between two data sets. Alternatively, 
+the last data set can be a number.
+
+*NOTE! When* Data1 *and* Data2 *are both data, their Q (or Qx and Qy for 2D) 
+value(s) must match with each other UNLESS using the 'append' operator.*
 
 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
@@ -19,21 +20,36 @@
 How To
 ------
-1. Type the data name resulted from an operation.
 
-2) Select a data/theory in the drop down menus. When data2 is set to number, 
-   type a number in the text control box.
+1) Enure you have loaded data into the *Data Explorer* (see :ref:`Load_Data`).
 
-3) Select an arithmetic operator symbol; + (for addition), - (for subtraction), 
-   * (for multiplication), / (for division), and | (for combination of two data
-   sets).
+2) Select *Data Operation* from the *Tool* menu on the SasView toolbar.
 
-   If two data sets do not match, the operation will fail and the background color
-   of the combo box items will turn to red (WIN only).
+3) Select a dataset/theory in the drop-down menu *Data1*. A mini-plot of the
+   data will appear underneath.
 
-4) If the operation is successful, hit the Apply button to make the new data.
-   Then the data name will be shown up in the data box in the data explorer.
+4) Select a dataset/theory in the drop-down menu *Data2* or select *Number* 
+   and enter a number in the box that appears alongside.
 
-Note: Any errors and warnings will be displayed at the bottom of the SasView
-window.
+5) Select an arithmetic operator symbol from the *Operator* drop-down. The 
+   available operators are:
+   
+*  + (for addition)
+*  - (for subtraction), 
+*  * (for multiplication)
+*  / (for division)
+*  | (for combination of two data sets)
+
+   If two data sets do not match, the operation will fail and the background 
+   color of the combo box items will turn to red (WIN only).
+
+6) If the operation is successful, hit the Apply button to make the new dataset.
+   The new dataset will appear in the *Data Explorer*.
+
+*NOTE! Any errors and warnings will be displayed at the bottom of the SasView
+window.*
 
 .. image:: data_oper_pic.png
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+.. note::  This help document was last changed by Steve King, 18Feb2015 
Index: src/sas/perspectives/calculator/media/density_calculator_help.rst
===================================================================
--- src/sas/perspectives/calculator/media/density_calculator_help.rst	(revision ec392464eef959a5c2e87e6a72ed72fd7e947a07)
+++ src/sas/perspectives/calculator/media/density_calculator_help.rst	(revision 054a3adbdd801eeb581a05fa28b4d54492c8e75a)
@@ -10,5 +10,5 @@
 -----------
 
-This tool is to calculate the mass density from the molar volume or vice 
+This tool calculates the mass density from the molar volume or vice 
 versa. To calculate the mass density, the chemical formula and molar volume 
 should be provided.
@@ -19,15 +19,15 @@
 ------
 
-1. Molecular Formula: The chemical formula of ONE molecule or ONE atom. For 
-mixtures, the ratio of the each molecules should be used; for example, 
-(H2O)0.5(D2O)0.5.
+1) Enter the empirical formula of a molecule. For mixtures, the ratio of each 
+   of the molecules should be used, for example, (H2O)0.5(D2O)0.5.
 
-2. Select input (molar volume or mass density) from combobox. Then type in the 
-input value.
+2) Use the input combo box to choose between molar volume or mass density and 
+   then type in an input value.
 
-3. Click the 'Calculate' button to perform the calculation.
-
-4. Outputs also include the molar mass (weight) that depends only on the 
-chemical formula
+3) Click the 'Calculate' button to perform the calculation.
 
 .. image:: density_tutor.gif
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+.. note::  This help document was last changed by Steve King, 18Feb2015
Index: src/sas/perspectives/fitting/basepage.py
===================================================================
--- src/sas/perspectives/fitting/basepage.py	(revision 4380c0369305596a099427fbfa5f6d1a5b8d62d1)
+++ src/sas/perspectives/fitting/basepage.py	(revision c1694f88ee64a0dfcedb2f35de163aba684dc2a4)
@@ -26,4 +26,6 @@
 from sas.perspectives.fitting.pagestate import PageState
 from sas.guiframe.CategoryInstaller import CategoryInstaller
+from sas.guiframe.documentation_window import DocumentationWindow
+
 
 (PageInfoEvent, EVT_PAGE_INFO) = wx.lib.newevent.NewEvent()
@@ -2916,48 +2918,63 @@
         return graphs, canvases
 
-    def on_model_help_clicked(self, event):
-        """
-        Function called when 'Details' button is pressed next to model
-        of interest.  As of Feb 2015 this function follows two paths:
-        For regular models that ship with the release, it calls the Sphinx
-        generated html documentation.  For plugin models it still uses the
-        old pop up window reading the description provided in the model.
-        
-        This will presumably be deprecated when the sas mdels team decides
-        on how to discover new models and grab their documentation from the
-        file.
-        
-        PDB 18 Feb 2015
-        
-        :param evt: on Details Button pressed event
-        """
-        from sas.perspectives.fitting.help_panel import  HelpWindow
-        from sas.models import get_data_path
-        
-        # Get models help model_function path
-        path = get_data_path(media='media')
-        model_path = os.path.join(path, "model_functions.html")
+    def on_function_help_clicked(self, event):
+        """
+        Function called when 'Help' button is pressed next to model
+        of interest.  This calls DocumentationWindow from 
+        documentation_window.py. It will load the top level of the model
+        help documenation sphinx generated html if no model is presented.
+        If a model IS present then if documention for that model exists
+        it will load to that  point otherwise again it will go to the top.
+        For Wx2.8 and below is used (i.e. non-released through installer)
+        a browser is loaded and the top of the model documentation only is
+        accessible because webbrowser module does not pass anything after
+        the # to the browser.
+        
+        :param evt: on Help Button pressed event
+        """
+
         if self.model == None:
             name = 'index.html'
         else:
             name = self.formfactorbox.GetValue()
-        frame = HelpWindow(None, -1, pageToOpen=model_path)
-        #If model name exists and model is not a custom model
-        #mod_cat = self.categorybox.GetStringSelection()
-        if frame.rhelp.HasAnchor(name):
-            frame.Show(True)
-            frame.rhelp.ScrollToAnchor(name)
+
+        if self.model != None:  
+            _docspath='user/models/model_functions.html#' + name
+            _doc_viewer = DocumentationWindow(self, -1, _docspath, name + "Help")
         else:
-            if self.model != None:
-                frame.Destroy()
-                msg = 'Model description:\n'
-                if str(self.model.description).rstrip().lstrip() == '':
-                    msg += "Sorry, no information is available for this model."
-                else:
-                    msg += self.model.description + '\n'
-                info = "Info"
-                wx.MessageBox(msg, info)
+            _doc_viewer = DocumentationWindow(self, -1, "index.html", \
+                                                "General Help")
+
+
+    def on_model_help_clicked(self, event):
+        """
+        Function called when 'Description' button is pressed next to model
+        of interest.  This calls the Description embedded in the model. This
+        should work with either Wx2.8 and lower or higher. If no model is
+        selected it will give the message that a model must be chosen first
+        in the box that would normally contain the description.  If a badly
+        behaved model is encountered which has no description then it will
+        give the message that none is available.
+        
+        :param evt: on Description Button pressed event
+        """
+
+        if self.model == None:
+            name = 'index.html'
+        else:
+            name = self.formfactorbox.GetValue()
+
+        msg = 'Model description:\n'
+        info = "Info"
+        if self.model != None:
+#                frame.Destroy()
+            if str(self.model.description).rstrip().lstrip() == '':
+                msg += "Sorry, no information is available for this model."
             else:
-                frame.Show(True)
+                msg += self.model.description + '\n'
+            wx.MessageBox(msg, info)
+        else:
+            msg += "You must select a model to get information on this"
+            wx.MessageBox(msg, info)
 
     def _on_mag_help(self, event):    
@@ -2966,5 +2983,5 @@
         is clicked. Calls DocumentationWindow with the path of the location 
         within the documentation tree (after /doc/ ....". When using old 
-        versions of Wx When (i.e. before 2.9 and therefore not part of release
+        versions of Wx (i.e. before 2.9 and therefore not part of release
         versions distributed via installer) it brings up an image viewer
         box which allows the user to click through the rest of the images in 
@@ -2976,6 +2993,4 @@
         :param evt: Triggers on clicking ? in Magnetic Angles? box
         """
-        
-        from sas.guiframe.documentation_window import DocumentationWindow
         
         _TreeLocation = "_images/M_angles_pic.bmp"
@@ -3024,7 +3039,5 @@
         :param evt: Triggers on clicking ? in polydispersity box
         """
-        
-        from sas.guiframe.documentation_window import DocumentationWindow
-        
+                
         _TreeLocation = "user/perspectives/fitting/fitting_help.html"
         _TreeLocation += "#polydispersity-distributions"
@@ -3592,7 +3605,11 @@
         self.mbox_description.SetForegroundColour(wx.RED)
         id = wx.NewId()
-        self.model_help = wx.Button(self, id, 'Details', size=(80, 23))
+        self.model_func = wx.Button(self, id, 'Help', size=(80, 23))
+        self.model_func.Bind(wx.EVT_BUTTON, self.on_function_help_clicked, id=id)
+        self.model_func.SetToolTipString("Full Model Function Help")
+        id = wx.NewId()
+        self.model_help = wx.Button(self, id, 'Description', size=(80, 23))
         self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked, id=id)
-        self.model_help.SetToolTipString("Model Function Help")
+        self.model_help.SetToolTipString("Short Model Function Description")
         id = wx.NewId()
         self.model_view = wx.Button(self, id, "Show 2D", size=(80, 23))
@@ -3636,13 +3653,16 @@
       
         sizer_radiobutton = wx.GridSizer(2, 2, 5, 5)
+        
 
         #sizer_radiobutton.Add(self.shape_rbutton)
         #sizer_radiobutton.Add(self.shape_indep_rbutton)
         sizer_radiobutton.Add((5,5))
-        sizer_radiobutton.Add(self.model_view, 1, wx.RIGHT, 15)
+        sizer_radiobutton.Add(self.model_view, 1, wx.RIGHT, 5)
         #sizer_radiobutton.Add(self.plugin_rbutton)
         #sizer_radiobutton.Add(self.struct_rbutton)
-        sizer_radiobutton.Add((5,5))
-        sizer_radiobutton.Add(self.model_help, 1, wx.RIGHT, 15)
+#        sizer_radiobutton.Add((5,5))
+        sizer_radiobutton.Add(self.model_help, 1, wx.RIGHT|wx.LEFT, 5)
+#        sizer_radiobutton.Add((5,5))
+        sizer_radiobutton.Add(self.model_func, 1, wx.RIGHT, 5)
         sizer_cat.Add(sizer_cat_box, 1, wx.LEFT, 2.5)
         sizer_cat.Add(sizer_radiobutton)
Index: src/sas/perspectives/fitting/report_dialog.py
===================================================================
--- src/sas/perspectives/fitting/report_dialog.py	(revision 4ec242ef37ff5f92d91a892156e04d092559af32)
+++ src/sas/perspectives/fitting/report_dialog.py	(revision e8bb5b62d717c7b44481a4b621030699e4efdaf4)
@@ -14,61 +14,35 @@
 
 import wx
-import sys
 import os
 import wx.html as html
-import logging
 
-_STATICBOX_WIDTH = 480
-PANEL_WIDTH = 530
-PANEL_HEIGHT = 700
-FONT_VARIANT = 1
-ISMAC = False
-ISPDF = False
-if sys.platform == "win32":
-    _STATICBOX_WIDTH = 450
-    PANEL_WIDTH = 500
-    PANEL_HEIGHT = 700
-    FONT_VARIANT = 0
-    ISMAC = False
-    ISPDF = True
-elif sys.platform == "darwin":
-    ISMAC = True
-    ISPDF = True
+from sas.guiframe.report_dialog import BaseReportDialog
 
-        
-class ReportDialog(wx.Dialog):
+class ReportDialog(BaseReportDialog):
     """
     The report dialog box.
     """
     
-    def __init__(self, list, *args, **kwds):
+    def __init__(self, report_list, *args, **kwds):
         """
         Initialization. The parameters added to Dialog are:
         
-        :param list: report_list (list of html_str, text_str, image)
+        :param report_list: list of html_str, text_str, image
         from invariant_state
         """
-        kwds["style"] = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE
-        wx.Dialog.__init__(self, *args, **kwds)
-        kwds["image"] = 'Dynamic Image'
+        super(ReportDialog, self).__init__(report_list, *args, **kwds)
+
         # title
         self.SetTitle("Report: Fitting")
-        # size
-        self.SetSize((720, 650))
-        # font size
-        self.SetWindowVariant(variant=FONT_VARIANT)
-        # check if tit is MAC
-        self.is_pdf = ISPDF
-        # report string
-        self.report_list = list
+
         # number of images of plot
-        self.nimages = len(list[2])
+        self.nimages = len(self.report_list[2])
         
-        if list[2] != None:
+        if self.report_list[2] != None:
             # put image path in the report string
-            if len(list[2]) == 1:
+            if len(self.report_list[2]) == 1:
                 self.report_html = self.report_list[0] % \
                                     "memory:img_fit0.png"
-            elif len(list[2]) == 2:
+            elif len(self.report_list) == 2:
                 self.report_html = self.report_list[0] % \
                                     ("memory:img_fit0.png",
@@ -85,71 +59,11 @@
         self._setup_layout()
         
-    def _setup_layout(self):
-        """
-        Set up layout
-        """
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        
-        # buttons
-        id = wx.ID_OK
-        button_close = wx.Button(self, id, "Close")
-        button_close.SetToolTipString("Close this report window.")
-        #hbox.Add((5,10), 1 , wx.EXPAND|wx.ADJUST_MINSIZE,0)
-        hbox.Add(button_close)
-        button_close.SetFocus()
-
-        id = wx.NewId()
-        button_preview = wx.Button(self, id, "Preview")
-        button_preview.SetToolTipString("Print preview this report.")
-        button_preview.Bind(wx.EVT_BUTTON, self.onPreview,
-                            id=button_preview.GetId()) 
-        hbox.Add(button_preview)
-
-        id = wx.NewId()
-        button_print = wx.Button(self, id, "Print")
-        button_print.SetToolTipString("Print this report.")
-        button_print.Bind(wx.EVT_BUTTON, self.onPrint,
-                          id=button_print.GetId())
-        hbox.Add(button_print)
-        
-        id = wx.NewId()
-        button_save = wx.Button(self, id, "Save")
-        button_save.SetToolTipString("Save this report.")
-        button_save.Bind(wx.EVT_BUTTON, self.onSave, id=button_save.GetId())
-        hbox.Add(button_save)
-        
-        # panel for report page
-        #panel = wx.Panel(self, -1)
-        vbox = wx.BoxSizer(wx.VERTICAL)
-        # html window
-        self.hwindow = html.HtmlWindow(self, style=wx.BORDER)
-        # set the html page with the report string
-        self.hwindow.SetPage(self.report_html)
-        
-        # add panels to boxsizers
-        vbox.Add(hbox)
-        vbox.Add(self.hwindow, 1, wx.EXPAND|wx.ALL,0)
-
-        self.SetSizer(vbox)
-        self.Centre()
-        self.Show(True)
-
     def onSave(self, event=None):
         """
         Save
         """
-        # pdf supporting only on MAC, not on exe
-        if self.is_pdf:
-            wild_card = ' PDF files (*.pdf)|*.pdf|'
-            ind_cor = 0
-        else:
-            wild_card = ''
-            ind_cor = 1
-        wild_card += 'HTML files (*.html)|*.html|'
-        wild_card += 'Text files (*.txt)|*.txt'
-
         #todo: complete saving fig file and as a txt file
         dlg = wx.FileDialog(self, "Choose a file",
-                            wildcard=wild_card,
+                            wildcard=self.wild_card,
                             style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
         dlg.SetFilterIndex(0)  # Set .html files to be default
@@ -166,5 +80,5 @@
         pic_fname = []
         #PDF
-        if ext_num == (0 + 2 * ind_cor):
+        if ext_num == (0 + 2 * self.index_offset):
             # TODO: Sort this case out
             ext = '.pdf'
@@ -216,5 +130,5 @@
             return
         #HTML + png(graph)
-        elif ext_num == (1 - ind_cor):
+        elif ext_num == (1 - self.index_offset):
             ext = '.html'
             for num in range(self.nimages):
@@ -222,5 +136,5 @@
             report_frame = self.report_list[0]
         #TEXT + pdf(graph)
-        elif ext_num == (2 - ind_cor):
+        elif ext_num == (2 - self.index_offset):
             ext = '.txt'
             # changing the image extension actually changes the image
@@ -241,5 +155,5 @@
             pic_fname.append(pic_name)
         #put the image path in html string
-        if ext_num == (1 - ind_cor):
+        if ext_num == (1 - self.index_offset):
             if self.nimages == 1:
                 report = report_frame % os.path.basename(pic_fname[0])
@@ -259,59 +173,2 @@
             self.report_list[2][num].savefig(pic_fname[num])
         
-    def onPreview(self, event=None):
-        """
-        Preview
-        
-        : event: Preview button event
-        """
-        previewh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
-        previewh.PreviewText(self.report_html)
-        if event is not None:
-            event.Skip()
-        self.Update()
-    
-    def onPrint(self, event=None):
-        """
-        Print
-        
-        : event: Print button event
-        """
-        printh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
-        printh.PrintText(self.report_html)
-        if event is not None:
-            event.Skip()
-        self.Update()
-        
-    def OnClose(self, event=None):
-        """
-        Close the Dialog
-        
-        : event: Close button event
-        """
-        self.Close()
-        # Reset memory
-        #wx.MemoryFSHandler()
-        if event is not None:
-            event.Skip()
-    
-    def HTML2PDF(self, data, filename):
-        """
-        Create a PDF file from html source string.
-        Returns True is the file creation was successful. 
-        
-        : data: html string
-        : filename: name of file to be saved
-        """
-        try:
-            from xhtml2pdf import pisa
-            # open output file for writing (truncated binary)
-            resultFile = open(filename, "w+b")
-            # convert HTML to PDF
-            pisaStatus = pisa.CreatePDF(data, dest=resultFile)
-            # close output file
-            resultFile.close()
-            self.Update()
-            return pisaStatus.err
-        except:
-            logging.error("Error creating pdf: %s" % sys.exc_value)
-        return False
Index: src/sas/perspectives/invariant/report_dialog.py
===================================================================
--- src/sas/perspectives/invariant/report_dialog.py	(revision 4ec242ef37ff5f92d91a892156e04d092559af32)
+++ src/sas/perspectives/invariant/report_dialog.py	(revision e8bb5b62d717c7b44481a4b621030699e4efdaf4)
@@ -15,116 +15,30 @@
 """
 import wx
-import sys
 import os
 import wx.html as html
-import logging
-ISPDF = False
-if sys.platform == "win32":
-    _STATICBOX_WIDTH = 450
-    PANEL_WIDTH = 500 
-    PANEL_HEIGHT = 700
-    FONT_VARIANT = 0
-    ISMAC = False
-    ISPDF = True
-elif sys.platform == "darwin":
-    _STATICBOX_WIDTH = 480
-    PANEL_WIDTH = 530
-    PANEL_HEIGHT = 700
-    FONT_VARIANT = 1
-    ISMAC = True
-    ISPDF = True
-  
-class ReportDialog(wx.Dialog):
+ 
+from sas.guiframe.report_dialog import BaseReportDialog
+
+class ReportDialog(BaseReportDialog):
     """
     The report dialog box. 
     """
     
-    def __init__(self,  list, *args, **kwds):
+    def __init__(self,  report_list, *args, **kwds):
         """
         Initialization. The parameters added to Dialog are:
         
-        :param list: report_list (list of html_str, text_str, image)
+        :param report_list: list of html_str, text_str, image
         from invariant_state
         """
-        kwds["style"] = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE
-        wx.Dialog.__init__(self, *args, **kwds)
-        kwds["image"] = 'Dynamic Image'
+        super(ReportDialog, self).__init__(report_list, *args, **kwds)
+
         # title
         self.SetTitle("Report: Invariant computaion")
-        # size
-        self.SetSize((720, 650))
-        # font size 
-        self.SetWindowVariant(variant=FONT_VARIANT)
 
-        # check if tit is MAC
-        self.is_pdf = ISPDF
-        
-        # report string
-        self.report_list = list
         # put image path in the report string
         self.report_html = self.report_list[0] % "memory:img_inv.png"
         # layout
         self._setup_layout()
-        # wild card
-        # pdf supporting only on MAC
-        if self.is_pdf:
-        	self.wild_card = ' PDF files (*.pdf)|*.pdf|'
-        else:
-        	self.wild_card = ''
-        self.wild_card += 'HTML files (*.html)|*.html|'
-        self.wild_card += 'Text files (*.txt)|*.txt'
-  
-        
-        
-    def _setup_layout(self):
-        """
-        Set up layout
-        """
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        
-        # buttons
-        id = wx.ID_OK
-        button_close = wx.Button(self, id, "Close")
-        button_close.SetToolTipString("Close this report window.") 
-        #hbox.Add((5,10), 1 , wx.EXPAND|wx.ADJUST_MINSIZE,0)
-        hbox.Add(button_close)
-        button_close.SetFocus()
-
-        id = wx.NewId()
-        button_preview = wx.Button(self, id, "Preview")
-        button_preview.SetToolTipString("Print preview this report.")
-        button_preview.Bind(wx.EVT_BUTTON, self.onPreview,
-                            id=button_preview.GetId()) 
-        hbox.Add(button_preview)
-
-        id = wx.NewId()
-        button_print = wx.Button(self, id, "Print")
-        button_print.SetToolTipString("Print this report.")
-        button_print.Bind(wx.EVT_BUTTON, self.onPrint,
-                          id=button_print.GetId()) 
-        hbox.Add(button_print)
-        
-        id = wx.NewId()
-        button_save = wx.Button(self, id, "Save" )
-        button_save.SetToolTipString("Save this report.")
-        button_save.Bind(wx.EVT_BUTTON, self.onSave, id = button_save.GetId()) 
-        hbox.Add(button_save)     
-        
-        # panel for report page
-        #panel = wx.Panel(self, -1)
-        vbox = wx.BoxSizer(wx.VERTICAL)
-        # html window
-        self.hwindow = html.HtmlWindow(self,style=wx.BORDER)
-        # set the html page with the report string
-        self.hwindow.SetPage(self.report_html)
-        
-        # add panels to boxsizers
-        vbox.Add(hbox)
-        vbox.Add(self.hwindow, 1, wx.EXPAND|wx.ALL,0)
-
-        self.SetSizer(vbox)
-        self.Centre()
-        self.Show(True)
-		
 
     def onSave(self, event=None):
@@ -144,12 +58,7 @@
         fName = dlg.GetPath()
         ext_num = dlg.GetFilterIndex()  
-        # index correction 
-        if not self.is_pdf:
-        	ind_cor = 1 
-        else:
-        	ind_cor = 0 
         #set file extensions  
-        if ext_num == (0 + 2 * ind_cor):
-			# TODO: Sort this case out
+        if ext_num == (0 + 2 * self.index_offset):
+            # TODO: Sort this case out
             ext = '.pdf'
             img_ext = '_img.png'
@@ -186,9 +95,9 @@
             os.remove(pic_fname)
             return
-        elif ext_num == (1 - ind_cor):
+        elif ext_num == (1 - self.index_offset):
             ext = '.html'
             img_ext = '_img4html.png'
             report_frame = self.report_list[0]
-        elif ext_num == (2 - ind_cor):
+        elif ext_num == (2 - self.index_offset):
             ext = '.txt'   
             # changing the image extension actually changes the image
@@ -205,5 +114,5 @@
         pic_fname = os.path.splitext(fName)[0] + img_ext
         #put the image path in html string
-        if ext_num == (1 - ind_cor):
+        if ext_num == (1 - self.index_offset):
             report = report_frame % os.path.basename(pic_fname)
 
@@ -214,54 +123,2 @@
         self.report_list[2].savefig(pic_fname)
         
-            
-    def onPreview(self, event=None):
-        """
-        Preview
-        
-        : event: Preview button event
-        """
-        previewh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
-        previewh.PreviewText(self.report_html)
-        if event is not None:
-            event.Skip()
-    
-    def onPrint(self, event=None):
-        """
-        Print
-        
-        : event: Print button event
-        """
-        printh = html.HtmlEasyPrinting(name="Printing", parentWindow=self)
-        printh.PrintText(self.report_html)
-        if event is not None:
-            event.Skip()
-
-    def OnClose(self,event=None):
-        """
-        Close the Dialog
-        
-        : event: Close button event
-        """
-        self.Close()
-    
-    def HTML2PDF(self, data, filename):
-        """
-        Create a PDF file from html source string.
-        Returns True is the file creation was successful. 
-        
-        : data: html string
-        : filename: name of file to be saved
-        """
-        try:
-            from xhtml2pdf import pisa
-            # open output file for writing (truncated binary)
-            resultFile = open(filename, "w+b")
-            # convert HTML to PDF
-            pisaStatus = pisa.CreatePDF(data, dest=resultFile)
-            # close output file
-            resultFile.close()
-            self.Update()
-            return pisaStatus.err
-        except:
-            logging.error("Error creating pdf: %s" % sys.exc_value)
-        return False
