#
# $Id: gui.py,v 1.1.1.1 2003/03/22 05:15:49 dbelan2 Exp $
#
# Graphical User Interface
#
#
#
# $Log: gui.py,v $
# Revision 1.1.1.1  2003/03/22 05:15:49  dbelan2
# Initial import of all public_html on www.cs.mcgill.ca.
#
# Revision 1.19  2001/10/02 01:49:16  dbelan2
# Fixed bug when clearing plot.
#
# Revision 1.18  2001/10/02 01:10:44  dbelan2
# Removed print from menu.
#
# Revision 1.17  2001/10/01 21:53:44  dbelan2
# Save default bug fixed.
#
# Revision 1.16  2001/10/01 21:36:32  dbelan2
# Changed window title.
#
# Revision 1.15  2001/10/01 16:11:26  dbelan2
# Move some Plotter functionnality to gui module.
#
# Revision 1.14  2001/09/30 22:11:39  dbelan2
# Bug fix: - constant framed clean up before packing new
#            widget.
#
# Revision 1.13  2001/09/30 21:27:41  dbelan2
# GUI Layout done of all frames.
#
# Revision 1.12  2001/09/29 23:57:31  dbelan2
# - Constants can be set by user.
#
# Revision 1.11  2001/09/29 23:45:24  dbelan2
# - Added code to display constants and allow user
#   to set their values.
#
# Revision 1.10  2001/09/29 22:43:29  dbelan2
# - Now can select what output goes to file!
# - Added menu option to save results to file
#
# Revision 1.9  2001/09/29 21:47:27  dbelan2
# - User can select what to plot.
# - Simulation can be run several times and plotted on
#   the same graph.
#
# Revision 1.8  2001/09/28 18:13:24  dbelan2
# Design of output device frame done, but no event
# implemented yet.
#
# Revision 1.7  2001/09/28 14:15:57  dbelan2
# Changed.  In plot data file, 1st line is always ignored
# (header line) and any empty lines.
#
# Revision 1.6  2001/09/28 04:04:33  dbelan2
# Manual merge of r1.4 and r1.5 done.
#
# Revision 1.5  2001/09/28 03:29:04  hchen19
# merging
#
# Revision 1.4  2001/09/28 03:25:04  dbelan2
# ci again for merge.
#
# Revision 1.3  2001/09/28 03:17:21  dbelan2
# ci again for merging.
#
# Revision 1.2  2001/09/28 02:52:39  dbelan2
# Plot from file working.
#
# Revision 1.1  2001/09/26 20:30:55  dbelan2
# Added GUI files.
#
#
#

from Tkinter import *
import tkFileDialog

from main import *



import sys
from Plotter import *

from MySimpleDialog import *


