Index: guitools/LineModel.py
===================================================================
--- guitools/LineModel.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
+++ guitools/LineModel.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+""" 
+    Provide Line function (y= A + Bx) as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+import math
+
+
+class LineModel(BaseComponent):
+    """ 
+        Class that evaluates a linear model.
+        
+        f(x) = A + Bx
+         
+        List of default parameters:
+          A = 0.0
+          B = 0.0 
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "Line"
+
+        ## Define parameters
+        self.params = {}
+        self.params['A'] = 10.0
+        self.params['B'] = 10.0
+
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['A'] = ['', None, None]
+        self.details['B'] = ['', None, None]
+               
+    def _line(self, x):
+        """
+            Evaluate the function
+            @param x: x-value
+            @return: function value
+        """
+        return  self.params['A'] + x *self.params['B']
+    
+    def run(self, x = 0.0):
+        """ Evaluate the model
+            @param x: simple value
+            @return: (Line value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._line(x[0]*math.cos(x[1]))*self._line(x[0]*math.sin(x[1]))
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._line(x)
+   
+    def runXY(self, x = 0.0):
+        """ Evaluate the model
+            @param x: simple value
+            @return: Line value
+        """
+        if x.__class__.__name__ == 'list':
+            return self._line(x[0])*self._line(x[1])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._line(x)
+   
+
+if __name__ == "__main__": 
+    l = Line()
+    print "hello"
+       
+# End of file
Index: guitools/PropertyDialog.py
===================================================================
--- guitools/PropertyDialog.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
+++ guitools/PropertyDialog.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+
+# myDialog.py
+
+import wx
+
+class Properties(wx.Dialog):
+    def __init__(self, parent, id, title):
+        wx.Dialog.__init__(self, parent, id, title, size=(300, 200))
+        """
+            for the properties window
+        """
+        self.parent = parent
+        panel = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)   
+        vbox  = wx.BoxSizer(wx.VERTICAL)
+        sizer = wx.GridBagSizer(5,0)
+        vbox.Add(panel, 1, wx.EXPAND | wx.ALL)
+     
+        ix = 1
+        iy = 1
+        sizer.Add(wx.StaticText(panel, -1, 'X'),(iy, ix))
+        ix += 2
+        sizer.Add(wx.StaticText(panel, -1, 'Y'),(iy, ix))
+        ix += 2
+        sizer.Add(wx.StaticText(panel, -1, 'View'),(iy, ix))
+        iy += 1
+        ix = 1
+        self.xvalue = wx.ComboBox(panel, -1, size=(60, -1))
+        sizer.Add(self.xvalue,(iy,ix))
+        ix +=2
+        self.yvalue = wx.ComboBox(panel, -1, size=(60, -1))
+        sizer.Add( self.yvalue,(iy, ix))
+        ix +=2
+        view =wx.ComboBox(panel, -1, size=(60, -1))
+        sizer.Add(view,(iy,ix))
+        ix =3
+        iy +=3
+        btCancel=wx.Button(panel, wx.ID_CANCEL,'Cancel' )
+        sizer.Add(btCancel,(iy,ix))
+        ix +=2
+        btOk = wx.Button(panel, wx.ID_OK, "Ok")
+        sizer.Add(btOk,(iy, ix))
+        
+        # scale value for x
+        self.xvalue.SetValue("x")
+        self.xvalue.Insert("x",0)
+        self.xvalue.Insert("Log(x)",1)
+        self.xvalue.Insert("x^(2)",2)
+        
+        # scale value for y
+        self.yvalue.SetValue("Log(y)")
+        self.yvalue.Insert("y",0)
+        self.yvalue.Insert("Log(y)",1)
+        self.yvalue.Insert("y^(2)",2)
+        
+        panel.SetSizer(sizer)
+        self.SetSizer(vbox)
+        self.Centre()
+           
+        
+    def setValues(self,x,y):
+        return  self.xvalue.SetValue(x),  self.yvalue.SetValue(y)
+        
+        
+    def getValues(self):
+        return self.xvalue.GetValue(), self.yvalue.GetValue()
+
+if __name__ == "__main__": 
+    app = wx.App()
+    dialog = Properties(None, -1, 'Properties')
+    dialog.ShowModal()
+    app.MainLoop()
+
+
Index: guitools/fitDialog.py
===================================================================
--- guitools/fitDialog.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
+++ guitools/fitDialog.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+
+# fitDialog.py
+
+import wx
+from sans.guitools.PlotPanel import PlotPanel
+
+class LinearFit(wx.Dialog):
+    def __init__(self, parent, id, title):
+        wx.Dialog.__init__(self, parent, id, title, size=(500, 300))
+        """
+            for the fit window
+        """
+        self.parent = parent
+        panel = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)   
+        vbox  = wx.BoxSizer(wx.VERTICAL)
+        sizer = wx.GridBagSizer(5,0)
+        vbox.Add(panel, 1, wx.EXPAND | wx.ALL)
+ 
+        self.tcA = wx.TextCtrl(panel, -1,style=wx.SIMPLE_BORDER)
+        self.tcErrA = wx.TextCtrl(panel, -1,style=wx.SIMPLE_BORDER)
+        self.tcB = wx.TextCtrl(panel, -1,style=wx.SIMPLE_BORDER)
+        self.tcErrB = wx.TextCtrl(panel, -1,style=wx.SIMPLE_BORDER)
+        self.tcChi = wx.TextCtrl(panel, -1,style=wx.SIMPLE_BORDER)
+        self.tcXmin = wx.TextCtrl(panel,-1,style=wx.SIMPLE_BORDER)
+        self.tcXmax = wx.TextCtrl(panel,-1,style=wx.SIMPLE_BORDER)
+        self.btFit =wx.Button(panel,-1,'Fit' )
+        btClose =wx.Button(panel, wx.ID_CANCEL,'Close' )
+        
+        ix = 1
+        iy = 1
+        sizer.Add(wx.StaticText(panel, -1, 'y = Ax +B'),(iy, ix))
+        ix = 1
+        iy += 2
+        sizer.Add(wx.StaticText(panel, -1, 'Param A'),(iy, ix))
+        ix += 1
+        sizer.Add(self.tcA, (iy, ix))
+        ix += 1
+        sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix))
+        ix += 1
+        sizer.Add(self.tcErrA, (iy, ix))
+        #self.tcErrA.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        iy += 1
+        ix = 1
+        sizer.Add(wx.StaticText(panel, -1, 'Param B'),(iy, ix))
+        ix += 1
+        sizer.Add(self.tcB, (iy, ix))
+        #self.tcB.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        ix += 1
+        # sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix))
+        ix += 1
+        sizer.Add(self.tcErrB, (iy, ix))
+        self.tcErrB.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        iy += 1
+        ix = 1
+        sizer.Add(wx.StaticText(panel, -1, 'Chi ^{2}'),(iy, ix))
+        ix += 1
+        sizer.Add(self.tcChi, (iy, ix))
+        #self.tcChi.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        iy += 1
+        ix = 1
+        sizer.Add(wx.StaticText(panel, -1, 'Xmin'),(iy, ix))
+        ix += 2
+        sizer.Add(wx.StaticText(panel, -1, 'Xmax'),(iy, ix))
+        iy += 1
+        ix = 1
+        sizer.Add(self.tcXmin, (iy, ix))
+        #self.tcXmin.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        ix += 2
+        sizer.Add(self.tcXmax, (iy, ix))
+        #self.tcXmax.Bind(wx.EVT_KILL_FOCUS, self._onTextEnter)
+        iy += 1
+        ix = 1
+        sizer.Add(self.btFit, (iy, ix))
+        self.tcXmax.Bind(wx.EVT_KILL_FOCUS, self._onFit)
+        ix += 2
+        sizer.Add(btClose, (iy, ix))
+       
+        panel.SetSizer(sizer)
+        self.SetSizer(vbox)
+        self.Centre()
+    def _onFit(self ,event):
+         param_evt1 = PlotPanel.FunctionFitEvent(\
+            Xmin=self._checkVal(self.tcXmin.GetValue()),\
+            Xmax=self._checkVal(self.tcXmax.GetValue())                                     )
+         wx.PostEvent(self, param_evt1)
+    
+    def _onsetValues(self,cstA,cstB,errA,errB,Chi):
+        
+         self.tcA.SetValue(cstA)
+         self.tcB.SetValue(cstB)
+         self.tcErrA.SetValue(cstB)
+         self.tcErrB.SetValue(cstA)
+         self.tcChi.SetValue(Chi)
+    def _getXrange(self):
+        if self.tcXmin.GetValue() and self.tcXmax.GetValue():
+            return float(),float(self.tcXmax.GetValue())
+        else:
+            return None, None
+    def _checkVal(self,value):
+        """
+                Ensure that fields parameter contains a value 
+                before sending to fit in Plotter1D
+        """
+        try:
+            param = float(value)
+        except:
+            param = None
+        return param
+if __name__ == "__main__": 
+    app = wx.App()
+    dialog=LinearFit(None, -1, 'Fitting')
+    dialog.ShowModal()
+    app.MainLoop()
+
+
Index: guitools/plottables.py
===================================================================
--- guitools/plottables.py	(revision 057210c6ea19572fef82f93aab447415c671aaa2)
+++ guitools/plottables.py	(revision 6cfe7031360bc5d65e5f82097116559ef04e5349)
@@ -199,4 +199,6 @@
         
         return labels
+    def returnPlottable(self):
+        return self.plottables
 
     def render(self,plot):
@@ -332,5 +334,5 @@
 
     def __init__(self):
-        pass
+        self.view = View()
     
     def render(self,plot):
@@ -342,10 +344,25 @@
         that it makes sense.
         """