class GUI:

    def __init__(self, master=None):
        self.solver = Solver()

        self.root=Tk()
        self.root.title('Causal Block Simulator')
        
        self.buildMenu()
        
        self.buildInfo()
        self.updateInfo()

        self.plotready = 0
        self.plotter = None


    def run(self):
        self.root.mainloop()


    def buildMenu(self):
        menu = Menu(self.root)
        self.root.config(menu=menu)

        self.filemenu = Menu(menu, tearoff = 0)
        menu.add_cascade(label="File", menu=self.filemenu)

        self.filemenu.add_command(label="Open model...", command=self.open)
        self.filemenu.add_command(label="Load state...", command=self.loadState)
        self.filemenu.add_command(label="Save state...", command=self.saveState)
        self.filemenu.add_command(label="Save global defaults", command=self.saveDefaults)
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.quit)


        self.filemenu = Menu(menu, tearoff = 0)
        menu.add_cascade(label="Simulator", menu=self.filemenu)
        self.filemenu.add_command(label="Go", command = self.go)
        self.filemenu.add_command(label="Save results to file...", command = self.saveResults)


        # Plotter menu
        self.filemenu = Menu(menu, tearoff = 0)
        menu.add_cascade(label="Plotter", menu=self.filemenu)
        self.filemenu.add_command(label="Plot from file...", command = self.plotFile)
        self.filemenu.add_command(label="Clear plot", command = self.clearPlot)


    def open(self):
        name = tkFileDialog.askopenfilename(filetypes=[("All Files", "*")])
        if name == '':
            return
	
	self.root.title(name)
        execfile(name)
        self.solver = Solver(self.model)
        self.setStatus("Model '" + name + "' loaded")

        # build outputs lists to display possible output variables
        self.outputsL.delete(0, END)
        outputnames = ['time']
        outputnames.extend(map(str, self.solver.intblocks))
        outputnames.extend(map(str, self.solver.nonintblockssorted))
        for name in outputnames:
            self.outputsL.insert(END, name)


        # build constant frame
        self.layoutConstants()

        # update solver params
        self.updateInfo()

        

    def loadState(self):
        name = tkFileDialog.askopenfilename(filetypes=[("All Files", "*")])
        if name == '':
            return
        self.solver.loadState(name)
        self.updateInfo()

    def saveState(self):
        name = tkFileDialog.asksaveasfilename(filetypes=[("All Files", "*")])
        if name == '':
            return
        self.solver.saveState(name)

    def saveDefaults(self):
        # set solver parameters        
        self.solver.step_size=float(self.step_sizeE.get())
        self.solver.comm_int=float(self.comm_intE.get())
        self.solver.start_t=float(self.start_tE.get())
        self.solver.end_t=float(self.end_tE.get())    
       
        self.solver.writeDefaults()
       


    def go(self):
        # set solver parameters        
        self.solver.step_size=float(self.step_sizeE.get())
        self.solver.comm_int=float(self.comm_intE.get())
        self.solver.start_t=float(self.start_tE.get())
        self.solver.end_t=float(self.end_tE.get())    

        # set constants
        for widget in self.constantFrame.slaves():
            if isinstance(widget, Entry):
                # code to set constant
                name = widget.cget('text')
                value = 0.0
                try:
                    value = float(widget.get())
                except ValueError:
                    d = Dialog(self.root, title='Constant not a float')
                    return  # abort simulation
                print "C:", name, value
                self.solver.changeBlockValue(name, value)

        #sys.exit(1)

        self.setStatus('Simulation Running...')
        self.solver.go()
        self.setStatus('Simulation Done')
        self.sttoplot = 1
        self.plot()


    def quit(self):
        # ask to save if modified
        sys.exit()


    def plot(self):
        points = self.solver.getPoints()
        if points != None:
            if len(points) > 0:
                            
                if not self.plotready:
                    self.plotter=Plotter()
                    self.plotready=1
                    
                self.plotter.plot(points)
                


    def plotFile(self):
        name = tkFileDialog.askopenfilename(filetypes=[("All Files", "*")])
        if name == '':
            return
        
        points = []
        f = open(name, "r")

        # ignore first 2 lines
        # considered as header
        #        f.readline()
        f.readline()

        line = f.readline()
        while line != "":
            if line != "\n":
                point = line.split('\t', 2)
                print "*", point, "*"
                
                points.append((float(point[0]),float(point[1])))

            line = f.readline()
        f.close()
        print points


        if not self.plotready:
            self.plotter=Plotter()
            self.plotready=1
        
        self.plotter.plot(points)
                

    def clearPlot(self):
        if self.plotter != None:
            self.plotter.clear()


    def buildInfo(self):
        

        topFrame = Frame(self.root)
        topFrame.pack()

        middleFrame = Frame(self.root)
        middleFrame.pack()

        statusFrame = Frame(self.root)
        Label(statusFrame, text='Status:').pack(side=LEFT)
        self.__statusL = Label(statusFrame, text='No Model Loaded')
        self.__statusL.pack()
        statusFrame.pack()


        # Frame containing labels and textboxes for
        # solver parameters
        paramFrame = Frame(topFrame)
        Label(paramFrame, text='Solver Parameters').pack() 

        frame = Frame(paramFrame)
        Label(frame, text='Step size').pack()
        Label(frame, text='Communication Interval').pack()
        Label(frame, text='Start Time').pack()
        Label(frame, text='End Time').pack()
        frame.pack(side=LEFT)

        frame = Frame(paramFrame)
        self.step_sizeE = Entry(frame)
        self.step_sizeE.pack()
        self.comm_intE = Entry(frame)
        self.comm_intE.pack()
        self.start_tE = Entry(frame)
        self.start_tE.pack()
        self.end_tE = Entry(frame)
        self.end_tE.pack()
        frame.pack(side=LEFT)

        paramFrame.pack(side=LEFT)

        # Lets the user set constants
        Label(topFrame, text='Constants').pack()
        self.constantFrame = Frame(topFrame)
        self.constantFrame.pack()


        # list to select X and Y for plotter
        # and to file.
        varFrame = Frame(middleFrame)
        Label(varFrame, text='Variables').pack()
        self.outputsL = Listbox(varFrame)
        self.outputsL.pack()
        varFrame.pack(side=LEFT)


        buttonFrame = Frame(middleFrame)
        frame = Frame(buttonFrame)
        self.__setXB = Button(frame, text='SetX', command=self.setX)
        self.__setYB = Button(frame, text='SetY', command=self.setY)
        self.__setXB.pack(side=LEFT)
        self.__setYB.pack()
        frame.pack()

        frame = Frame(buttonFrame)
        self.__setToFileB = Button(frame, text='SetToFile', command=self.setToFile)
        self.__setToFileB.pack(side=LEFT)
        self.__resetToFileB = Button(frame, text='ResetToFile', command=self.resetToFile)
        self.__resetToFileB.pack()
        frame.pack()
        buttonFrame.pack()
        
        #xyfileFrame = Frame(middleFrame)
        frame = Frame(middleFrame)
        Label(frame, text='x:').pack(side=LEFT)
        self.xOutputL = Label(frame, text='None')
        self.xOutputL.pack(side=LEFT)
        Label(frame, text='y:').pack(side=LEFT)
        self.yOutputL = Label(frame, text='None')
        self.yOutputL.pack()
        frame.pack()

        frame = Frame(middleFrame)
        Label(frame, text='to file:').pack()
        self.fileOutputL = Label(frame, text='[]')
        self.fileOutputL.pack()
        frame.pack()


        #outputFrame.pack()





        #print self.root.slaves()
        


    def layoutConstants(self):
        # remove old fields
        for slave in self.constantFrame.pack_slaves():
            slave.pack_forget()

        # add new ones
        constants = self.solver.constantblocks
        for c in constants:
            Label(self.constantFrame, text=c.name).pack()
            entry = Entry(self.constantFrame, text=c.name)
            entry.delete(0, END)  # otherwise value append.
            entry.insert(0, c.value)
            entry.pack()




    def setX(self):
        self.xOutputL.configure(text = self.outputsL.get(ACTIVE))
        self.updateOutfmtplot()

    def setY(self):
        self.yOutputL.configure(text = self.outputsL.get(ACTIVE))
        self.updateOutfmtplot()

    def setToFile(self):
        liststr = self.fileOutputL.cget('text')
        print "liststr", liststr
        list = eval(liststr)
        print "list", list
        list.append(self.outputsL.get(ACTIVE))
        print "list", list
        liststr = str(list)
        self.fileOutputL.configure(text = liststr)

        list = eval(liststr)
        print list
        self.solver.setOutputFormat(list)

    def resetToFile(self):
        list = []
        liststr = str(list)
        self.fileOutputL.configure(text = liststr)
        self.solver.setOutputFormat(list)

    def saveResults(self):
        # add check to see if available

        name = tkFileDialog.asksaveasfilename(filetypes=[("All Files", "*")])
        if name == '':
            return
        self.solver.resultfilename = name
        self.solver.saveResultToFile()


    def updateOutfmtplot(self):
        self.solver.setXYOutput(self.xOutputL.cget('text'), self.yOutputL.cget('text'))


    def setStatus(self, text):
        self.__statusL.configure(text=text)


    # Display numbers in text boxes so user can change it.
    #
    def updateInfo(self):
        self.replaceText(self.step_sizeE, `self.solver.step_size`)
        self.replaceText(self.comm_intE, `self.solver.comm_int`)
        self.replaceText(self.start_tE, `self.solver.start_t`)
        self.replaceText(self.end_tE, `self.solver.end_t`)


    def replaceText(self, entry, newtext):
        print newtext
        entry.delete(0, END)
        entry.insert(0, newtext)

        


GUI().run()