-        plot.xaxis(self._xaxis, self._xunit)
-        plot.yaxis(self._yaxis, self._yunit)
+        self.view.render()
+        #plot.xaxis(self._xaxis, self._xunit)
+        #plot.yaxis(self._yaxis, self._yunit)
         
     def colors(self):
         """Return the number of colors need to render the object"""
         return 1
+    
+    def transform_x(self, func, errfunc):
+        """
+            @param func: reference to x transformation function
+            
+        """
+        self.view.transform_x(func, errfunc, self.x, self.dx)
+    
+    def transform_y(self, func, errfunc):
+        """
+            @param func: reference to y transformation function
+            
+        """
+        self.view.transform_y(func, errfunc, self.y, self.dy)
     
     class View:
@@ -378,11 +395,11 @@
                 raise ValueError, "Plottable.View: Given x and dx are not of the same length"
             
-            self.x  = deepcopy(x)
-            self.dx = deepcopy(dx)
+            self.x  = copy.deepcopy(x)
+            self.dx = copy.deepcopy(dx)
             
             for i in range(len(x)):
                  self.x[i] = func(x[i])
                  self.dx[i] = errfunc(dx[i])
-                      
+                          
         def transform_y(self, func, errfunc, y, dy):
             """
@@ -405,6 +422,16 @@
                  self.y[i] = func(y[i])
                  self.dy[i] = errfunc(dy[i])
-                      
-        
+        def render(self,plot):
+            """The base class makes sure the correct units are being used for
+            subsequent plottable.  
+            
+            For now it is assumed that the graphs are commensurate, and if you 
+            put a Qx object on a Temperature graph then you had better hope 
+            that it makes sense.
+            """
+            plot.xaxis(self._xaxis, self._xunit)
+            plot.yaxis(self._yaxis, self._yunit)
+                          
+            
 
 class Data1D(Plottable):
