Example #1
0
class bootWindow:
    def __init__(self, parent):
        logging.info("Host IP: " +get_ip())
        self.screen = Canvas(parent, bg=black, height=480, width=320)
        self.screen.place(x=0,y=0)
        Testline = self.screen.create_line(160, 0, 160, 480, fill=red)
        Testline2 = self.screen.create_line(0, 240, 320, 240, fill=red)
        self.img = ImageTk.PhotoImage(Image.open("images/logo.PNG"))
        self.imglabel = Label(self.screen, image=self.img).place(x=160, y=150, anchor="center")

        self.text = self.screen.create_text(160,270 , text="Loading, Please wait...", fill=white, font=(textFont, 13))

        self.p = ttk.Progressbar(self.screen, orient="horizontal", length=200, mode='determinate')
        self.p.place(x=160, y=300, anchor="center")
        # LOAD ALL THE STUFF!!
        parent.update()
        self.p.step(10)
        parent.update()
        #time.sleep(1)
        self.p.step(10)
        parent.update()
        #time.sleep(1)
        self.p.step(30)
        parent.update()
        time.sleep(1)
        self.screen.destroy()
        self.p.destroy()
    def hide(self):
        pass
    def show(self):
        pass
    def update(self):
        pass
    def __del__(self):
        pass
class ImageView(BaseView):
    def __init__(self, manager):
        self.viewname = 'imageview'
        BaseView.__init__(self, manager)

    def pack_view(self, *args, **kwargs):
        layout = kwargs.get('layout', 2)
        image_object = kwargs['image_object']
        image_no = kwargs.get('image_no', None)

        left_frame = self.display_left(flexible=True)

        _display_idx = self.manager.get_display_index()
        _display_size = (self.config.DISPLAY_SIZE[_display_idx][0], self.config.DISPLAY_SIZE[_display_idx][1])
        self.manager.log('display size', _display_size)
        self._imgtk = ImageTk.PhotoImage(image_object.resize(_display_size))

        # # self.frame = Frame(self.master)
        # self.frame = Frame(self.master, bg='white', width=_display_size[0], height=_display_size[1])
        # self.frame.grid_propagate(0)
        left_frame.config(bg='white', width=_display_size[0], height=_display_size[1])

        self.canvas = Canvas(left_frame, width=_display_size[0], height=_display_size[1], bg='red')
        # self.canvas.grid_propagate(0)
        self.canvas.place(relx=0.5, rely=0.5, anchor=CENTER)
        self.canvas.create_image(2, 2, image=self._imgtk, anchor='nw')
        if image_no is not None:
            self.canvas.create_text(self._imgtk.width() * 0.9, self._imgtk.height() * 0.9, text="Image No: " + str(image_no),
                                fill="white")
        if layout == 2:
            bottom_frame = self.display_bottom(True)

        self.add_next_action_btn(lambda: self.done())
        self.display()
Example #3
0
class bootWindow:
    def __init__(self, parent):
        logging.info("Host IP: " + get_ip())
        self.screen = Canvas(parent, bg=black, height=480, width=320)
        self.screen.place(x=0, y=0)
        Testline = self.screen.create_line(160, 0, 160, 480, fill=red)
        Testline2 = self.screen.create_line(0, 240, 320, 240, fill=red)
        self.img = ImageTk.PhotoImage(Image.open("images/logo.PNG"))
        self.imglabel = Label(self.screen,
                              image=self.img).place(x=160,
                                                    y=150,
                                                    anchor="center")

        self.text = self.screen.create_text(160,
                                            270,
                                            text="Loading, Please wait...",
                                            fill=white,
                                            font=(textFont, 13))

        self.p = ttk.Progressbar(self.screen,
                                 orient="horizontal",
                                 length=200,
                                 mode='determinate')
        self.p.place(x=160, y=300, anchor="center")
        # LOAD ALL THE STUFF!!
        parent.update()
        self.p.step(10)
        parent.update()
        #time.sleep(1)
        self.p.step(10)
        parent.update()
        #time.sleep(1)
        self.p.step(30)
        parent.update()
        time.sleep(1)
        self.screen.destroy()
        self.p.destroy()

    def hide(self):
        pass

    def show(self):
        pass

    def update(self):
        pass

    def __del__(self):
        pass
Example #4
0
def show_word(word):
    t = time()
    select = [0]
    root = Tk()
    root.title('CrazyEnglish')
    try:
        root.call('wm', 'iconphoto', root._w, PhotoImage(file='english.png'))
    except Exception:
        print 'Error loading icon'
    root.geometry(
        str(root.winfo_screenwidth()) + 'x' + str(root.winfo_screenheight()) +
        '+0+0')  #root.winfo_screenheight()
    root.resizable(False, False)
    root.protocol('WM_DELETE_WINDOW', lambda: exit(root, select))

    canvas = Canvas(root)  #,bg='green')
    canvas.place(x=100, y=100, width=800, height=50)

    canvas.create_text(0,
                       0,
                       text=word[0],
                       anchor='nw',
                       font=('', 14),
                       fill='red')
    canvas.create_text(0, 30, text='(' + word[1] + ')', anchor='nw')

    entry = Entry(root, font=('', 10))
    entry.place(x=100, y=200, width=800, height=30)

    Button(root, text='OK',
           command=lambda: press_btn(root, entry, word[0])).place(x=100,
                                                                  y=250,
                                                                  height=30,
                                                                  width=80)

    root.after(0, lambda: close_window(root, t))

    entry.focus_force()

    root.mainloop()

    return select[0]
Example #5
0
    def display(self, frame_obj):

        canvas_popup = Canvas(frame_obj, background=conf.left_nav_background)
        # canvas_popup.config(x=0, y=0)
        canvas_popup.place(x=(frame_obj.sw/2), y=(frame_obj.sh/2)-100)

        if self.title != "":
            title_label = Label(canvas_popup, text=self.title, fg=conf.main_text_color)
            title_label.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background)
            title_label.grid(row=0, sticky='e,w', padx=10, pady=10)

        if self.content != "":
            content_label = Label(canvas_popup, text=self.content, fg=conf.main_text_color)
            content_label.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background)
            content_label.grid(row=1, sticky='e,w', padx=10, pady=10)

        if self.content != "":
            action_button = Button(canvas_popup, text="Ok", fg=conf.main_text_color)
            action_button.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background)
            action_button.bind("<Button-1>", self.dismiss)
            action_button.grid(row=2, sticky='e,w', padx=10, pady=10)
class LD_GUI(Frame):
    def __init__(self, parent):
        Frame.__init__(self, master=parent)
        parent.title('Liar\'s Dice')
        self.canvas = Canvas(self, width=550, height=500)
        self.canvas.pack(fill='both', expand=True)
        self.canvas.place(x=0, y=0)
        self.bid_logs = ScrolledText(self, undo=True, width=100, height=100)
        self.bid_logs.pack(fill='both', expand=True)
        self.bid_logs['font'] = ('consolas', '12')
        self.bid_logs.place(x=350, y=0)
        self.input_box = Text(self, undo=True, width=100, height=100)
        self.input_box.pack(fill='both', expand=True)
        self.input_box['font'] = ('consolas', '12')
        self.input_box.place(x=350, y=450)
        self.pack(fill='both', expand=True)
        self.insert_to_log()

    def insert_to_log(self):
        self.bid_logs.insert(tki.INSERT, 'HI!')
        self.input_box.insert(tki.INSERT, 'OK')

    def initGame(self):
        try:
            self.idot = Image.open("dot.png")
            self.dot = ImageTk.PhotoImage(self.idot)
            self.ihead = Image.open("head.png")
            self.head = ImageTk.PhotoImage(self.ihead)
            self.iapple = Image.open("apple.png")
            self.apple = ImageTk.PhotoImage(self.iapple)

        except IOError, e:
            print e
            sys.exit(1)

        self.createObjects()
        self.locateApple()
        self.bind_all("<Key>", self.onKeyPressed)
        self.after(DELAY, self.onTimer)
class LD_GUI(Frame):
    def __init__(self, parent):
        Frame.__init__(self, master=parent)
        parent.title('Liar\'s Dice')
        self.canvas = Canvas(self, width=550, height=500)
        self.canvas.pack(fill='both', expand = True)
        self.canvas.place(x=0, y=0)
        self.bid_logs = ScrolledText(self, undo=True, width=100, height = 100)
        self.bid_logs.pack(fill='both', expand = True)
        self.bid_logs['font'] = ('consolas', '12')
        self.bid_logs.place(x=350, y=0)
        self.input_box = Text(self, undo=True, width=100, height=100)
        self.input_box.pack(fill='both', expand = True)
        self.input_box['font'] = ('consolas', '12')
        self.input_box.place(x=350, y=450)
        self.pack(fill='both', expand = True)
        self.insert_to_log()

    def insert_to_log(self):
        self.bid_logs.insert(tki.INSERT, 'HI!')
        self.input_box.insert(tki.INSERT, 'OK')

    def initGame(self):
        try:
            self.idot = Image.open("dot.png")
            self.dot = ImageTk.PhotoImage(self.idot)    
            self.ihead = Image.open("head.png")
            self.head = ImageTk.PhotoImage(self.ihead)           
            self.iapple = Image.open("apple.png")
            self.apple = ImageTk.PhotoImage(self.iapple) 

        except IOError, e:
            print e
            sys.exit(1)

        self.createObjects()
        self.locateApple()
        self.bind_all("<Key>", self.onKeyPressed)
        self.after(DELAY, self.onTimer)
Example #8
0
class calculadora(object):
    def __init__(self, master):

        ######### VARIABLES ADMIN #############

        # SCREEN
        fullscreen = 0
        ultrawidescreen = 0

        # Velocidad (lista de velocidades en milisegundos)
        self.velist = [3000,2000,1500,1000,750,500,300,200,150,100,80,60,40,20,10]

        # Debug
        self.debuguear = 1
        self.porcionlen = 70 # Porcion a mostrar
        
        # Display out to Arduino (on/off)
        self.sendToDisplay = 0

        #Arduino COMM (Display)
        if self.sendToDisplay>0:
            arduino = serial.Serial('COM3', 9600, timeout=.1) # debe coincidir con los baudios y el puerto arduino
            time.sleep(0.1)

        #######################################
        ######### VARIABLES GENERALES #########

        # nsp class
        self.nsp = NumericStringParser()

        # Vel sets
        self.velmax = len(self.velist)-1
        self.vel = -1

        # Contador de envio a Arduino
        self.resultadoAduino = ''
        self.contador = -1

        #######################################

        self.master = master
        if fullscreen>0:
            # Full screen
            master.overrideredirect(True)
            master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
            master.focus_set()  # <-- move focus to this widget
            # Otra opción
            # master.attributes('-fullscreen', True)
        else:
            # master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth()-16, root.winfo_screenheight()-80))
            master.geometry("%dx%d+0+0" % (master.winfo_screenwidth()-16, master.winfo_screenheight()-80))

        master.title("Calculadora")

        master.bind("<Escape>", lambda e: e.widget.quit()) # Python 2
        master.bind("<Key>", self.recibeChar)

        self.dondestoy = 'p'

        # Dividendo p
        self.dividendostr = ""
        self.dividendo = StringVar()
        self.dividendo.set(self.dividendostr)
        if ultrawidescreen>0:
            # UltraWide Screen
            self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=18, justify="center", font=("Roboto", 192))
        else:
            # 16:9 Screen
            self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=21, justify="center", font=("Roboto", 96))

        self.line = Canvas(master, width=master.winfo_screenwidth(), height=50)
        # self.line.create_rectangle(0, 0, master.winfo_screenwidth(), 20, outline="#000", fill="#000")
        self.line.create_line(0, 0, master.winfo_screenwidth(), 0, fill="#000",width=50)

        # Divisor q
        self.divisorstr = "1"
        self.divisor = StringVar()
        self.divisor.set(self.divisorstr)
        if ultrawidescreen>0:
            # UltraWide Screen
            self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=18, justify="center", font=("Roboto", 192))
        else:
            # 16:9 Screen
            self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=21, justify="center", font=("Roboto", 96))

        # Resultado res
        self.resultastr = ""
        self.resulta = StringVar()
        self.resulta.set(self.resultastr)
        if ultrawidescreen>0:
            # UltraWide Screen
            self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=213, justify="left", font=("Roboto", 16))
        else:
            # 16:9 Screen
            self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=120, justify="left", font=("Roboto", 16))

        # Posiciona
        self.line.place(relx=0, rely=.495)
        self.labelp.place(relx=0, rely=.22)
        self.labelq.place(relx=0, rely=.545)
        self.labelr.place(relx=0, rely=.80)

        # init timer de envio a arduino
        # self.onUpdate()

        #######################################

        # self.operacion(p='',q=1)
        # self.calculadora()

        #######################################
    def filtrar(self,s):
        if '.' in s:
            r = {
                '1':'A',
                '2': 'B',
                '3': 'C',
                '4': 'D',
                '5': 'E',
                '6': 'F',
                '7': 'G',
                '8': 'H',
                '9': 'I',
                '0': 'J'
            }
            s = s.split('.')
            c = s[0][-1:]
            s[0] = s[0][0:-1]
            return s[0]+r[c]+s[1]
        else:
            return s

    def modcad(self,cad,c):
        cad = cad.decode('utf-8')
        p = cad[-1:]
        if isinstance(c, int):
            # if p==')':
            #     if (len(cad)>=c+1):
            #         cad = cad[:-(c+1)]+')'
            # else:
            if (len(cad)>=c):
                cad = cad[:-c]
        else:
            c = c.decode('utf-8')
            # if p==')':
            #     cad = cad[:-1]+c+')'
            # else:
            cad = cad+c
        cad = cad.encode('utf-8')
        return cad

    def recibeChar(self,event):
        # Color gris en divisor cuando es 1
        k = event.keycode
        c = event.char
        p = str(self.dividendostr)
        q = str(self.divisorstr)
        # self.resultastr = c+': ',str(k)+': '+str(event.state)
        # self.resulta.set(self.resultastr)
        # return

        numrs = ['0','1','2','3','4','5','6','7','8','9']
        if (self.dondestoy=='q'):
            cadena = q
            # if cadena=='1':
            #     cadena = ''
        else:
            cadena = p
        # SALIDAS
        if c=='c': # c
            # reiniciar programa
            self.calculadora('REINICIAR', '', p, q)
            return
            # return '','REINICIAR'
        elif c=='k': # k
            # salir del programa
            self.calculadora('SALIR', '', p, q)
            return
            # return '','SALIR'

        # AVANZAR Y STOP
        if c=='a': # Avanza/Acelera
            if self.vel<0 and self.resultadoAduino!='':
                self.vel=0
                self.onUpdate()
            elif self.vel<self.velmax:
                self.vel = self.vel+1
            return
            # return '','REINICIAR'
        elif c=='s': # Stop
            if self.vel>=0:
                self.vel = self.vel-1
            return

        # IGUAL A
        elif k==10 or k==13 or c=='=':# or k==61: # [ENTER] o [=] > Salto de línea o igual: '\n' ó '\r' ó '='
            # imprimir cadena RESULTADO
            self.calculadora('RESULTADO', cadena, p, q)
            return
            # return cadena,'RESULTADO'

        # ESCRITURA NORMAL
        elif k == 8: # BACKSPACE
            # recortar cadena un digito
            cadena = self.modcad(cadena,1)
        elif c in numrs: # NUMEROS 0-9
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        # elif c==',' or c=='.': # COMA o PUNTO
        #     c='.' # Siempre usa punto
        #     # incrementa la cadena con c
        #     cadena = self.modcad(cadena,str(c))

        # NUMEROS ESPECIALES e y pi
        elif c=='e':    # e => 101
            # Euler's number => 'e'
            c = 'e'
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='h':    # h => 104
            # PI => 'h'
            c = 'π'
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='f':    # f => 104
            # PI => 'h'
            c = 'φ'
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        
        # OPERACIONES SIMPLES: * + - /
        elif c=='*': # * => 42
            # Multiplicación => Reemplaza asterisco con signo de multiplicacion ×
            c = '×'
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='+':    # + => 43
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='-':    # - => 45
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='r':    # r
            # SQRT => 'r'
            if '(' in cadena:
                if ')' in cadena:
                    c=''
                else:
                    c=')'
            else:
                c = '√('
            # incrementa la cadena con c
            cadena = self.modcad(cadena,str(c))
        elif c=='p':    # p => 112
            # Debe enviar al valor p sólo si no estamos ahí
            if (self.dondestoy!='p'):
                self.calculadora('SETP', cadena, p, q)
                return
                # return cadena, 'SETP'
        elif c=='q':    # q => 113
            # Debe enviar al valor q sólo si no estamos ahí
            if (self.dondestoy!='q'):
                self.calculadora('SETQ', cadena, p, q)
                return
                # return cadena, 'SETQ'

        if (self.dondestoy=='p'):
            p = cadena
        if (self.dondestoy=='q'):
            q = cadena
        # if (q==''):
        #     q = '1'
        self.operacion(p,q)
    
    def pausa(self, ):
        while 1:
            c = readchar.readchar()
            if c!='':
                break


    def calculadora(self, estado, cadena='', p='', q=''):
        if (estado=='RESULTADO'):
            self.vel = -1 # Stop timer
            self.contador = -1 # Reset timer
            if (self.dondestoy=='p'):
                p = cadena
            if (self.dondestoy=='q'):
                q = cadena
            if p=='':
                p='0'
            if (q==''):
                q='1'
            if '(' in p and ')' not in p:
                p=p+')'
            if '(' in q and ')' not in q:
                q=q+')'
            res = self.nsp.eval(p+'/'+q)
            res = str(res)
            if (res[-2:]=='.0'):
                res=res[:-2]
            # res = p+'/'+q
            self.resultado(p,q, res)
            # self.pausa()
            # self.calculadora(cadena,p,q,dondestoy)
        if (estado=='REINICIAR'):
            self.vel = -1 # Stop timer
            self.contador = -1 # Reset timer
            self.operacion(p='',q=1)
            self.resultastr = ''
            self.resulta.set(self.resultastr)
            self.dondestoy = 'p'
            self.labelp.config(bg="#fd0")
            self.labelq.config(bg="#eee")
            # self.calculadora()
        if (estado=='SALIR'):
            self.vel = -1 # Stop timer
            self.master.quit()
            # return
        if (estado=='SETP'):
            q = cadena
            if '(' in q and ')' not in q:
                q=q+')'
            if q=='0' or q=='':
                self.divisorstr = str('1')
                self.divisor.set(self.divisorstr)
                self.labelq.config(fg="#aaa")
            self.dondestoy = 'p'
            self.labelp.config(bg="#fd0")
            self.labelq.config(bg="#eee")
            # self.calculadora(p,p,q,dondestoy)
        if (estado=='SETQ'):
            p = cadena
            if '(' in p and ')' not in p:
                p=p+')'
            if q=='1':
                self.divisorstr = str('')
                self.divisor.set(self.divisorstr)
                self.labelq.config(fg="#aaa")
            self.dondestoy = 'q'
            self.labelp.config(bg="#eee")
            self.labelq.config(bg="#fd0")
            # self.calculadora(q,p,q,dondestoy)

    def maxlen(self, p,q):
        maxlen = len(str(p))
        if (len(str(q))>maxlen):
            maxlen = len(str(q))
        lp = len(str(p))
        lq = len(str(q))
        return maxlen,lp,lq

    def operacion(self, p='',q=1):
        ml,lp,lq = self.maxlen(p,q)
        self.dividendostr = str(p)
        self.dividendo.set(self.dividendostr)
        self.divisorstr = str(q)
        self.divisor.set(self.divisorstr)

        # Color gris en divisor cuando es 1
        if self.divisorstr != "1":
            self.labelq.config(fg="#000")
        else:
            self.labelq.config(fg="#aaa")

    def resultado(self, p,q, res):
        ml,lp,lq = self.maxlen(p,q)
        self.dividendostr = str(p)
        self.dividendo.set(self.dividendostr)
        self.divisorstr = str(q)
        self.divisor.set(self.divisorstr)

        # Color gris en divisor cuando es 1
        if self.divisorstr != "1":
            self.labelq.config(fg="#000")
        else:
            self.labelq.config(fg="#aaa")

        ################################################
        # Calcula p y q numericamente a floats
        res = self.nsp.eval('('+p+')/('+q+')')
        # nspep = self.nsp.eval(p)
        # nspeq = self.nsp.eval(q)
        # print("p:", nspep)
        # print("q:", nspeq)
        # if isinstance(nspep, float)==False:
        #     nspep = nspep[1]
        # if isinstance(nspeq, float)==False:
        #     nspeq = nspeq[1]
        # print("p:", nspep)
        # print("q:", nspeq)
        # res = self.nsp.eval(p+'/'+q)
        # print("p:", nspep)
        # print("q:", nspeq)
        # fp = float(nspep)
        # fq = float(nspeq)
        # fp = Decimal(p)
        # fq = Decimal(q)
        # print fp,fq

        ################################################
        ####### AQUÍ VAN LOS CALCULOS DE PERIODO #######

        # PL = self.Periodo(fq)
        # prec = (PL[0]+2)*(PL[1]+5)

        # self.resultastr = str(",".join([str(x) for x in PL]))
        # self.resulta.set(self.resultastr)
        # return

        # prec = (PL[0]+2)*(PL[1]+5)
        # prec = 1000
        # getcontext().prec = prec

        # res = fp/fq
        # res = Decimal(fp)/Decimal(fq)
        # nrp, pl = PL[0], PL[1]
        # if not '.' in str(res):
        #     precad = str(res)+'.'
        #     res = str(res)+'.0'
        #     cad = '0'
        #     repite = '0'
        #     longperiodo = '1'
        # else:
        #     res = str(res)
        #     cad = res.split('.')
        #     precad = str(cad[0])+'.'+str(cad[0:nrp-1])
        #     cad = str(res.split('.')[1])
        #     repite = cad[nrp-1:pl+nrp-1]
        #     longperiodo = str(PL[1])


        # RESULTADO COMO CADENA
        nres = ''
        sres = str(res)

        # Set start envio Arduino
        self.resultadoAduino = self.filtrar(sres)
        self.contador = -1
        self.vel = 0

        # # IMPRIME LOS DETALLES DEL RESULTADO
        # salida = ''
        # for i in range(len(sres)):
        #     r = sres[i]
        #     if i/100==int(i/100):
        #         r=r+"\n"
        #     nres=nres+r
        # salida = salida+ 'LONGITUD DEL RESULTADO: '+str(len(sres))
        # salida = salida+ '\nRESULTADO: '+nres
        # self.resultastr = salida
        # self.resulta.set(self.resultastr)

        self.onUpdate()

    def onUpdate(self):
        # Actualiza el caracter enviado, la posición y el estado actual (pausa/play)
        self.contador = self.contador+1
        if self.contador>len(self.resultadoAduino)-2:
            enviar = '0'
        else:
            enviar = self.resultadoAduino[self.contador]

        if self.debuguear>0:
            salida = "Velocidad: "+str(self.velist[self.vel])+" ms"
            salida = salida+u"\nPosición: "+str(self.contador)
            salida = salida+u"\nDígito: "+enviar
            inicio = self.contador-self.porcionlen
            if inicio<0:
                inicio=0
            salida = salida+u"\nPorción: "+self.resultadoAduino[inicio:self.contador+1].rjust(self.porcionlen, ' ').replace(' ','  ')
            self.resultastr = salida
            self.resulta.set(self.resultastr)
        # ENVIO A DISPLAY
        if self.sendToDisplay>0:
            arduino.write(enviar) # Envia digito actual a DISPLAY, la pausa la genera el unUpdate mismo
        # DEBUG EN CONSOLA
        if self.debuguear>0:
            print(current_iso8601(),self.contador,self.vel,self.velist[self.vel],enviar)
        # schedule timer para ayutollamarse cada segundo
        if self.vel>=0:
            self.master.after(self.velist[self.vel], self.onUpdate)
Example #9
0
    def __init__(self, master):
        def center(win):
            win.update_idletasks()
            width = win.winfo_width()
            height = win.winfo_height()
            x = (win.winfo_screenwidth() // 4) - (width // 2) + 40
            y = (win.winfo_screenheight() // 4) - (height // 2) + 40
            win.geometry('{}x{}+{}+{}'.format(width, height, x, y))

        def callback(event):
            event.widget.focus_set()
            print "clicked at", event.x, event.y

            if self.add_tasks_flg.get() == 1:
                # Select number of robots
                # Define elements of pop up window
                self.top = Toplevel()

                self.num_robots = StringVar(self.top)
                self.num_robots.set("1")  # default value
                w = OptionMenu(self.top, self.num_robots, '1', '2', '3',
                               '4').grid(row=0, column=1)
                text1 = Message(self.top, text="Number of robots:",
                                width=150).grid(row=0, column=0)

                self.e = Entry(self.top, width=10)
                self.e.grid(row=1, column=1)
                text2 = Message(self.top, text="Task duration:",
                                width=150).grid(row=1, column=0)
                text3 = Message(self.top, text="(s)", width=60).grid(row=1,
                                                                     column=2)

                newline = Message(self.top, text=" ").grid(row=2)

                button = Button(self.top,
                                text='Enter',
                                command=lambda: self.enter_task(event)).grid(
                                    row=3, column=1)
                button_cancel = Button(self.top,
                                       text='Cancel',
                                       command=self.cancel_task).grid(row=3,
                                                                      column=2)

                center(self.top)

        master.title("Map Interface")
        master.minsize(width=1000, height=750)
        master.maxsize(width=1000, height=750)
        master.config(bg=BKG_COLOUR)
        self.master = master

        # Canvas for overlaying map
        self.map_canvas = Canvas(master,
                                 width=CANVAS_W,
                                 height=CANVAS_H,
                                 bg='gray85',
                                 highlightthickness=0)
        self.map_canvas.pack(side='right', padx=50)
        self.map_canvas.bind("<Button-1>", callback)
        global CANVAS_PTR
        CANVAS_PTR = self.map_canvas
        self.master.update()
        w = self.map_canvas.winfo_width()
        h = self.map_canvas.winfo_height()
        # Overlay a grid
        for i in range(0, w, SQ_SIZE):
            if i != 0:
                self.map_canvas.create_line(i, 0, i, h, dash=1)
        for i in range(0, h, SQ_SIZE):
            if i != 0:
                self.map_canvas.create_line(0, i, w, i, dash=1)

        # Load in flame icon from flame.gif
        self.flame_icon = PhotoImage(file="flame.gif")
        # Load in the drone icon from drone.gif
        global DRONE_ICON
        DRONE_ICON = PhotoImage(file="drone.gif")

        buttons_frame = Canvas(master,
                               width=163,
                               height=230,
                               bg=BUTTONS_BKG_COLOUR,
                               highlightthickness=1,
                               highlightbackground='dim grey')
        buttons_frame.place(x=40, y=200)

        # Define UI buttons
        self.add_tasks_flg = IntVar()
        self.add_tasks_b = Checkbutton(master,
                                       text="Add Tasks",
                                       variable=self.add_tasks_flg,
                                       highlightbackground=BUTTONS_BKG_COLOUR,
                                       background=BUTTONS_BKG_COLOUR)
        self.add_tasks_b.place(x=77, y=240)

        self.clear_wp_b = Button(master,
                                 text='Clear Tasks',
                                 command=self.clear_wp,
                                 highlightbackground=BUTTONS_BKG_COLOUR)
        self.clear_wp_b.config(width=10)
        self.clear_wp_b.place(x=65, y=270)
        '''
        self.gen_wp_file_b = Button(master, text='Generate Waypoints File', command=self.gen_wp_file, highlightbackground=BKG_COLOUR)
        self.gen_wp_file_b.config(width=20)
        self.gen_wp_file_b.place(x=20, y=250)
        '''

        self.land_b = Button(master,
                             text='Land',
                             command=self.land,
                             highlightbackground=BUTTONS_BKG_COLOUR)
        self.land_b.config(width=10)
        self.land_b.place(x=65, y=350)

        # Set up coordinate system conversion and display corners of room:
        file_obj = open('antenna_locations.txt', 'r')
        anchors = []
        for line in file_obj:
            cur_anchors = map(float, line.split())
            anchors.append(cur_anchors)
        file_obj.close()
        anchors = (np.array(anchors)).T

        # Find largest (abs) x and y values to use a reference for conversion ratio
        x_vals = anchors[0]
        largest_x_val = x_vals[np.argmax(abs(x_vals))]
        y_vals = anchors[1]
        largest_y_val = y_vals[np.argmax(abs(y_vals))]

        if largest_x_val > largest_y_val:
            largest_y_val = largest_x_val
        else:
            largest_x_val = largest_y_val

        global m_per_pixel_x
        m_per_pixel_x = float(largest_x_val / (CANVAS_W / 2))
        global m_per_pixel_y
        m_per_pixel_y = float(largest_y_val / (CANVAS_H / 2))

        # Place antenna (anchors) on UI
        anchors = anchors.T
        for cur_anchor in anchors:
            x_pixel_loc = cur_anchor[0] / m_per_pixel_x + CANVAS_W / 2
            y_pixel_loc = -1 * (cur_anchor[1] / m_per_pixel_y) + CANVAS_H / 2

            # Draw antenna @ location
            global ANTENNA_LIST
            antenna_id = self.map_canvas.create_oval(x_pixel_loc - 15,
                                                     y_pixel_loc - 15,
                                                     x_pixel_loc + 15,
                                                     y_pixel_loc + 15,
                                                     fill='red')

        self.master.update()
class PiPresents(object):

    def __init__(self):
        gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL)
        self.pipresents_issue="1.3"
        self.pipresents_minorissue = '1.3.1g'
        # position and size of window without -f command line option
        self.nonfull_window_width = 0.45 # proportion of width
        self.nonfull_window_height= 0.7 # proportion of height
        self.nonfull_window_x = 0 # position of top left corner
        self.nonfull_window_y=0   # position of top left corner
        self.pp_background='black'

        StopWatch.global_enable=False

        # set up the handler for SIGTERM
        signal.signal(signal.SIGTERM,self.handle_sigterm)
        

# ****************************************
# Initialisation
# ***************************************
        # get command line options
        self.options=command_options()

        # get Pi Presents code directory
        pp_dir=sys.path[0]
        self.pp_dir=pp_dir
        
        if not os.path.exists(pp_dir+"/pipresents.py"):
            if self.options['manager']  is False:
                tkMessageBox.showwarning("Pi Presents","Bad Application Directory:\n{0}".format(pp_dir))
            exit(103)

        
        # Initialise logging and tracing
        Monitor.log_path=pp_dir
        self.mon=Monitor()
        # Init in PiPresents only
        self.mon.init()

        # uncomment to enable control of logging from within a class
        # Monitor.enable_in_code = True # enables control of log level in the code for a class  - self.mon.set_log_level()
        
        # make a shorter list to log/trace only some classes without using enable_in_code.
        Monitor.classes  = ['PiPresents', 'pp_paths',
                            
                            'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow',
                            'PathManager','ControlsManager','ShowManager','PluginManager',
                            'MplayerDriver','OMXDriver','UZBLDriver',
                            'KbdDriver','GPIODriver','TimeOfDay','ScreenDriver','Animate','OSCDriver'
                            ]

        # Monitor.classes=['PiPresents','ArtMediaShow','VideoPlayer','OMXDriver']
        
        # get global log level from command line
        Monitor.log_level = int(self.options['debug'])
        Monitor.manager = self.options['manager']
        # print self.options['manager']
        self.mon.newline(3)    
        self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue)
        # self.mon.log (self," OS and separator:" + os.name +'  ' + os.sep)
        self.mon.log(self,"sys.path[0] -  location of code: "+sys.path[0])
        if os.geteuid() !=0:
            user=os.getenv('USER')
        else:
            user = os.getenv('SUDO_USER')
        self.mon.log(self,'User is: '+ user)
        # self.mon.log(self,"os.getenv('HOME') -  user home directory (not used): " + os.getenv('HOME')) # does not work
        # self.mon.log(self,"os.path.expanduser('~') -  user home directory: " + os.path.expanduser('~'))   # does not work

        # optional other classes used
        self.root=None
        self.ppio=None
        self.tod=None
        self.animate=None
        self.gpiodriver=None
        self.oscdriver=None
        self.osc_enabled=False
        self.gpio_enabled=False
        self.tod_enabled=False
         
        # get home path from -o option
        self.pp_home = pp_paths.get_home(self.options['home'])
        if self.pp_home is None:
            self.end('error','Failed to find pp_home')

        # get profile path from -p option
        # pp_profile is the full path to the directory that contains 
        # pp_showlist.json and other files for the profile
        self.pp_profile = pp_paths.get_profile_dir(self.pp_home, self.options['profile'])
        if self.pp_profile is None:
            self.end('error','Failed to find profile')

        # check profile exists
        if os.path.exists(self.pp_profile):
            self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile)
        else:
            self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile)
            self.end('error','Failed to find profile')

        self.mon.start_stats(self.options['profile'])
        
        # check 'verify' option
        if self.options['verify'] is True:
            val =Validator()
            if  val.validate_profile(None,pp_dir,self.pp_home,self.pp_profile,self.pipresents_issue,False) is  False:
                self.mon.err(self,"Validation Failed")
                self.end('error','Validation Failed')

        # initialise and read the showlist in the profile
        self.showlist=ShowList()
        self.showlist_file= self.pp_profile+ "/pp_showlist.json"
        if os.path.exists(self.showlist_file):
            self.showlist.open_json(self.showlist_file)
        else:
            self.mon.err(self,"showlist not found at "+self.showlist_file)
            self.end('error','showlist not found')

        # check profile and Pi Presents issues are compatible
        if float(self.showlist.sissue()) != float(self.pipresents_issue):
            self.mon.err(self,"Version of profile " + self.showlist.sissue() + " is not  same as Pi Presents, must exit")
            self.end('error','wrong version of profile')


        # get the 'start' show from the showlist
        index = self.showlist.index_of_show('start')
        if index >=0:
            self.showlist.select(index)
            self.starter_show=self.showlist.selected_show()
        else:
            self.mon.err(self,"Show [start] not found in showlist")
            self.end('error','start show not found')

        if self.starter_show['start-show']=='':
             self.mon.warn(self,"No Start Shows in Start Show")       

# ********************
# SET UP THE GUI
# ********************
        # turn off the screenblanking and saver
        if self.options['noblank'] is True:
            call(["xset","s", "off"])
            call(["xset","s", "-dpms"])

        self.root=Tk()   
       
        self.title='Pi Presents - '+ self.pp_profile
        self.icon_text= 'Pi Presents'
        self.root.title(self.title)
        self.root.iconname(self.icon_text)
        self.root.config(bg=self.pp_background)

        self.mon.log(self, 'native screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixcels')
        if self.options['screensize'] =='':        
            self.screen_width = self.root.winfo_screenwidth()
            self.screen_height = self.root.winfo_screenheight()
        else:
            reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize'])
            if reason =='error':
                self.mon.err(self,message)
                self.end('error',message)

        self.mon.log(self, 'commanded screen dimensions are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixcels')
       
        # set window dimensions and decorations
        if self.options['fullscreen'] is False:
            self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width)
            self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height)
            self.window_x=self.nonfull_window_x
            self.window_y=self.nonfull_window_y
            self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y))
        else:
            self.window_width=self.screen_width
            self.window_height=self.screen_height
            self.root.attributes('-fullscreen', True)
            os.system('unclutter 1>&- 2>&- &') # Suppress 'someone created a subwindow' complaints from unclutter
            self.window_x=0
            self.window_y=0  
            self.root.geometry("%dx%d%+d%+d"  % (self.window_width,self.window_height,self.window_x,self.window_y))
            self.root.attributes('-zoomed','1')

        # canvs cover the whole screen whatever the size of the window. 
        self.canvas_height=self.screen_height
        self.canvas_width=self.screen_width
  
        # make sure focus is set.
        self.root.focus_set()

        # define response to main window closing.
        self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort)

        # setup a canvas onto which will be drawn the images or text
        self.canvas = Canvas(self.root, bg=self.pp_background)


        if self.options['fullscreen'] is True:
            self.canvas.config(height=self.canvas_height,
                               width=self.canvas_width,
                               highlightthickness=0)
        else:
            self.canvas.config(height=self.canvas_height,
                    width=self.canvas_width,
                        highlightthickness=1,
                               highlightcolor='yellow')
            
        self.canvas.place(x=0,y=0)
        # self.canvas.config(bg='black')
        self.canvas.focus_set()


                
# ****************************************
# INITIALISE THE INPUT DRIVERS
# ****************************************

        # each driver takes a set of inputs, binds them to symboic names
        # and sets up a callback which returns the symbolic name when an input event occurs/

        # use keyboard driver to bind keys to symbolic names and to set up callback
        kbd=KbdDriver()
        if kbd.read(pp_dir,self.pp_home,self.pp_profile) is False:
            self.end('error','cannot find or error in keys.cfg')
        kbd.bind_keys(self.root,self.handle_input_event)

        self.sr=ScreenDriver()
        # read the screen click area config file
        reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile)
        if reason == 'error':
            self.end('error','cannot find screen.cfg')


        # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes
        # click areas are made on the Pi Presents canvas not the show canvases.
        reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event)
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)


# ****************************************
# INITIALISE THE APPLICATION AND START
# ****************************************
        self.shutdown_required=False
        self.exitpipresents_required=False
        
        # kick off GPIO if enabled by command line option
        self.gpio_enabled=False
        if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+os.sep+ 'gpio.cfg'):
            # initialise the GPIO
            self.gpiodriver=GPIODriver()
            reason,message=self.gpiodriver.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,50,self.handle_input_event)
            if reason == 'error':
                self.end('error',message)
            else:
                self.gpio_enabled=True
                # and start polling gpio
                self.gpiodriver.poll()
            
        # kick off animation sequencer
        self.animate = Animate()
        self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event)
        self.animate.poll()

        #create a showmanager ready for time of day scheduler and osc server
        show_id=-1
        self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home)
        # first time through set callback to terminate Pi Presents if all shows have ended.
        self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist)
        # Register all the shows in the showlist
        reason,message=self.show_manager.register_shows()
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)

        # Init OSCDriver, read config and start OSC server
        self.osc_enabled=False
        if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'):
            self.oscdriver=OSCDriver()
            reason,message=self.oscdriver.init(self.pp_profile,self.handle_command,self.handle_input_event,self.e_osc_handle_output_event)
            if reason == 'error':
                self.end('error',message)
            else:
                self.osc_enabled=True
                self.root.after(1000,self.oscdriver.start_server())

        # and run the start shows
        self.run_start_shows()

       # set up the time of day scheduler including catchup         
        self.tod_enabled=False
        if os.path.exists(self.pp_profile + os.sep + 'schedule.json'):
            # kick off the time of day scheduler which may run additional shows
            self.tod=TimeOfDay()
            self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.root,self.handle_command)
            self.tod_enabled = True


        # then start the time of day scheduler
        if self.tod_enabled is True:
            self.tod.poll()

        # start Tkinters event loop
        self.root.mainloop( )


    def parse_screen(self,size_text):
        fields=size_text.split('*')
        if len(fields)!=2:
            return 'error','do not understand --fullscreen comand option',0,0
        elif fields[0].isdigit()  is False or fields[1].isdigit()  is False:
            return 'error','dimensions are not positive integers in ---fullscreen',0,0
        else:
            return 'normal','',int(fields[0]),int(fields[1])
        

# *********************
#  RUN START SHOWS
# ********************   
    def run_start_shows(self):
        self.mon.trace(self,'run start shows')
        # parse the start shows field and start the initial shows       
        show_refs=self.starter_show['start-show'].split()
        for show_ref in show_refs:
            reason,message=self.show_manager.control_a_show(show_ref,'open')
            if reason == 'error':
                self.mon.err(self,message)
                


# *********************
# User inputs
# ********************
    # handles one command provided as a line of text
    def handle_command(self,command_text):
        self.mon.log(self,"command received: " + command_text)
        if command_text.strip()=="":
            return

        if command_text[0]=='/': 
            if self.osc_enabled is True:
                self.oscdriver.send_command(command_text)
            return
        
        fields= command_text.split()
        show_command=fields[0]
        if len(fields)>1:
            show_ref=fields[1]
        else:
            show_ref=''
            
        if show_command in ('open','close'):
            if self.shutdown_required is False:
                reason,message=self.show_manager.control_a_show(show_ref,show_command)
            else:
                return
        elif show_command == 'exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to get out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            else:
                reason,message= self.show_manager.exit_all_shows()

        elif show_command == 'shutdownnow':
            # need root.after to get out of st thread
            self.root.after(1,self.e_shutdown_pressed)
            return
        else:
            reason='error'
            message = 'command not recognised: '+ show_command
            
        if reason=='error':
            self.mon.err(self,message)
        return

    def e_all_shows_ended_callback(self):
            self.all_shows_ended_callback('normal','no shows running')

    def e_shutdown_pressed(self):
            self.shutdown_pressed('now')


    def e_osc_handle_output_event(self,line):
        #jump  out of server thread
        self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg))

    def  osc_handle_output_event(self,line):
        self.mon.log(self,"output event received: "+ line)
        #osc sends output events as a string
        reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line)
        if reason == 'error':
            self.mon.err(self,message)
            self.end(reason,message)
        self.handle_output_event(name,param_type,param_values,0)

               
    def handle_output_event(self,symbol,param_type,param_values,req_time):
        if self.gpio_enabled is True:
            reason,message=self.gpiodriver.handle_output_event(symbol,param_type,param_values,req_time)
            if reason =='error':
                self.mon.err(self,message)
                self.end(reason,message)
        else:
            self.mon.warn(self,'GPIO not enabled')


    # all input events call this callback with a symbolic name.
    # handle events that affect PP overall, otherwise pass to all active shows
    def handle_input_event(self,symbol,source):
        self.mon.log(self,"event received: "+symbol + ' from '+ source)
        if symbol == 'pp-terminate':
            self.handle_user_abort()
            
        elif symbol == 'pp-shutdown':
            self.shutdown_pressed('delay')
            
        elif symbol == 'pp-shutdownnow':
            # need root.after to grt out of st thread
            self.root.after(1,self.e_shutdown_pressed)
            return
        
        elif symbol == 'pp-exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to grt out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            reason,message= self.show_manager.exit_all_shows()
        else:
            # events for shows affect the show and could cause it to exit.
            for show in self.show_manager.shows:
                show_obj=show[ShowManager.SHOW_OBJ]
                if show_obj is not None:
                    show_obj.handle_input_event(symbol)



    def shutdown_pressed(self, when):
        if when == 'delay':
            self.root.after(5000,self.on_shutdown_delay)
        else:
            self.shutdown_required=True
            if self.show_manager.all_shows_exited() is True:
               self.all_shows_ended_callback('normal','no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()           


    def on_shutdown_delay(self):
        # 5 second delay is up, if shutdown button still pressed then shutdown
        if self.gpiodriver.shutdown_pressed() is True:
            self.shutdown_required=True
            if self.show_manager.all_shows_exited() is True:
               self.all_shows_ended_callback('normal','no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()


    def handle_sigterm(self,signum,frame):
        self.mon.log(self,'SIGTERM received - '+ str(signum))
        self.terminate()


    def handle_user_abort(self):
        self.mon.log(self,'User abort received')
        self.terminate()

    def terminate(self):
        self.mon.log(self, "terminate received")
        needs_termination=False
        for show in self.show_manager.shows:
            # print  show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF]
            if show[ShowManager.SHOW_OBJ] is not None:
                needs_termination=True
                self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF])
                # call shows terminate method
                # eventually the show will exit and after all shows have exited all_shows_callback will be executed.
                show[ShowManager.SHOW_OBJ].terminate()
        if needs_termination is False:
            self.end('killed','killed - no termination of shows required')


# ******************************
# Ending Pi Presents after all the showers and players are closed
# **************************

    # callback from ShowManager when all shows have ended
    def all_shows_ended_callback(self,reason,message):
        self.canvas.config(bg=self.pp_background)
        if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True:
            self.end(reason,message)

    def end(self,reason,message):
        self.mon.log(self,"Pi Presents ending with reason: " + reason)
        if self.root is not None:
            self.root.destroy()
        self.tidy_up()
        # gc.collect()
        # print gc.garbage
        if reason == 'killed':
            self.mon.log(self, "Pi Presents Aborted, au revoir")
            # close logging files 
            self.mon.finish()
            sys.exit(101)     
        elif reason == 'error':
            self.mon.log(self, "Pi Presents closing because of error, sorry")
            # close logging files 
            self.mon.finish()
            sys.exit(102)            
        else:
            self.mon.log(self,"Pi Presents  exiting normally, bye")
            # close logging files 
            self.mon.finish()
            if self.shutdown_required is True:
                # print 'SHUTDOWN'
                call(['sudo', 'shutdown', '-h', '-t 5','now'])
                sys.exit(100)
            else:
                sys.exit(100)


    
    # tidy up all the peripheral bits of Pi Presents
    def tidy_up(self):
        self.mon.log(self, "Tidying Up")
        # turn screen blanking back on
        if self.options['noblank'] is True:
            call(["xset","s", "on"])
            call(["xset","s", "+dpms"])
            
        # tidy up animation and gpio
        if self.animate is not None:
            self.animate.terminate()
            
        if self.gpio_enabled==True:
            self.gpiodriver.terminate()

        if self.osc_enabled is True:
            self.oscdriver.terminate()
            
        # tidy up time of day scheduler
        if self.tod_enabled is True:
            self.tod.terminate()
Example #11
0
# plot a point
# import mathplotlib.pyplot as plt
from Tkinter import Tk, Canvas, PhotoImage, Label

if __name__ == '__main__':
    root = Tk()
    w = Label(root, text="Draw a Point on Canvas in Python")
    canvas = Canvas(root, width=250, height=250, bg='#E2E2E2')
    canvas.place(x=20, y=26, height=250, width=250)
    #img= PhotoImage(width=200, height=200)
    # img.putpixel(1,2)
    w.pack()
    canvas.pack()
    root.mainloop()
imgobj2 = query_image_canv.create_image(0, 0)

# Расположение всех выше указанных компонентов на форме
# (в относиельных координатах)
f_1.pack()
model_path_label.place(relx=0.01, rely=0.003)
model_path_entry.place(relx=0.01, rely=0.053)
open_model_button.place(relx=0.36, rely=0.051)
sensitivity_label.place(relx=0.02, rely=0.113)
sensitivity_entry.place(relx=0.01, rely=0.193)
num_of_parts_label.place(relx=0.25, rely=0.113)
num_of_parts_X_entry.place(relx=0.255, rely=0.193)
num_of_parts_Y_entry.place(relx=0.357, rely=0.193)
def_finding_button.place(relx=0.443, rely=0.5)
model_image_label.place(relx=0.12, rely=0.28)
model_image_canv.place(relx=0.01, rely=0.33)
query_image_label.place(relx=0.65, rely=0.28)
query_image_canv.place(relx=0.57, rely=0.33)
query_path_label.place(relx=0.55, rely=0.003)
query_path_entry.place(relx=0.55, rely=0.053)
open_query_button.place(relx=0.9, rely=0.051)
color_model_label.place(relx=0.55, rely=0.119)
hist_dim_label.place(relx=0.55, rely=0.169)
metric_label.place(relx=0.55, rely=0.219)
color_model_entry.place(relx=0.85, rely=0.119)
hist_dimension_entry.place(relx=0.85, rely=0.169)
metric_entry.place(relx=0.85, rely=0.219)

# Отображение формы
root.mainloop()
Example #13
0
class gui(Frame):
    """
    Class for the GUI drawing
    """

    __conf = globalConfig

    def __init__(self, parent):

        self.lbl_schlagwort = ""
        self.lbl_txt_wo = ""
        self.lbl_ekreuz = ""
        self.arrow_right = ""
        self.lbl_bem = ""
        self.arrow_left = ""
        self.lbl_version = ""
        self.cv_arrow_left = ""
        self.cv_arrow_right = ""
        self.lbl_estrasse = ""
        self.lbl_eobjekt = ""
        self.lbl_stichwort = ""
        self.einsatz = ""
        self.lbl_eort = ""


        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()
        self.update_clock()


    def initUI(self):
        """
        Initial setup the GUI
        """
        ### Font settings
        fnt = self.__conf.get_font_name()
        fntsize1 = self.__conf.get_font_size_1()
        fntsize2 = self.__conf.get_font_size_2()

        ### Window title
        self.parent.title("EDIS")

        self.pack(fill=BOTH, expand=1)
        # pylint: disable=W0201
        self.var = IntVar()

        ### GUI sections
        # pylint: disable=W0201
        self.canvas = Canvas(self, width =1024, height=768)
        self.canvas.create_rectangle(+5, +40, 1019, +180, outline='white', fill='gray80')    # Einsatzgrund
        self.canvas.create_rectangle(+5, +190, 1019, +500, outline='gray80', fill='white')    # Einsatzort
        self.canvas.create_rectangle(+5, +510, 1019, +760, outline='white', fill='gray80')    # Bemerkung
        self.canvas.place(x=0, y=0)


        #### GUI text objects
        # Version
        self.lbl_version = Label(self, text=self.__conf.get_version(), font=(fnt, fntsize1))
        self.lbl_version.place(x=420, y=0)

        # Strichwort
        self.lbl_stichwort = Label(self, text='<STICHWORT>', font=(fnt, fntsize2, "bold"), width=33, height=1, bg='gray80')
        self.lbl_stichwort.place(x=+10, y=+50)
        # Schlagwort
        self.lbl_schlagwort = Label(self, text='<SCHLAGWORT>', font=(fnt, fntsize2), width=34, height=1, bg='gray80')
        self.lbl_schlagwort.place(x=+10, y=+105)

        # Wo
        self.lbl_txt_wo = Label(self, text='Wo:', font=(fnt, fntsize2, "bold"), bg='white', anchor='nw')
        self.lbl_txt_wo.place(x=+10, y=+200)
        # Strasse
        self.lbl_estrasse = Label(self, text='<STRASSE>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw')
        self.lbl_estrasse.place(x=+90, y=+255)
        # Ort
        self.lbl_eort = Label(self, text='<ORT>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw')
        self.lbl_eort.place(x=+90, y=+310)
        # Objekt
        self.lbl_eobjekt = Label(self, text='<OBJEKT>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw')
        self.lbl_eobjekt.place(x=+90, y=+365)
        # Kreuzung
        self.lbl_ekreuz = Label(self, text='<KREUZUNG>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw')
        self.lbl_ekreuz.place(x=+90, y=+420)
        # Bemerkung
        self.lbl_bem = Label(self, text='<BEMERKUNG>', font=(fnt, fntsize2), bg='gray80', width=37, height=4,  anchor='nw', justify='left', wraplength=1000)
        self.lbl_bem.place(x=+10, y=+520)

        # Arrows
        imgpath = os.path.dirname(os.path.abspath(__file__))+"/../images/"
        self.arrow_left = ImageTk.PhotoImage(file=imgpath + "arrow_left.png")
        self.arrow_right = ImageTk.PhotoImage(file=imgpath + "arrow_right.png")

        self.cv_arrow_left = Canvas(self, width=46, height=46, bg='gray80', bd=0)
        self.cv_arrow_right = Canvas(self, width=46, height=46, bg='gray80', bd=0)

        self.cv_arrow_left.place(x=+6, y=+110)
        self.cv_arrow_right.place(x=970, y=+110)

        self.cv_arrow_left.create_image(25, 23, image=self.arrow_left)
        self.cv_arrow_right.create_image(23, 23, image=self.arrow_right)

    # pylint: disable=W0221
    def update(self, efile):
        self.einsatz = opp.opp(efile)
            
        # Clear all fields
        self.lbl_stichwort['text'] = ""
        self.lbl_schlagwort['text'] = ""
        self.lbl_txt_wo['text'] = ""
        self.lbl_estrasse['text'] = ""
        self.lbl_eort['text'] = ""
        self.lbl_eobjekt['text'] = ""
        self.lbl_ekreuz['text'] = ""
        self.lbl_bem['text'] = ""


        if self.einsatz.load():

            # Update with new data
            self.lbl_stichwort['text'] = self.einsatz.get_fld_egnd_stichw()
            if (self.einsatz.get_fld_egnd_stichw().find("THL") != -1):
                self.lbl_stichwort['bg'] = '#7777FF'
            elif (self.einsatz.get_fld_egnd_stichw().find("B") != -1):
                self.lbl_stichwort['bg'] = '#FF9999'
            elif (self.einsatz.get_fld_egnd_stichw().find("Unwetter") != -1):
                self.lbl_stichwort['bg'] = '#7777FF'
            else:
                self.lbl_stichwort['bg'] = 'gray50'


            self.lbl_schlagwort['text'] = self.einsatz.get_fld_egnd_schlagw()
            self.lbl_estrasse['text'] = self.einsatz.get_fld_eort_strasse() + ' ' + self.einsatz.get_fld_eort_hnummer()
            self.lbl_eort['text'] = self.einsatz.get_fld_eort_ort()
            self.lbl_eobjekt['text'] = self.einsatz.get_fld_eort_objekt()
            self.lbl_ekreuz['text'] = self.einsatz.get_fld_eort_kreuzung()
            self.lbl_bem['text'] = self.einsatz.get_fld_bem()


            # Show arrows

            fz_right = False
            fz_left = False

            for f in self.einsatz.get_lst_emittel():
                if get_close_matches(f, [self.__conf.get_vehicle_0()], 1, 0.9):
                    fz_right = True
                if get_close_matches(f, [self.__conf.get_vehicle_1()], 1, 0.9):
                    fz_left = True


            if (fz_left):
                self.cv_arrow_left.place(x=+6, y=+110)
            else:
                self.cv_arrow_left.place(x=-100, y=-100)

            if (fz_right):
                self.cv_arrow_right.place(x=970, y=+110)
            else:
                self.cv_arrow_right.place(x=-100, y=-100)



    def update_clock(self):
        """
        Update the clock timer
        """
        try:
            ocr_file = self.__conf.get_ocrpath()
            fd = open(ocr_file, "r")
        except:
            pass
        else:
            fd.close()
            self.update(ocr_file)

            ######## Archive
            if not os.path.exists(self.__conf.get_archive_path()):
                try:
                    log.debug("Archive does not exist! Try to create...")
                    os.mkdir(self.__conf.get_archive_path())
                    log.debug("Archive created")
                except:
                    log.error("Unable to operate with archive!")
            try:
                log.debug("Copy file to archive...")
                os.rename(ocr_file, self.__conf.get_archive_path() + '/' + strftime("%Y%m%d%H%M%S", gmtime()) + '.txt')
                log.debug("Copy to archive done!")
            except:
                log.error("Unable to write to archive!")

            #########

            ######### Activate screen
            xsrv = xhandler.xhandle()
            xret = 0

            xret += xsrv.test()
            xret += xsrv.unblank()
            xret += xsrv.set_timeout(self.__conf.get_scr_standby(), self.__conf.get_scr_suspend(), self.__conf.get_scr_off())

            if xret != 0:
                log.warn("Unblank of XServer failed!")

            #########

        self.after(1000, self.update_clock)
Example #14
0
class PiPresents(object):

    def pipresents_version(self):
        vitems=self.pipresents_issue.split('.')
        if len(vitems)==2:
            # cope with 2 digit version numbers before 1.3.2
            return 1000*int(vitems[0])+100*int(vitems[1])
        else:
            return 1000*int(vitems[0])+100*int(vitems[1])+int(vitems[2])


    def __init__(self):
        gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL)
        self.pipresents_issue="1.3.2"
        self.pipresents_minorissue = '1.3.2a'
        # position and size of window without -f command line option
        self.nonfull_window_width = 0.45 # proportion of width
        self.nonfull_window_height= 0.7 # proportion of height
        self.nonfull_window_x = 0 # position of top left corner
        self.nonfull_window_y=0   # position of top left corner


        StopWatch.global_enable=False

        # set up the handler for SIGTERM
        signal.signal(signal.SIGTERM,self.handle_sigterm)
        

# ****************************************
# Initialisation
# ***************************************
        # get command line options
        self.options=command_options()

        # get Pi Presents code directory
        pp_dir=sys.path[0]
        self.pp_dir=pp_dir
        
        if not os.path.exists(pp_dir+"/pipresents.py"):
            if self.options['manager']  is False:
                tkMessageBox.showwarning("Pi Presents","Bad Application Directory")
            exit(102)

        
        # Initialise logging and tracing
        Monitor.log_path=pp_dir
        self.mon=Monitor()
        # Init in PiPresents only
        self.mon.init()

        # uncomment to enable control of logging from within a class
        # Monitor.enable_in_code = True # enables control of log level in the code for a class  - self.mon.set_log_level()

        
        # make a shorter list to log/trace only some classes without using enable_in_code.
        Monitor.classes  = ['PiPresents',
                            
                            'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow',
                            'GapShow','Show','ArtShow',
                            'AudioPlayer','BrowserPlayer','ImagePlayer','MenuPlayer','MessagePlayer','VideoPlayer','Player',
                            'MediaList','LiveList','ShowList',
                            'PathManager','ControlsManager','ShowManager','PluginManager',
                            'MplayerDriver','OMXDriver','UZBLDriver',
                            'KbdDriver','GPIODriver','TimeOfDay','ScreenDriver','Animate','OSCDriver',
                            'Network','Mailer'
                            ]
        

        # Monitor.classes=['PiPresents','MediaShow','GapShow','Show','VideoPlayer','Player','OMXDriver']
        
        # get global log level from command line
        Monitor.log_level = int(self.options['debug'])
        Monitor.manager = self.options['manager']
        # print self.options['manager']
        self.mon.newline(3)
        self.mon.sched (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue + ' at '+time.strftime("%Y-%m-%d %H:%M.%S"))
        self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue+ ' at '+time.strftime("%Y-%m-%d %H:%M.%S"))
        # self.mon.log (self," OS and separator:" + os.name +'  ' + os.sep)
        self.mon.log(self,"sys.path[0] -  location of code: "+sys.path[0])

        # log versions of Raspbian and omxplayer, and GPU Memory
        with open("/boot/issue.txt") as file:
            self.mon.log(self,'\nRaspbian: '+file.read())

        self.mon.log(self,'\n'+check_output(["omxplayer", "-v"]))
        self.mon.log(self,'\nGPU Memory: '+check_output(["vcgencmd", "get_mem", "gpu"]))
        
        if "DESKTOP_SESSION" not in os.environ:
            print 'Pi Presents must be run from the Desktop'
            self.mon.log(self,'Pi Presents must be run from the Desktop')
            self.mon.finish()
            sys.exit(102)
        else:
            self.mon.log(self,'Desktop is '+ os.environ['DESKTOP_SESSION'])
        
        # optional other classes used
        self.root=None
        self.ppio=None
        self.tod=None
        self.animate=None
        self.gpiodriver=None
        self.oscdriver=None
        self.osc_enabled=False
        self.gpio_enabled=False
        self.tod_enabled=False
        self.email_enabled=False


        if os.geteuid() == 0:
            self.mon.err(self,'Do not run Pi Presents with sudo')
            self.end('error','Do not run Pi Presents with sudo')

        
        user=os.getenv('USER')

        self.mon.log(self,'User is: '+ user)
        # self.mon.log(self,"os.getenv('HOME') -  user home directory (not used): " + os.getenv('HOME')) # does not work
        # self.mon.log(self,"os.path.expanduser('~') -  user home directory: " + os.path.expanduser('~'))   # does not work



        # check network is available
        self.network_connected=False
        self.network_details=False
        self.interface=''
        self.ip=''
        self.unit=''
        
        # sets self.network_connected and self.network_details
        self.init_network()

        
        # start the mailer and send email when PP starts
        self.email_enabled=False
        if self.network_connected is True:
            self.init_mailer()
            if self.email_enabled is True and self.mailer.email_at_start is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Started on ' + time.strftime("%Y-%m-%d %H:%M")
                message = time.strftime("%Y-%m-%d %H:%M") + '\nUnit: ' + self.unit + '   Profile: '+ self.options['profile']+ '\n ' + self.interface + '\n ' + self.ip 
                self.send_email('start',subject,message) 

         
        # get profile path from -p option
        if self.options['profile'] != '':
            self.pp_profile_path="/pp_profiles/"+self.options['profile']
        else:
            self.mon.err(self,"Profile not specified in command ")
            self.end('error','Profile not specified with the commands -p option')
        
       # get directory containing pp_home from the command,
        if self.options['home']  == "":
            home = os.sep+ 'home' + os.sep + user + os.sep+"pp_home"
        else:
            home = self.options['home'] + os.sep+ "pp_home"         
        self.mon.log(self,"pp_home directory is: " + home)


        # check if pp_home exists.
        # try for 10 seconds to allow usb stick to automount
        found=False
        for i in range (1, 10):
            self.mon.log(self,"Trying pp_home at: " + home +  " (" + str(i)+')')
            if os.path.exists(home):
                found=True
                self.pp_home=home
                break
            time.sleep (1)
        if found is True:
            self.mon.log(self,"Found Requested Home Directory, using pp_home at: " + home)
        else:
            self.mon.err(self,"Failed to find pp_home directory at " + home)
            self.end('error',"Failed to find pp_home directory at " + home)


        # check profile exists
        self.pp_profile=self.pp_home+self.pp_profile_path
        if os.path.exists(self.pp_profile):
            self.mon.sched(self,"Running profile: " + self.pp_profile_path)
            self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile)
        else:
            self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile)
            self.end('error',"Failed to find requested profile: "+ self.pp_profile)

        self.mon.start_stats(self.options['profile'])
        
        if self.options['verify'] is True:
            val =Validator()
            if  val.validate_profile(None,pp_dir,self.pp_home,self.pp_profile,self.pipresents_issue,False) is  False:
                self.mon.err(self,"Validation Failed")
                self.end('error','Validation Failed')

         
        # initialise and read the showlist in the profile
        self.showlist=ShowList()
        self.showlist_file= self.pp_profile+ "/pp_showlist.json"
        if os.path.exists(self.showlist_file):
            self.showlist.open_json(self.showlist_file)
        else:
            self.mon.err(self,"showlist not found at "+self.showlist_file)
            self.end('error',"showlist not found at "+self.showlist_file)

        # check profile and Pi Presents issues are compatible
        if self.showlist.profile_version() != self.pipresents_version():
            self.mon.err(self,"Version of showlist " + self.showlist.profile_version_string + " is not  same as Pi Presents")
            self.end('error',"Version of showlist " + self.showlist.profile_version_string + " is not  same as Pi Presents")


        # get the 'start' show from the showlist
        index = self.showlist.index_of_show('start')
        if index >=0:
            self.showlist.select(index)
            self.starter_show=self.showlist.selected_show()
        else:
            self.mon.err(self,"Show [start] not found in showlist")
            self.end('error',"Show [start] not found in showlist")


# ********************
# SET UP THE GUI
# ********************
        # turn off the screenblanking and saver
        if self.options['noblank'] is True:
            call(["xset","s", "off"])
            call(["xset","s", "-dpms"])

        self.root=Tk()   
       
        self.title='Pi Presents - '+ self.pp_profile
        self.icon_text= 'Pi Presents'
        self.root.title(self.title)
        self.root.iconname(self.icon_text)
        self.root.config(bg=self.starter_show['background-colour'])

        self.mon.log(self, 'monitor screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixels')
        if self.options['screensize'] =='':        
            self.screen_width = self.root.winfo_screenwidth()
            self.screen_height = self.root.winfo_screenheight()
        else:
            reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize'])
            if reason =='error':
                self.mon.err(self,message)
                self.end('error',message)

        self.mon.log(self, 'forced screen dimensions (--screensize) are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixels')
       
        # set window dimensions and decorations
        if self.options['fullscreen'] is False:
            self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width)
            self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height)
            self.window_x=self.nonfull_window_x
            self.window_y=self.nonfull_window_y
            self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y))
        else:
            self.window_width=self.screen_width
            self.window_height=self.screen_height
            self.root.attributes('-fullscreen', True)
            os.system('unclutter &')
            self.window_x=0
            self.window_y=0  
            self.root.geometry("%dx%d%+d%+d"  % (self.window_width,self.window_height,self.window_x,self.window_y))
            self.root.attributes('-zoomed','1')

        # canvas cover the whole screen whatever the size of the window. 
        self.canvas_height=self.screen_height
        self.canvas_width=self.screen_width
  
        # make sure focus is set.
        self.root.focus_set()

        # define response to main window closing.
        self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort)

        # setup a canvas onto which will be drawn the images or text
        self.canvas = Canvas(self.root, bg=self.starter_show['background-colour'])


        if self.options['fullscreen'] is True:
            self.canvas.config(height=self.canvas_height,
                               width=self.canvas_width,
                               highlightthickness=0)
        else:
            self.canvas.config(height=self.canvas_height,
                    width=self.canvas_width,
                        highlightthickness=1,
                               highlightcolor='yellow')
            
        self.canvas.place(x=0,y=0)
        # self.canvas.config(bg='black')
        self.canvas.focus_set()


                
# ****************************************
# INITIALISE THE INPUT DRIVERS
# ****************************************

        # each driver takes a set of inputs, binds them to symboic names
        # and sets up a callback which returns the symbolic name when an input event occurs/

        # use keyboard driver to bind keys to symbolic names and to set up callback
        kbd=KbdDriver()
        if kbd.read(pp_dir,self.pp_home,self.pp_profile) is False:
            self.end('error','cannot find, or error in keys.cfg')
        kbd.bind_keys(self.root,self.handle_input_event)

        self.sr=ScreenDriver()
        # read the screen click area config file
        reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile)
        if reason == 'error':
            self.end('error','cannot find, or error in screen.cfg')


        # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes
        # click areas are made on the Pi Presents canvas not the show canvases.
        reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event)
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)


# ****************************************
# INITIALISE THE APPLICATION AND START
# ****************************************
        self.shutdown_required=False
        self.terminate_required=False
        self.exitpipresents_required=False

        # delete omxplayer dbus files
        # if os.path.exists("/tmp/omxplayerdbus.{}".format(user)):
            # os.remove("/tmp/omxplayerdbus.{}".format(user))
        # if os.path.exists("/tmp/omxplayerdbus.{}.pid".format(user)):
            # os.remove("/tmp/omxplayerdbus.{}.pid".format(user))
        
        # kick off GPIO if enabled by command line option
        self.gpio_enabled=False
        if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+os.sep+ 'gpio.cfg'):
            # initialise the GPIO
            self.gpiodriver=GPIODriver()
            reason,message=self.gpiodriver.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,50,self.handle_input_event)
            if reason == 'error':
                self.end('error',message)
            else:
                self.gpio_enabled=True
                # and start polling gpio
                self.gpiodriver.poll()
            
        # kick off animation sequencer
        self.animate = Animate()
        self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event)
        self.animate.poll()

        #create a showmanager ready for time of day scheduler and osc server
        show_id=-1
        self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home)
        # first time through set callback to terminate Pi Presents if all shows have ended.
        self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist)
        # Register all the shows in the showlist
        reason,message=self.show_manager.register_shows()
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)


        # Init OSCDriver, read config and start OSC server
        self.osc_enabled=False
        if self.network_connected is True:
            if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'):
                self.oscdriver=OSCDriver()
                reason,message=self.oscdriver.init(self.pp_profile,self.handle_command,self.handle_input_event,self.e_osc_handle_output_event)
                if reason == 'error':
                    self.mon.err(self,message)
                    self.end('error',message)
                else:
                    self.osc_enabled=True
                    self.root.after(1000,self.oscdriver.start_server())

        
        # enable ToD scheduler if schedule exists      
        if os.path.exists(self.pp_profile + os.sep + 'schedule.json'):                
            self.tod_enabled = True
        else:
            self.tod_enabled=False

        # warn if the network not available when ToD required

        if self.tod_enabled is True and self.network_connected is False:
            self.mon.warn(self,'Network not connected  so Time of Day scheduler may be using the internal clock')

        # warn about start shows and scheduler

        if self.starter_show['start-show']=='' and self.tod_enabled is False:
            self.mon.sched(self,"No Start Shows in Start Show and no shows scheduled") 
            self.mon.warn(self,"No Start Shows in Start Show and no shows scheduled")

        if self.starter_show['start-show'] !='' and self.tod_enabled is True:
            self.mon.sched(self,"Start Shows in Start Show and shows scheduled - conflict?") 
            self.mon.warn(self,"Start Shows in Start Show and shows scheduled - conflict?")

        # run the start shows
        self.run_start_shows()           

        # kick off the time of day scheduler which may run additional shows
        if self.tod_enabled is True:
            self.tod=TimeOfDay()
            self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.root,self.handle_command)
            self.tod.poll()            


        # start Tkinters event loop
        self.root.mainloop( )


    def parse_screen(self,size_text):
        fields=size_text.split('*')
        if len(fields)!=2:
            return 'error','do not understand --screensize comand option',0,0
        elif fields[0].isdigit()  is False or fields[1].isdigit()  is False:
            return 'error','dimensions are not positive integers in --screensize',0,0
        else:
            return 'normal','',int(fields[0]),int(fields[1])
        

# *********************
#  RUN START SHOWS
# ********************   
    def run_start_shows(self):
        self.mon.trace(self,'run start shows')
        # parse the start shows field and start the initial shows       
        show_refs=self.starter_show['start-show'].split()
        for show_ref in show_refs:
            reason,message=self.show_manager.control_a_show(show_ref,'open')
            if reason == 'error':
                self.mon.err(self,message)
                


# *********************
# User inputs
# ********************
    # handles one command provided as a line of text
    
    def handle_command(self,command_text,source='',show=''):
        # print 'PIPRESENTS ',command_text,source,'from',show
        self.mon.log(self,"command received: " + command_text)
        if command_text.strip()=="":
            return

        if command_text[0]=='/': 
            if self.osc_enabled is True:
                self.oscdriver.send_command(command_text)
            return
        
        fields= command_text.split()
        show_command=fields[0]
        if len(fields)>1:
            show_ref=fields[1]
        else:
            show_ref=''

        if show_command in ('open','close'):
            self.mon.sched(self, command_text + ' received from show:'+show)
            if self.shutdown_required is False and self.terminate_required is False:
                reason,message=self.show_manager.control_a_show(show_ref,show_command)
            else:
                return
        elif show_command =='monitor':
            self.handle_monitor_command(show_ref)
            return
        elif show_command == 'event':
            self.handle_input_event(show_ref,'Show Control')
            return
        elif show_command == 'exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to get out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            else:
                reason,message= self.show_manager.exit_all_shows()

        elif show_command == 'shutdownnow':
            # need root.after to get out of st thread
            self.root.after(1,self.e_shutdown_pressed)
            return
        else:
            reason='error'
            message = 'command not recognised: '+ show_command
            
        if reason=='error':
            self.mon.err(self,message)
        return


    def handle_monitor_command(self,command):
        if command == 'on':
            os.system('vcgencmd display_power 1 >/dev/null')
        elif command == 'off':
            os.system('vcgencmd display_power 0 >/dev/null')           
                      
    

    def e_all_shows_ended_callback(self):
        self.all_shows_ended_callback('normal','no shows running')

    def e_shutdown_pressed(self):
        self.shutdown_pressed('now')


    def e_osc_handle_output_event(self,line):
        #jump  out of server thread
        self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg))

    def  osc_handle_output_event(self,line):
        self.mon.log(self,"output event received: "+ line)
        #osc sends output events as a string
        reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line)
        if reason == 'error':
            self.mon.err(self,message)
            self.end(reason,message)
        self.handle_output_event(name,param_type,param_values,0)

               
    def handle_output_event(self,symbol,param_type,param_values,req_time):
        if self.gpio_enabled is True:
            reason,message=self.gpiodriver.handle_output_event(symbol,param_type,param_values,req_time)
            if reason =='error':
                self.mon.err(self,message)
                self.end(reason,message)
        else:
            self.mon.warn(self,'GPIO not enabled')


    # all input events call this callback with a symbolic name.
    # handle events that affect PP overall, otherwise pass to all active shows
    def handle_input_event(self,symbol,source):
        self.mon.log(self,"event received: "+symbol + ' from '+ source)
        if symbol == 'pp-terminate':
            self.handle_user_abort()
            
        elif symbol == 'pp-shutdown':
            self.shutdown_pressed('delay')
            
        elif symbol == 'pp-shutdownnow':
            # need root.after to grt out of st thread
            self.root.after(1,self.e_shutdown_pressed)
            return
        
        elif symbol == 'pp-exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to grt out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            reason,message= self.show_manager.exit_all_shows()
        else:
            # events for shows affect the show and could cause it to exit.
            for show in self.show_manager.shows:
                show_obj=show[ShowManager.SHOW_OBJ]
                if show_obj is not None:
                    show_obj.handle_input_event(symbol)



    def shutdown_pressed(self, when):
        if when == 'delay':
            self.root.after(5000,self.on_shutdown_delay)
        else:
            self.shutdown_required=True
            if self.show_manager.all_shows_exited() is True:
               self.all_shows_ended_callback('normal','no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()           


    def on_shutdown_delay(self):
        # 5 second delay is up, if shutdown button still pressed then shutdown
        if self.gpiodriver.shutdown_pressed() is True:
            self.shutdown_required=True
            if self.show_manager.all_shows_exited() is True:
               self.all_shows_ended_callback('normal','no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()


    def handle_sigterm(self,signum,frame):
        self.mon.log(self,'SIGTERM received - '+ str(signum))
        self.terminate()


    def handle_user_abort(self):
        self.mon.log(self,'User abort received')
        self.terminate()

    def terminate(self):
        self.mon.log(self, "terminate received")
        self.terminate_required=True
        needs_termination=False
        for show in self.show_manager.shows:
            # print  show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF]
            if show[ShowManager.SHOW_OBJ] is not None:
                needs_termination=True
                self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF])
                # call shows terminate method
                # eventually the show will exit and after all shows have exited all_shows_callback will be executed.
                show[ShowManager.SHOW_OBJ].terminate()
        if needs_termination is False:
            self.end('killed','killed - no termination of shows required')


# ******************************
# Ending Pi Presents after all the showers and players are closed
# **************************

    # callback from ShowManager when all shows have ended
    def all_shows_ended_callback(self,reason,message):
        self.canvas.config(bg=self.starter_show['background-colour'])
        if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True:
            self.end(reason,message)

    def end(self,reason,message):
        self.mon.log(self,"Pi Presents ending with reason: " + reason)
        if self.root is not None:
            self.root.destroy()
        self.tidy_up()
        # gc.collect()
        # print gc.garbage
        if reason == 'killed':
            if self.email_enabled is True and self.mailer.email_on_terminate is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Terminated'
                message = time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip 
                self.send_email(reason,subject,message)
            self.mon.sched(self, "Pi Presents Terminated, au revoir\n")
            self.mon.log(self, "Pi Presents Terminated, au revoir")
                          
            # close logging files 
            self.mon.finish()
            sys.exit(101)
                          
        elif reason == 'error':
            if self.email_enabled is True and self.mailer.email_on_error is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Error'
                message_text = 'Error message: '+ message + '\n'+ time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip 
                self.send_email(reason,subject,message_text)   
            self.mon.sched(self, "Pi Presents closing because of error, sorry\n")
            self.mon.log(self, "Pi Presents closing because of error, sorry")
                          
            # close logging files 
            self.mon.finish()
            sys.exit(102)

        else:           
            self.mon.sched(self,"Pi Presents  exiting normally, bye\n")
            self.mon.log(self,"Pi Presents  exiting normally, bye")
            
            # close logging files 
            self.mon.finish()
            if self.shutdown_required is True:
                # print 'SHUTDOWN'
                call (['sudo','shutdown','now','SHUTTING DOWN'])
            sys.exit(100)



    def init_network(self):

        timeout=int(self.options['nonetwork'])
        if timeout== 0:
            self.network_connected=False
            self.unit=''
            self.ip=''
            self.interface=''
            return
        
        self.network=Network()
        self.network_connected=False

        # try to connect to network
        self.mon.log (self, 'Waiting up to '+ str(timeout) + ' seconds for network')
        success=self.network.wait_for_network(timeout)
        if success is False:
            self.mon.warn(self,'Failed to connect to network after ' + str(timeout) + ' seconds')
            # tkMessageBox.showwarning("Pi Presents","Failed to connect to network so using fake-hwclock")
            return

        self.network_connected=True
        self.mon.sched (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S"))
        self.mon.log (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S"))

        # Get web configuration
        self.network_details=False
        network_options_file_path=self.pp_dir+os.sep+'pp_config'+os.sep+'pp_web.cfg'
        if not os.path.exists(network_options_file_path):
            self.mon.warn(self,"pp_web.cfg not found at "+network_options_file_path)
            return
        self.mon.log(self, 'Found pp_web.cfg in ' + network_options_file_path)

        self.network.read_config(network_options_file_path)
        self.unit=self.network.unit

        # get interface and IP details of preferred interface
        self.interface,self.ip = self.network.get_preferred_ip()
        if self.interface == '':
            self.network_connected=False
            return
        self.network_details=True
        self.mon.log (self, 'Network details ' + self.unit + ' ' + self.interface + ' ' +self.ip)


    def init_mailer(self):

        self.email_enabled=False
        email_file_path = self.pp_dir+os.sep+'pp_config'+os.sep+'pp_email.cfg'
        if not os.path.exists(email_file_path):
            self.mon.log(self,'pp_email.cfg not found at ' + email_file_path)
            return
        self.mon.log(self,'Found pp_email.cfg at ' + email_file_path)
        self.mailer=Mailer()
        self.mailer.read_config(email_file_path)
        # all Ok so can enable email if config file allows it.
        if self.mailer.email_allowed is True:
            self.email_enabled=True
            self.mon.log (self,'Email Enabled')



    def send_email(self,reason,subject,message):
        if self.try_connect() is False:
            return False
        else:
            success,error = self.mailer.send(subject,message)
            if success is False:
                self.mon.log(self, 'Failed to send email: ' + str(error))
                success,error=self.mailer.disconnect()
                if success is False:
                    self.mon.log(self,'Failed disconnect after send:' + str(error))
                return False
            else:
                self.mon.log(self,'Sent email for ' + reason)
                success,error=self.mailer.disconnect()
                if success is False:
                    self.mon.log(self,'Failed disconnect from email server ' + str(error))
                return True


    def try_connect(self):
        tries=1
        while True:
            success, error = self.mailer.connect()
            if success is True:
                return True
            else:
                self.mon.log(self,'Failed to connect to email SMTP server ' + str(tries) +  '\n ' +str(error))
                tries +=1
                if tries >5:
                    self.mon.log(self,'Failed to connect to email SMTP server after ' + str(tries))
                    return False

                
    
    # tidy up all the peripheral bits of Pi Presents
    def tidy_up(self):
        self.handle_monitor_command('on')
        self.mon.log(self, "Tidying Up")
        # turn screen blanking back on
        if self.options['noblank'] is True:
            call(["xset","s", "on"])
            call(["xset","s", "+dpms"])
            
        # tidy up animation and gpio
        if self.animate is not None:
            self.animate.terminate()
            
        if self.gpio_enabled==True:
            self.gpiodriver.terminate()

        if self.osc_enabled is True:
            self.oscdriver.terminate()
            
        # tidy up time of day scheduler
        if self.tod_enabled is True:
            self.tod.terminate()
class PiPresents(object):
    def __init__(self):
        gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES
                     | gc.DEBUG_OBJECTS | gc.DEBUG_SAVEALL)
        self.pipresents_issue = "1.3"
        self.pipresents_minorissue = '1.3.1g'
        # position and size of window without -f command line option
        self.nonfull_window_width = 0.45  # proportion of width
        self.nonfull_window_height = 0.7  # proportion of height
        self.nonfull_window_x = 0  # position of top left corner
        self.nonfull_window_y = 0  # position of top left corner
        self.pp_background = 'black'

        StopWatch.global_enable = False

        # set up the handler for SIGTERM
        signal.signal(signal.SIGTERM, self.handle_sigterm)

        # ****************************************
        # Initialisation
        # ***************************************
        # get command line options
        self.options = command_options()

        # get Pi Presents code directory
        pp_dir = sys.path[0]
        self.pp_dir = pp_dir

        if not os.path.exists(pp_dir + "/pipresents.py"):
            if self.options['manager'] is False:
                tkMessageBox.showwarning(
                    "Pi Presents",
                    "Bad Application Directory:\n{0}".format(pp_dir))
            exit(103)

        # Initialise logging and tracing
        Monitor.log_path = pp_dir
        self.mon = Monitor()
        # Init in PiPresents only
        self.mon.init()

        # uncomment to enable control of logging from within a class
        # Monitor.enable_in_code = True # enables control of log level in the code for a class  - self.mon.set_log_level()

        # make a shorter list to log/trace only some classes without using enable_in_code.
        Monitor.classes = [
            'PiPresents', 'pp_paths', 'HyperlinkShow', 'RadioButtonShow',
            'ArtLiveShow', 'ArtMediaShow', 'MediaShow', 'LiveShow', 'MenuShow',
            'PathManager', 'ControlsManager', 'ShowManager', 'PluginManager',
            'MplayerDriver', 'OMXDriver', 'UZBLDriver', 'KbdDriver',
            'GPIODriver', 'TimeOfDay', 'ScreenDriver', 'Animate', 'OSCDriver'
        ]

        # Monitor.classes=['PiPresents','ArtMediaShow','VideoPlayer','OMXDriver']

        # get global log level from command line
        Monitor.log_level = int(self.options['debug'])
        Monitor.manager = self.options['manager']
        # print self.options['manager']
        self.mon.newline(3)
        self.mon.log(
            self,
            "Pi Presents is starting, Version:" + self.pipresents_minorissue)
        # self.mon.log (self," OS and separator:" + os.name +'  ' + os.sep)
        self.mon.log(self, "sys.path[0] -  location of code: " + sys.path[0])
        if os.geteuid() != 0:
            user = os.getenv('USER')
        else:
            user = os.getenv('SUDO_USER')
        self.mon.log(self, 'User is: ' + user)
        # self.mon.log(self,"os.getenv('HOME') -  user home directory (not used): " + os.getenv('HOME')) # does not work
        # self.mon.log(self,"os.path.expanduser('~') -  user home directory: " + os.path.expanduser('~'))   # does not work

        # optional other classes used
        self.root = None
        self.ppio = None
        self.tod = None
        self.animate = None
        self.gpiodriver = None
        self.oscdriver = None
        self.osc_enabled = False
        self.gpio_enabled = False
        self.tod_enabled = False

        # get home path from -o option
        self.pp_home = pp_paths.get_home(self.options['home'])
        if self.pp_home is None:
            self.end('error', 'Failed to find pp_home')

        # get profile path from -p option
        # pp_profile is the full path to the directory that contains
        # pp_showlist.json and other files for the profile
        self.pp_profile = pp_paths.get_profile_dir(self.pp_home,
                                                   self.options['profile'])
        if self.pp_profile is None:
            self.end('error', 'Failed to find profile')

        # check profile exists
        if os.path.exists(self.pp_profile):
            self.mon.log(
                self, "Found Requested profile - pp_profile directory is: " +
                self.pp_profile)
        else:
            self.mon.err(
                self, "Failed to find requested profile: " + self.pp_profile)
            self.end('error', 'Failed to find profile')

        self.mon.start_stats(self.options['profile'])

        # check 'verify' option
        if self.options['verify'] is True:
            val = Validator()
            if val.validate_profile(None, pp_dir, self.pp_home,
                                    self.pp_profile, self.pipresents_issue,
                                    False) is False:
                self.mon.err(self, "Validation Failed")
                self.end('error', 'Validation Failed')

        # initialise and read the showlist in the profile
        self.showlist = ShowList()
        self.showlist_file = self.pp_profile + "/pp_showlist.json"
        if os.path.exists(self.showlist_file):
            self.showlist.open_json(self.showlist_file)
        else:
            self.mon.err(self, "showlist not found at " + self.showlist_file)
            self.end('error', 'showlist not found')

        # check profile and Pi Presents issues are compatible
        if float(self.showlist.sissue()) != float(self.pipresents_issue):
            self.mon.err(
                self, "Version of profile " + self.showlist.sissue() +
                " is not  same as Pi Presents, must exit")
            self.end('error', 'wrong version of profile')

        # get the 'start' show from the showlist
        index = self.showlist.index_of_show('start')
        if index >= 0:
            self.showlist.select(index)
            self.starter_show = self.showlist.selected_show()
        else:
            self.mon.err(self, "Show [start] not found in showlist")
            self.end('error', 'start show not found')

        if self.starter_show['start-show'] == '':
            self.mon.warn(self, "No Start Shows in Start Show")

# ********************
# SET UP THE GUI
# ********************
# turn off the screenblanking and saver
        if self.options['noblank'] is True:
            call(["xset", "s", "off"])
            call(["xset", "s", "-dpms"])

        self.root = Tk()

        self.title = 'Pi Presents - ' + self.pp_profile
        self.icon_text = 'Pi Presents'
        self.root.title(self.title)
        self.root.iconname(self.icon_text)
        self.root.config(bg=self.pp_background)

        self.mon.log(
            self, 'native screen dimensions are ' +
            str(self.root.winfo_screenwidth()) + ' x ' +
            str(self.root.winfo_screenheight()) + ' pixcels')
        if self.options['screensize'] == '':
            self.screen_width = self.root.winfo_screenwidth()
            self.screen_height = self.root.winfo_screenheight()
        else:
            reason, message, self.screen_width, self.screen_height = self.parse_screen(
                self.options['screensize'])
            if reason == 'error':
                self.mon.err(self, message)
                self.end('error', message)

        self.mon.log(
            self, 'commanded screen dimensions are ' + str(self.screen_width) +
            ' x ' + str(self.screen_height) + ' pixcels')

        # set window dimensions and decorations
        if self.options['fullscreen'] is False:
            self.window_width = int(self.root.winfo_screenwidth() *
                                    self.nonfull_window_width)
            self.window_height = int(self.root.winfo_screenheight() *
                                     self.nonfull_window_height)
            self.window_x = self.nonfull_window_x
            self.window_y = self.nonfull_window_y
            self.root.geometry("%dx%d%+d%+d" %
                               (self.window_width, self.window_height,
                                self.window_x, self.window_y))
        else:
            self.window_width = self.screen_width
            self.window_height = self.screen_height
            self.root.attributes('-fullscreen', True)
            os.system(
                'unclutter 1>&- 2>&- &'
            )  # Suppress 'someone created a subwindow' complaints from unclutter
            self.window_x = 0
            self.window_y = 0
            self.root.geometry("%dx%d%+d%+d" %
                               (self.window_width, self.window_height,
                                self.window_x, self.window_y))
            self.root.attributes('-zoomed', '1')

        # canvs cover the whole screen whatever the size of the window.
        self.canvas_height = self.screen_height
        self.canvas_width = self.screen_width

        # make sure focus is set.
        self.root.focus_set()

        # define response to main window closing.
        self.root.protocol("WM_DELETE_WINDOW", self.handle_user_abort)

        # setup a canvas onto which will be drawn the images or text
        self.canvas = Canvas(self.root, bg=self.pp_background)

        if self.options['fullscreen'] is True:
            self.canvas.config(height=self.canvas_height,
                               width=self.canvas_width,
                               highlightthickness=0)
        else:
            self.canvas.config(height=self.canvas_height,
                               width=self.canvas_width,
                               highlightthickness=1,
                               highlightcolor='yellow')

        self.canvas.place(x=0, y=0)
        # self.canvas.config(bg='black')
        self.canvas.focus_set()

        # ****************************************
        # INITIALISE THE INPUT DRIVERS
        # ****************************************

        # each driver takes a set of inputs, binds them to symboic names
        # and sets up a callback which returns the symbolic name when an input event occurs/

        # use keyboard driver to bind keys to symbolic names and to set up callback
        kbd = KbdDriver()
        if kbd.read(pp_dir, self.pp_home, self.pp_profile) is False:
            self.end('error', 'cannot find or error in keys.cfg')
        kbd.bind_keys(self.root, self.handle_input_event)

        self.sr = ScreenDriver()
        # read the screen click area config file
        reason, message = self.sr.read(pp_dir, self.pp_home, self.pp_profile)
        if reason == 'error':
            self.end('error', 'cannot find screen.cfg')

        # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes
        # click areas are made on the Pi Presents canvas not the show canvases.
        reason, message = self.sr.make_click_areas(self.canvas,
                                                   self.handle_input_event)
        if reason == 'error':
            self.mon.err(self, message)
            self.end('error', message)

# ****************************************
# INITIALISE THE APPLICATION AND START
# ****************************************
        self.shutdown_required = False
        self.exitpipresents_required = False

        # kick off GPIO if enabled by command line option
        self.gpio_enabled = False
        if os.path.exists(self.pp_profile + os.sep + 'pp_io_config' + os.sep +
                          'gpio.cfg'):
            # initialise the GPIO
            self.gpiodriver = GPIODriver()
            reason, message = self.gpiodriver.init(pp_dir, self.pp_home,
                                                   self.pp_profile,
                                                   self.canvas, 50,
                                                   self.handle_input_event)
            if reason == 'error':
                self.end('error', message)
            else:
                self.gpio_enabled = True
                # and start polling gpio
                self.gpiodriver.poll()

        # kick off animation sequencer
        self.animate = Animate()
        self.animate.init(pp_dir, self.pp_home, self.pp_profile, self.canvas,
                          200, self.handle_output_event)
        self.animate.poll()

        #create a showmanager ready for time of day scheduler and osc server
        show_id = -1
        self.show_manager = ShowManager(show_id, self.showlist,
                                        self.starter_show, self.root,
                                        self.canvas, self.pp_dir,
                                        self.pp_profile, self.pp_home)
        # first time through set callback to terminate Pi Presents if all shows have ended.
        self.show_manager.init(self.canvas, self.all_shows_ended_callback,
                               self.handle_command, self.showlist)
        # Register all the shows in the showlist
        reason, message = self.show_manager.register_shows()
        if reason == 'error':
            self.mon.err(self, message)
            self.end('error', message)

        # Init OSCDriver, read config and start OSC server
        self.osc_enabled = False
        if os.path.exists(self.pp_profile + os.sep + 'pp_io_config' + os.sep +
                          'osc.cfg'):
            self.oscdriver = OSCDriver()
            reason, message = self.oscdriver.init(
                self.pp_profile, self.handle_command, self.handle_input_event,
                self.e_osc_handle_output_event)
            if reason == 'error':
                self.end('error', message)
            else:
                self.osc_enabled = True
                self.root.after(1000, self.oscdriver.start_server())

        # and run the start shows
        self.run_start_shows()

        # set up the time of day scheduler including catchup
        self.tod_enabled = False
        if os.path.exists(self.pp_profile + os.sep + 'schedule.json'):
            # kick off the time of day scheduler which may run additional shows
            self.tod = TimeOfDay()
            self.tod.init(pp_dir, self.pp_home, self.pp_profile, self.root,
                          self.handle_command)
            self.tod_enabled = True

        # then start the time of day scheduler
        if self.tod_enabled is True:
            self.tod.poll()

        # start Tkinters event loop
        self.root.mainloop()

    def parse_screen(self, size_text):
        fields = size_text.split('*')
        if len(fields) != 2:
            return 'error', 'do not understand --fullscreen comand option', 0, 0
        elif fields[0].isdigit() is False or fields[1].isdigit() is False:
            return 'error', 'dimensions are not positive integers in ---fullscreen', 0, 0
        else:
            return 'normal', '', int(fields[0]), int(fields[1])

# *********************
#  RUN START SHOWS
# ********************

    def run_start_shows(self):
        self.mon.trace(self, 'run start shows')
        # parse the start shows field and start the initial shows
        show_refs = self.starter_show['start-show'].split()
        for show_ref in show_refs:
            reason, message = self.show_manager.control_a_show(
                show_ref, 'open')
            if reason == 'error':
                self.mon.err(self, message)

# *********************
# User inputs
# ********************
# handles one command provided as a line of text

    def handle_command(self, command_text):
        self.mon.log(self, "command received: " + command_text)
        if command_text.strip() == "":
            return

        if command_text[0] == '/':
            if self.osc_enabled is True:
                self.oscdriver.send_command(command_text)
            return

        fields = command_text.split()
        show_command = fields[0]
        if len(fields) > 1:
            show_ref = fields[1]
        else:
            show_ref = ''

        if show_command in ('open', 'close'):
            if self.shutdown_required is False:
                reason, message = self.show_manager.control_a_show(
                    show_ref, show_command)
            else:
                return
        elif show_command == 'exitpipresents':
            self.exitpipresents_required = True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to get out of st thread
                self.root.after(1, self.e_all_shows_ended_callback)
                return
            else:
                reason, message = self.show_manager.exit_all_shows()

        elif show_command == 'shutdownnow':
            # need root.after to get out of st thread
            self.root.after(1, self.e_shutdown_pressed)
            return
        else:
            reason = 'error'
            message = 'command not recognised: ' + show_command

        if reason == 'error':
            self.mon.err(self, message)
        return

    def e_all_shows_ended_callback(self):
        self.all_shows_ended_callback('normal', 'no shows running')

    def e_shutdown_pressed(self):
        self.shutdown_pressed('now')

    def e_osc_handle_output_event(self, line):
        #jump  out of server thread
        self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg))

    def osc_handle_output_event(self, line):
        self.mon.log(self, "output event received: " + line)
        #osc sends output events as a string
        reason, message, delay, name, param_type, param_values = self.animate.parse_animate_fields(
            line)
        if reason == 'error':
            self.mon.err(self, message)
            self.end(reason, message)
        self.handle_output_event(name, param_type, param_values, 0)

    def handle_output_event(self, symbol, param_type, param_values, req_time):
        if self.gpio_enabled is True:
            reason, message = self.gpiodriver.handle_output_event(
                symbol, param_type, param_values, req_time)
            if reason == 'error':
                self.mon.err(self, message)
                self.end(reason, message)
        else:
            self.mon.warn(self, 'GPIO not enabled')

    # all input events call this callback with a symbolic name.
    # handle events that affect PP overall, otherwise pass to all active shows
    def handle_input_event(self, symbol, source):
        self.mon.log(self, "event received: " + symbol + ' from ' + source)
        if symbol == 'pp-terminate':
            self.handle_user_abort()

        elif symbol == 'pp-shutdown':
            self.shutdown_pressed('delay')

        elif symbol == 'pp-shutdownnow':
            # need root.after to grt out of st thread
            self.root.after(1, self.e_shutdown_pressed)
            return

        elif symbol == 'pp-exitpipresents':
            self.exitpipresents_required = True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to grt out of st thread
                self.root.after(1, self.e_all_shows_ended_callback)
                return
            reason, message = self.show_manager.exit_all_shows()
        else:
            # events for shows affect the show and could cause it to exit.
            for show in self.show_manager.shows:
                show_obj = show[ShowManager.SHOW_OBJ]
                if show_obj is not None:
                    show_obj.handle_input_event(symbol)

    def shutdown_pressed(self, when):
        if when == 'delay':
            self.root.after(5000, self.on_shutdown_delay)
        else:
            self.shutdown_required = True
            if self.show_manager.all_shows_exited() is True:
                self.all_shows_ended_callback('normal', 'no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()

    def on_shutdown_delay(self):
        # 5 second delay is up, if shutdown button still pressed then shutdown
        if self.gpiodriver.shutdown_pressed() is True:
            self.shutdown_required = True
            if self.show_manager.all_shows_exited() is True:
                self.all_shows_ended_callback('normal', 'no shows running')
            else:
                # calls exit method of all shows, results in all_shows_closed_callback
                self.show_manager.exit_all_shows()

    def handle_sigterm(self, signum, frame):
        self.mon.log(self, 'SIGTERM received - ' + str(signum))
        self.terminate()

    def handle_user_abort(self):
        self.mon.log(self, 'User abort received')
        self.terminate()

    def terminate(self):
        self.mon.log(self, "terminate received")
        needs_termination = False
        for show in self.show_manager.shows:
            # print  show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF]
            if show[ShowManager.SHOW_OBJ] is not None:
                needs_termination = True
                self.mon.log(
                    self,
                    "Sent terminate to show " + show[ShowManager.SHOW_REF])
                # call shows terminate method
                # eventually the show will exit and after all shows have exited all_shows_callback will be executed.
                show[ShowManager.SHOW_OBJ].terminate()
        if needs_termination is False:
            self.end('killed', 'killed - no termination of shows required')


# ******************************
# Ending Pi Presents after all the showers and players are closed
# **************************

# callback from ShowManager when all shows have ended

    def all_shows_ended_callback(self, reason, message):
        self.canvas.config(bg=self.pp_background)
        if reason in (
                'killed', 'error'
        ) or self.shutdown_required is True or self.exitpipresents_required is True:
            self.end(reason, message)

    def end(self, reason, message):
        self.mon.log(self, "Pi Presents ending with reason: " + reason)
        if self.root is not None:
            self.root.destroy()
        self.tidy_up()
        # gc.collect()
        # print gc.garbage
        if reason == 'killed':
            self.mon.log(self, "Pi Presents Aborted, au revoir")
            # close logging files
            self.mon.finish()
            sys.exit(101)
        elif reason == 'error':
            self.mon.log(self, "Pi Presents closing because of error, sorry")
            # close logging files
            self.mon.finish()
            sys.exit(102)
        else:
            self.mon.log(self, "Pi Presents  exiting normally, bye")
            # close logging files
            self.mon.finish()
            if self.shutdown_required is True:
                # print 'SHUTDOWN'
                call(['sudo', 'shutdown', '-h', '-t 5', 'now'])
                sys.exit(100)
            else:
                sys.exit(100)

    # tidy up all the peripheral bits of Pi Presents
    def tidy_up(self):
        self.mon.log(self, "Tidying Up")
        # turn screen blanking back on
        if self.options['noblank'] is True:
            call(["xset", "s", "on"])
            call(["xset", "s", "+dpms"])

        # tidy up animation and gpio
        if self.animate is not None:
            self.animate.terminate()

        if self.gpio_enabled == True:
            self.gpiodriver.terminate()

        if self.osc_enabled is True:
            self.oscdriver.terminate()

        # tidy up time of day scheduler
        if self.tod_enabled is True:
            self.tod.terminate()
Example #16
0
class calculadora(object):
    def __init__(self):

        # DEFINIR VARIABLES GENERALES
        self.maxprec = 20000  # Precision numérica de la calculadora - Dev:1000, Prd: 20000
        self.debuguear = 1  # Debug. Muestra en pantalla lo que se envia al display
        self.sendToDisplay = 0  # Enviar dígitos a Display (on/off)
        self.ard_comm = 'COM3'  # Serial com port, debe coincidir con los baudios y el puerto arduino
        self.ard_baud = 9600  # Serial baud rate, debe coincidir con los baudios y el puerto arduino
        self.ard_tiot = 0.1  # Serial timeout 100ms, testeado con arduino UNO
        self.fullscreen = 0  # Abrir en pantalla completa. Dev: 0, Prd: 1
        self.ultrawidescreen = 0  # Monitor UltraWideScreen

    def iniciar(self, master):
        ######### VARIABLES GENERALES #########
        # Velocidad (lista de velocidades en milisegundos)
        self.velist = [1000, 700, 500, 400, 300, 200, 150, 100]
        self.velmax = len(self.velist) - 1
        self.vel = -1
        self.memvel = 0

        # Debug
        self.porcionlen = 70  # Porcion a mostrar
        self.porcion = ''
        self.playsounds = 0  # VERSION DE PRUEBA!!
        self.playwaves = 1  # VERSION DE PRUEBA!!

        #Arduino COMM (Display)
        if self.sendToDisplay > 0:
            # debe coincidir con los baudios y el puerto arduino
            self.arduino = serial.Serial(self.ard_comm,
                                         self.ard_baud,
                                         timeout=self.ard_tiot)
            time.sleep(1)
            if self.sendToDisplay > 0:
                self.arduino.write('N')  # RESET DYSPLAY
                time.sleep(1)

        # nsp class
        self.nsp = NumericStringParser()
        self.nsp.setPresicion(self.maxprec)  #Set presicion

        # Contador de envio a Arduino
        self.resultadoAduino = ''
        self.resultadoNormal = ''
        self.contador = -1
        self._job = None

        #######################################
        if self.playwaves > 0:
            p = mu.pyaudio.PyAudio()

            self.stream = p.open(format=mu.pyaudio.paFloat32,
                                 channels=mu.CHANNELS,
                                 rate=mu.RATE,
                                 output=True,
                                 stream_callback=mu.callback)

            self.stream.stop_stream()
        #######################################

        self.master = master
        if self.fullscreen > 0:
            # Full screen
            master.overrideredirect(True)
            master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(),
                                                 root.winfo_screenheight()))
            master.focus_set()  # <-- move focus to this widget
            # Otra opción
            # master.attributes('-fullscreen', True)
        else:
            master.geometry("%dx%d+0+0" % (master.winfo_screenwidth() - 16,
                                           master.winfo_screenheight() - 80))

        master.title("Calculadora")

        master.bind("<Escape>", lambda e: e.widget.quit())  # Python 2
        master.bind("<Key>", self.recibeChar)

        self.dondestoy = 'p'

        # Dividendo p
        self.dividendostr = ""
        self.dividendo = StringVar()
        self.dividendo.set(self.dividendostr)
        if self.ultrawidescreen > 0:
            # UltraWide Screen
            self.labelp = Label(master,
                                textvariable=self.dividendo,
                                bg="#fd0",
                                width=18,
                                justify="center",
                                font=("Roboto", 192))
        else:
            # 16:9 Screen
            self.labelp = Label(master,
                                textvariable=self.dividendo,
                                bg="#fd0",
                                width=21,
                                justify="center",
                                font=("Roboto", 96))

        self.line = Canvas(master, width=master.winfo_screenwidth(), height=50)
        # self.line.create_rectangle(0, 0, master.winfo_screenwidth(), 20, outline="#000", fill="#000")
        self.line.create_line(0,
                              0,
                              master.winfo_screenwidth(),
                              0,
                              fill="#000",
                              width=50)

        # Divisor q
        self.divisorstr = "1"
        self.divisor = StringVar()
        self.divisor.set(self.divisorstr)
        if self.ultrawidescreen > 0:
            # UltraWide Screen
            self.labelq = Label(master,
                                textvariable=self.divisor,
                                bg="#eee",
                                fg="#aaa",
                                width=18,
                                justify="center",
                                font=("Roboto", 192))
        else:
            # 16:9 Screen
            self.labelq = Label(master,
                                textvariable=self.divisor,
                                bg="#eee",
                                fg="#aaa",
                                width=21,
                                justify="center",
                                font=("Roboto", 96))

        # Resultado res
        self.resultastr = ""
        self.resulta = StringVar()
        self.resulta.set(self.resultastr)
        if self.ultrawidescreen > 0:
            # UltraWide Screen
            self.labelr = Label(master,
                                textvariable=self.resulta,
                                bg="#eee",
                                width=213,
                                justify="left",
                                font=("Roboto", 16))
        else:
            # 16:9 Screen
            self.labelr = Label(master,
                                textvariable=self.resulta,
                                bg="#eee",
                                width=120,
                                justify="left",
                                font=("Roboto", 16))

        # Posiciona
        self.line.place(relx=0, rely=.495)
        self.labelp.place(relx=0, rely=.22)
        self.labelq.place(relx=0, rely=.545)
        self.labelr.place(relx=0, rely=.80)

        # init timer de envio a arduino
        # self.onUpdate()

        #######################################
    def filtrar(self, s):
        if '.' in s:
            r = {
                '1': 'A',
                '2': 'B',
                '3': 'C',
                '4': 'D',
                '5': 'E',
                '6': 'F',
                '7': 'G',
                '8': 'H',
                '9': 'I',
                '0': 'J'
            }
            s = s.split('.')
            c = s[0][-1:]
            s[0] = s[0][0:-1]
            return s[0] + r[c] + s[1]
        else:
            return s

    def modcad(self, cad, c):
        cad = cad.decode('utf-8')
        p = cad[-1:]
        if isinstance(c, int):
            if (len(cad) >= c):
                cad = cad[:-c]
        else:
            c = c.decode('utf-8')
            cad = cad + c
        cad = cad.encode('utf-8')
        return cad

    def recibeChar(self, event):
        k = event.keycode
        c = event.char
        p = str(self.dividendostr)
        q = str(self.divisorstr)

        # # Test input del teclado
        # self.resultastr = c+': ',str(k)+': '+str(event.state)
        # self.resulta.set(self.resultastr)
        # return

        if self.debuguear == 0:
            self.resultastr = ''
            self.resulta.set(self.resultastr)

        numrs = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        if (self.dondestoy == 'q'):
            cadena = q
            # if cadena=='1':
            #     cadena = ''
        else:
            cadena = p
        # SALIDAS
        if c == 'c':  # c
            # reiniciar programa
            self.calculadora('REINICIAR', '', p, q)
            return
            # return '','REINICIAR'
        elif c == 'k':  # k
            # salir del programa
            self.calculadora('SALIR', '', p, q)
            return
            # return '','SALIR'

        # AVANZAR Y STOP
        if c == 'a':  # Avanza/Acelera
            if self.vel < 0 and self.resultadoAduino != '':
                self.vel = 0
                self.calcelUpdate('Avanzar')
                self.onUpdate()
            elif self.vel < self.velmax:
                self.vel = self.vel + 1
            return
            # return '','REINICIAR'
        elif c == 's':  # Stop
            if self.vel >= 0:
                self.vel = self.vel - 1
            return

        # IGUAL A
        elif k == 10 or k == 13 or c == 'i':  # or k==61: # [ENTER] o [=] > Salto de línea o igual: '\n' ó '\r' ó '='
            # imprimir cadena RESULTADO
            self.calculadora('RESULTADO', cadena, p, q)
            return
            # return cadena,'RESULTADO'

        # ESCRITURA NORMAL
        elif k == 8 or c == 'x':  # BACKSPACE
            # recortar cadena un digito
            cadena = self.modcad(cadena, 1)
        elif c in numrs:  # NUMEROS 0-9
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))
        # elif c==',' or c=='.': # COMA o PUNTO
        #     c='.' # Siempre usa punto
        #     # incrementa la cadena con c
        #     cadena = self.modcad(cadena,str(c))

        # NUMEROS ESPECIALES e y pi
        elif c == 'e':  # e => 101
            # Euler's number => 'e'
            c = 'e'
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))
        elif c == 'h':  # h => 104
            # PI => 'h'
            c = 'π'
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))
        elif c == 'f':  # f => 104
            # PI => 'h'
            c = 'φ'
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))

        # OPERACIONES SIMPLES: * + - /
        elif c == '*':  # * => 42
            # Multiplicación => Reemplaza asterisco con signo de multiplicacion ×
            c = '×'
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))
        elif c == '+' or c == 'm':  # + => 43
            # incrementa la cadena con c
            c = '+'
            cadena = self.modcad(cadena, str(c))
        elif c == '-' or c == 'n':  # - => 45
            # incrementa la cadena con c
            c = '-'
            cadena = self.modcad(cadena, str(c))
        elif c == 'r':  # r
            # SQRT => 'r'
            rcadena = cadena[::-1]
            if '(' in rcadena:
                if ')' in rcadena:
                    ax = rcadena.index('(')
                    cx = rcadena.index(')')
                    if ax < cx:
                        c = ')'
                    else:
                        c = '√('
                else:
                    c = ')'
            else:
                c = '√('
            # incrementa la cadena con c
            cadena = self.modcad(cadena, str(c))
        elif c == 'p':  # p
            # Debe enviar al valor p sólo si no estamos ahí
            if (self.dondestoy != 'p'):
                self.calculadora('SETP', cadena, p, q)
                return
        elif c == 'q':  # q
            # Debe enviar al valor q sólo si no estamos ahí
            if (self.dondestoy != 'q'):
                self.calculadora('SETQ', cadena, p, q)
                return

        if (self.dondestoy == 'p'):
            p = cadena
        if (self.dondestoy == 'q'):
            q = cadena
        # if (q==''):
        #     q = '1'
        self.operacion(p, q)

    def calculadora(self, estado, cadena='', p='', q=''):
        if (estado == 'RESULTADO'):
            self.calcelUpdate('Nuevo resultado')
            self.porcion = ''
            self.memvel = 0  #Memoria de la volicidad actual
            if self.vel > 0:
                self.memvel = self.vel
            self.vel = -1  # Stop timer
            self.contador = -1  # Reset timer
            if self.sendToDisplay > 0:
                self.arduino.write('N')  # RESET DYSPLAY
                time.sleep(1)
            if (self.dondestoy == 'p'):
                p = cadena
            if (self.dondestoy == 'q'):
                q = cadena
            if p == '':
                p = '0'
            if (q == ''):
                q = '1'
            rcadena = p[::-1]
            if '(' in rcadena:
                if ')' in rcadena:
                    ax = rcadena.index('(')
                    cx = rcadena.index(')')
                    if ax < cx:
                        p = p + ')'
                else:
                    p = p + ')'
            rcadena = q[::-1]
            if '(' in rcadena:
                if ')' in rcadena:
                    ax = rcadena.index('(')
                    cx = rcadena.index(')')
                    if ax < cx:
                        q = q + ')'
                else:
                    q = q + ')'
            self.resultado(p, q)

        if (estado == 'REINICIAR'):
            self.calcelUpdate('Reiniciar')
            self.resultadoNormal = ''
            self.resultadoAduino = ''
            self.vel = -1  # Stop timer
            self.contador = -1  # Reset timer
            self.operacion(p='', q=1)
            self.resultastr = ''
            self.resulta.set(self.resultastr)
            self.dondestoy = 'p'
            self.labelp.config(bg="#fd0")
            self.labelq.config(bg="#eee")
            if self.sendToDisplay > 0:
                self.arduino.write('N')  # RESET DYSPLAY
                time.sleep(1)
            # self.calculadora()
        if (estado == 'SALIR'):
            self.calcelUpdate()
            logging.info("INFO\tSalir del programa")
            time.sleep(1)
            self.vel = -1  # Stop timer
            self.master.quit()
            # return
        if (estado == 'SETP'):
            q = cadena
            if '(' in q and ')' not in q:
                q = q + ')'
            if q == '0' or q == '':
                self.divisorstr = str('1')
                self.divisor.set(self.divisorstr)
                self.labelq.config(fg="#aaa")
            self.dondestoy = 'p'
            self.labelp.config(bg="#fd0")
            self.labelq.config(bg="#eee")
            # self.calculadora(p,p,q,dondestoy)
        if (estado == 'SETQ'):
            p = cadena
            if '(' in p and ')' not in p:
                p = p + ')'
            if q == '1':
                self.divisorstr = str('')
                self.divisor.set(self.divisorstr)
                self.labelq.config(fg="#aaa")
            self.dondestoy = 'q'
            self.labelp.config(bg="#eee")
            self.labelq.config(bg="#fd0")
            # self.calculadora(q,p,q,dondestoy)

    def maxlen(self, p, q):
        maxlen = len(str(p))
        if (len(str(q)) > maxlen):
            maxlen = len(str(q))
        lp = len(str(p))
        lq = len(str(q))
        return maxlen, lp, lq

    def operacion(self, p='', q=1):
        ml, lp, lq = self.maxlen(p, q)
        self.dividendostr = str(p)
        self.dividendo.set(self.dividendostr)
        self.divisorstr = str(q)
        self.divisor.set(self.divisorstr)

        # Color gris en divisor cuando es 1
        if self.divisorstr != "1":
            self.labelq.config(fg="#000")
        else:
            self.labelq.config(fg="#aaa")

    def resultado(self, p, q):
        self.calcelUpdate()
        ml, lp, lq = self.maxlen(p, q)
        self.dividendostr = str(p)
        self.dividendo.set(self.dividendostr)
        self.divisorstr = str(q)
        self.divisor.set(self.divisorstr)

        # Color gris en divisor cuando es 1
        if self.divisorstr != "1":
            self.labelq.config(fg="#000")
        else:
            self.labelq.config(fg="#aaa")

        ################################################
        # Calcula p/q en la presición definida
        equa = '(' + p + ')/(' + q + ')'
        res = self.nsp.eval(equa)

        # RESULTADO COMO CADENA
        nres = ''
        sres = str(res)
        if sres == 'ERROR':
            self.resultastr = sres
            self.resulta.set(self.resultastr)
            logging.info("ERROR\t" + equa)
            return
        # Set start envio Arduino
        self.resultadoNormal = sres
        self.resultadoAduino = self.filtrar(sres)
        self.contador = -1
        self.vel = self.memvel
        logging.info("OK\t" + equa)
        # Inicia envío a display arduino
        self.onUpdate()

    def calcelUpdate(self, quien=''):
        if self.playwaves > 0:
            mu.newfreq = 0
        if self._job is not None:
            if quien != '':
                logging.info("CANCEL\t" + quien)
            self.master.after_cancel(self._job)
            self._job = None

    def onUpdate(self):
        self.calcelUpdate()
        # Actualiza el caracter enviado, la posición y el estado actual (pausa/play)
        self.contador = self.contador + 1
        inicio = self.contador - self.porcionlen
        if self.contador > self.maxprec:
            self.porcion = ''
            self.contador = 0
            self.resultado(self.dividendostr, self.divisorstr)
            if self.playwaves > 0:
                mu.newfreq = 0
            return
        if inicio < 0:
            inicio = 0
        if self.contador > len(self.resultadoAduino) - 1:
            enviar = '0'
        else:
            enviar = self.resultadoAduino[self.contador]
        self.porcion = self.porcion + enviar
        if len(self.porcion) > self.porcionlen - 1:
            self.porcion = self.porcion[-self.porcionlen:]

        if self.debuguear > 0:
            salida = u"Resultado: " + self.resultadoNormal[0:self.porcionlen]
            salida = salida + u"\nVelocidad: " + str(
                self.velist[self.vel]) + " ms"
            tiempofaltante = round(
                self.velist[self.vel] *
                (len(self.resultadoAduino) - self.contador) / 1000)
            m, s = divmod(tiempofaltante, 60)
            h, m = divmod(m, 60)
            salida = salida + u"\nTiempo restante: " + str("%d:%02d:%02d" %
                                                           (h, m, s)) + " hms"
            salida = salida + u"\nPosición: " + str(
                self.contador) + " / " + str(len(self.resultadoAduino))
            salida = salida + u"\nDígito: " + enviar
            salida = salida + u"\nPorción: " + self.porcion.rjust(
                self.porcionlen, ' ').replace(' ', '  ')
            self.resultastr = salida
            self.resulta.set(self.resultastr)

        if self.playwaves > 0:
            self.stream.start_stream()
            try:
                nx = int(enviar)
            except ValueError:
                nx = -1
                pass
            if nx > 0:
                nx = nx - 1
            elif nx == 0:
                nx = -1
            if nx < 0:
                mu.newfreq = 0
            else:
                mu.newfreq = mu.listaFreq[nx]

        # ENVIO A DISPLAY
        if self.sendToDisplay > 0:
            self.arduino.write(
                enviar
            )  # Envia digito actual a DISPLAY, la pausa la genera el unUpdate mismo
        # DEBUG EN CONSOLA
        if self.debuguear > 1:
            print(current_iso8601(), self.contador, self.vel,
                  self.velist[self.vel], enviar)
        # schedule timer para ayutollamarse cada segundo
        if self.vel >= 0:
            self._job = self.master.after(self.velist[self.vel], self.onUpdate)

        # Versión de prueba !!!
        if self.playsounds > 0 and self.char2wav(enviar) != '':
            corto = ''
            if self.velist[self.vel] < 300:
                corto = '_'
            winsound.PlaySound('wav/' + self.char2wav(enviar) + corto + '.wav',
                               winsound.SND_FILENAME | winsound.SND_ASYNC)

    def char2wav(self, c):
        r = {
            'A': '1',
            'B': '2',
            'C': '3',
            'D': '4',
            'E': '5',
            'G': '7',
            'H': '8',
            'I': '9',
            'J': '0',
            '-': '0'
        }
        if c in r.keys():
            c = r[c]
        n = {
            # '1':'c1', '2':'d1', '3':'e1', '4':'f1', '5':'', '6':'g1', '7':'a1', '8':'b1', '9':'c2', '0':'' # Mayor, Silencios: 0, 5
            '1': 'c1',
            '2': 'd1',
            '3': 'd1s',
            '4': 'e1',
            '5': 'f1',
            '6': 'g1',
            '7': 'a1',
            '8': 'b1',
            '9': 'c2',
            '0': ''  # Mayor/Menor, Silencio: 0
        }
        return n[c]
Example #17
0
class SkyglowEstimationToolbox:
    """Main class that establishes GUI."""
    def __init__(self, root):
        self.root = root

        # Radio action buttons
        self.action = None
        self.sgmap_single_btn, self.krn_lib_btn, self.multi_map_btn = None, None, None

        self.file_log_var = StringVar()
        self.csv_file_var = StringVar()
        self.krn_folder_var = StringVar()
        self.output_folder_var = StringVar()
        self.sgmap_folder_var = StringVar()

        self.krn_ent_var = StringVar()
        self.krn_var, self.hem_var = IntVar(), IntVar()
        self.img, self.cdiag = None, None
        self.lat_lbl, self.lat_entry = None, None
        self.k_lbl, self.k_entry = None, None
        self.zen_lbl, self.zen_entry = None, None
        self.azi_lbl, self.azi_entry = None, None
        self.krn_lvl, self.krn_entry, self.krn_btn = None, None, None
        self.txt_redir, self.prg_log = None, None
        self.map_btn, self.gen_krn_btn = None, None

        # Sets window title, size, and icon on screen.
        self.root.title("Skyglow Estimation Toolbox (SET)")
        self.root.geometry('%dx%d+%d+%d' %
                           (constants.SW * 0.75, constants.SH * 0.75, 25, 25))
        self.root.iconbitmap(os.path.join(os.getcwd(), constants.ICO))
        self.root.resizable(False, False)
        self.root.update_idletasks()

        # Creates three paned windows for the main screen.
        base = PanedWindow()
        base.pack(fill=BOTH, expand=1)
        sub1 = PanedWindow(base,
                           orient=VERTICAL,
                           height=self.root.winfo_height() * 3 / 4)
        base.add(sub1)
        sub2 = PanedWindow(sub1,
                           orient=HORIZONTAL,
                           height=self.root.winfo_height() / 5)
        sub1.add(sub2)

        # Creates frame for holding inputs.
        self.input_frame = Frame(sub2)
        sub2.add(self.input_frame)

        # Creates frame for bottom half of main screen.
        self.img_frame = Frame(sub1, bd=2, bg='white', relief="sunken")
        sub1.add(self.img_frame)

        # Creates canvas for displaying images.
        self.img_canvas = Canvas(self.img_frame,
                                 bd=2,
                                 relief="groove",
                                 width=constants.SW * 0.6,
                                 height=self.root.winfo_height() * 3 / 4 * 0.9)
        self.img_canvas.place(relx=.5, rely=.5, anchor=CENTER)

        # Creates help button for link to documentation, instructions, and about.
        self.help_btn = Menubutton(self.input_frame,
                                   text="Help",
                                   relief="raised",
                                   bd=2,
                                   width=8,
                                   pady=1)
        #self.help_btn.place(relx=1, rely=0, anchor=NE)
        self.help_btn.grid(column=4, columnspan=1, row=0)
        self.help_btn_menu = Menu(self.help_btn, tearoff=0)
        doc = 'https://github.com/NASA-DEVELOP'
        self.help_btn_menu.add_command(label="Documentation",
                                       command=lambda: self.open_url(doc))
        self.help_btn_menu.add_command(label="Instructions",
                                       command=self.instructions)
        self.help_btn_menu.add_separator()
        self.help_btn_menu.add_command(label="About", command=self.about)
        self.help_btn["menu"] = self.help_btn_menu

    def main_screen(self):
        """Set up input GUI and image display screen."""
        self.action = IntVar()

        btn_width = int(constants.SW / 60)
        file_width = int(constants.SW / 18)
        lbl_width = int(constants.SW / 60)
        gen_width = int(constants.SW / 42)
        radio_font = Font(family='TkDefaultFont', size=12)
        self.sgmap_single_btn = Radiobutton(
            self.input_frame,
            text="Generate Artificial Skyglow Map",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='sng',
            command=self.sng_popup)
        self.krn_lib_btn = Radiobutton(self.input_frame,
                                       text="Generate Kernel Library",
                                       font=radio_font,
                                       width=btn_width,
                                       variable=self.action,
                                       value='krn',
                                       command=self.krn_popup)
        self.multi_map_btn = Radiobutton(
            self.input_frame,
            text="Generate Maps from Multiple Kernels",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='mul',
            command=self.mul_popup)
        self.hem_map_btn = Radiobutton(
            self.input_frame,
            text="Generate Hemispherical Visualization",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='hem',
            command=self.hem_popup)
        #Place widget
        self.sgmap_single_btn.grid(column=0, columnspan=1, row=0)
        self.krn_lib_btn.grid(column=1, columnspan=1, row=0)
        self.multi_map_btn.grid(column=2, columnspan=1, row=0)
        self.hem_map_btn.grid(column=3, columnspan=1, row=0)

        # VIIRS Image Reference File
        self.file_lbl = Label(self.input_frame,
                              text="Image File:",
                              width=lbl_width,
                              anchor=E)
        self.file_log = Entry(self.input_frame,
                              width=file_width,
                              bd=2,
                              relief="sunken",
                              textvariable=self.file_log_var)
        self.browse_btn = Button(self.input_frame,
                                 text="Browse",
                                 command=self.import_viirs)

        # Angles CSV File
        self.csv_file_lbl = Label(self.input_frame,
                                  text="Angles CSV File:",
                                  width=lbl_width,
                                  anchor=E)
        self.csv_file_log = Entry(self.input_frame,
                                  width=file_width,
                                  bd=2,
                                  relief="sunken",
                                  textvariable=self.csv_file_var)
        self.csv_browse_btn = Button(self.input_frame,
                                     text="Browse",
                                     command=self.import_csv)

        # Multiple Maps form Kernel library
        self.mul_file_lbl = Label(self.input_frame,
                                  text="Kernel Folder:",
                                  width=lbl_width,
                                  anchor=E)
        self.mul_file_log = Entry(self.input_frame,
                                  width=file_width,
                                  bd=2,
                                  relief="sunken",
                                  textvariable=self.krn_folder_var)
        self.mul_browse_btn = Button(self.input_frame,
                                     text="Browse",
                                     command=self.import_krn_folder)

        # MultiKrn Map Output Location
        self.output_lbl = Label(self.input_frame,
                                text="Output Location:",
                                width=lbl_width,
                                anchor=E)
        self.output_log = Entry(self.input_frame,
                                width=file_width,
                                bd=2,
                                relief="sunken",
                                textvariable=self.output_folder_var)
        self.output_btn = Button(self.input_frame,
                                 text="Browse",
                                 command=self.import_out_folder)

        # Hemisphere Output Location
        self.sgmap_folder_lbl = Label(self.input_frame,
                                      text="Skyglow Map Location:",
                                      width=lbl_width,
                                      anchor=E)
        self.sgmap_folder_log = Entry(self.input_frame,
                                      width=file_width,
                                      bd=2,
                                      relief="sunken",
                                      textvariable=self.sgmap_folder_var)
        self.sgmap_folder_btn = Button(self.input_frame,
                                       text="Browse",
                                       command=self.import_sgmap_folder)

        # Import Kernel Checkbutton
        self.check_lbl = Label(self.input_frame,
                               text="Import Kernel:",
                               width=lbl_width,
                               anchor=E)

        self.krn_chk = Checkbutton(self.input_frame,
                                   anchor=W,
                                   variable=self.krn_var,
                                   command=self.checkbtn_val)

        self.hem_chk_lbl = Label(self.input_frame,
                                 text="Generate kernels for hemisphere:",
                                 width=lbl_width,
                                 anchor=E)

        self.hem_chk = Checkbutton(self.input_frame,
                                   anchor=W,
                                   variable=self.hem_var)

        # Region Latitude (deg), Grand Teton National park = 43.7904 degrees N
        self.lat_lbl = Label(self.input_frame,
                             text="Latitude (deg):",
                             width=lbl_width,
                             anchor=E)
        self.lat_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")
        self.lon_lbl = Label(self.input_frame,
                             text="Longitude (deg):",
                             width=lbl_width,
                             anchor=E)
        self.lon_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        # Atmospheric Clarity Parameter, REF 2, Eq. 12, p. 645
        self.k_lbl = Label(self.input_frame,
                           text="Atmospheric Clarity Parameter:",
                           width=btn_width,
                           anchor=E)
        self.k_entry = Entry(self.input_frame,
                             width=btn_width,
                             bd=2,
                             relief="sunken")

        # Zenith angle (deg), z, REF 2, Fig. 6, p.648
        self.zen_lbl = Label(self.input_frame,
                             text="Zenith Angle (deg):",
                             width=lbl_width,
                             anchor=E)
        self.zen_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        # Azimuth angle (deg)
        self.azi_lbl = Label(self.input_frame,
                             text="Azimuth Angle (deg):",
                             width=lbl_width,
                             anchor=E)
        self.azi_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        self.krn_lbl = Label(self.input_frame,
                             text="Kernel File:",
                             width=lbl_width,
                             anchor=E)
        self.krn_ent = Entry(self.input_frame,
                             width=file_width,
                             bd=2,
                             relief="sunken",
                             textvariable=self.krn_ent_var)
        self.krn_btn = Button(self.input_frame,
                              text="Browse",
                              command=self.import_krn)

        # Generate Artificial Skyglow Map Button
        self.map_btn = Button(self.input_frame,
                              text="Generate Artificial Skyglow Map",
                              width=gen_width,
                              command=self.generate_map)
        # Generate Kernal library button for SET
        self.gen_krn_btn = Button(self.input_frame,
                                  text="Generate Kernel Library",
                                  width=gen_width,
                                  command=self.generate_krn)
        # Generate Map of Multiple Kernals(word better later on)
        self.mul_map_btn = Button(self.input_frame,
                                  text="Generate Maps from Multiple Kernels",
                                  width=gen_width,
                                  command=self.generate_mmap)
        # Generate Hemispherical Visualization Display of Skyglow
        self.hem_gen_btn = Button(self.input_frame,
                                  text="Generate Hemisphere",
                                  width=gen_width,
                                  command=self.generate_hem)

    def import_viirs(self):
        """Import a VIIRS DNB file."""
        # Allows user to search through his directory for VIIRS Image file.
        file_types = [('TIFF Files', '*.tif'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.file_log_var.set(file_name)

        # Checks to see if file is empty. If not, displays image on canvas.
        if file_name != '':
            pilimg = Image.open(file_name)
            pilimg_width, pilimg_height = pilimg.size
            pilimg.tile = [
                t for t in pilimg.tile
                if t[1][2] < pilimg_width and t[1][3] < pilimg_height
            ]
            canvas_size = (self.img_canvas.winfo_width(),
                           self.img_canvas.winfo_height())
            pilimg_r = pilimg.resize(canvas_size, Image.ANTIALIAS)
            pilimg_col = ImageOps.colorize(ImageOps.grayscale(pilimg_r),
                                           (0, 0, 0), (255, 255, 255))
            pilimg_cont = ImageOps.autocontrast(pilimg_col,
                                                cutoff=.4,
                                                ignore=None)
            self.img = ImageTk.PhotoImage(pilimg_cont)
            self.img_canvas.create_image(canvas_size[0] / 2,
                                         canvas_size[1] / 2,
                                         image=self.img)
        else:
            print('File is empty.')

    def import_csv(self):
        """Import CSV file."""
        file_types = [('CSV Files', '*.csv'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.csv_file_var.set(file_name)

        if file_name is '':
            print('File is empty.')

    def import_krn_folder(self):
        """Import kernel folder."""
        krn_dir = filedialog.askdirectory(initialdir='/',
                                          title="Select kernel folder")
        self.krn_folder_var.set(krn_dir)

        if krn_dir is '':
            print('Directory is empty.')

    def import_out_folder(self):
        """Import skyglow output folder."""
        output_dir = filedialog.askdirectory(initialdir='/',
                                             title="Select output folder")
        self.output_folder_var.set(output_dir)

        if output_dir is '':
            print('Directory is empty.')

    def import_krn(self):
        """Import existing kernel tif."""
        file_types = [('TIFF Files', '*.tif'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.krn_ent_var.set(file_name)

    def import_sgmap_folder(self):
        """Import skyglow map folder for hemisphere building."""
        sgmap_dir = filedialog.askdirectory(initialdir='/',
                                            title="Select skyglow map folder")
        self.sgmap_folder_var.set(sgmap_dir)

        if sgmap_dir is '':
            print('Directory is empty.')

    def sng_popup(self):
        """Single map tab."""
        self.remove_all()

        self.check_lbl.grid(column=0, row=2)
        self.krn_chk.place(relx=.22, rely=.41, anchor=CENTER)

        self.file_lbl.grid(column=0, row=1)
        self.file_log.grid(column=1, columnspan=3, row=1)
        self.browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        self.k_lbl.grid(column=2, row=3)
        self.k_entry.grid(column=3, row=3)

        self.zen_lbl.grid(column=0, row=4)
        self.zen_entry.grid(column=1, row=4)

        self.azi_lbl.grid(column=2, row=4)
        self.azi_entry.grid(column=3, row=4)

        self.map_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W)

    def krn_popup(self):
        """Kernel lib tab."""
        self.remove_all()

        # latitude
        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        # atmospheric clarity
        self.k_lbl.grid(column=2, row=3)
        self.k_entry.grid(column=3, row=3)

        # angles file
        self.csv_file_lbl.grid(column=0, row=1)
        self.csv_file_log.grid(column=1, columnspan=3, row=1)
        self.csv_browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        # input VIIRS image
        self.file_lbl.grid(column=0, row=2)
        self.file_log.grid(column=1, columnspan=3, row=2)
        self.browse_btn.grid(column=4, row=2, sticky=W, padx=3)

        self.hem_chk_lbl.grid(column=0, row=4)
        self.hem_chk.place(relx=.21, rely=.69)

        self.gen_krn_btn.grid(column=1,
                              columnspan=3,
                              row=5,
                              sticky=N + S + E + W)

    def mul_popup(self):
        """Multiple maps tab."""
        self.remove_all()

        # Kernel folder location
        self.mul_file_lbl.grid(column=0, row=1)
        self.mul_file_log.grid(column=1, columnspan=3, row=1)
        self.mul_browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        # input VIIRS image
        self.file_lbl.grid(column=0, row=2)
        self.file_log.grid(column=1, columnspan=3, row=2)
        self.browse_btn.grid(column=4, row=2, sticky=W, padx=3)

        # Choose output location
        self.output_lbl.grid(column=0, row=3)
        self.output_log.grid(column=1, columnspan=3, row=3)
        self.output_btn.grid(column=4, row=3, sticky=W, padx=3)

        # Generate map from kernel folder
        self.mul_map_btn.grid(column=1,
                              columnspan=3,
                              row=4,
                              sticky=N + S + E + W)

    def hem_popup(self):
        """Hemisphere tab."""
        self.remove_all()

        # Skyglow Map Folder
        self.sgmap_folder_lbl.grid(column=0, row=1)
        self.sgmap_folder_log.grid(column=1, columnspan=3, row=1)
        self.sgmap_folder_btn.grid(column=4, row=1, sticky=W, padx=3)

        # Latitude entry
        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        # Longitude entry
        self.lon_lbl.grid(column=2, row=3)
        self.lon_entry.grid(column=3, row=3)

        # Generate Hemispherical Visualization button
        self.hem_gen_btn.grid(column=1,
                              columnspan=3,
                              row=4,
                              sticky=N + S + E + W)

    def remove_all(self):
        """Remove all existing GUI elements before opening new tab."""
        self.check_lbl.grid_remove()
        self.krn_chk.place_forget()
        self.hem_chk.place_forget()
        self.hem_chk_lbl.grid_remove()
        self.file_lbl.grid_remove()
        self.file_log.grid_remove()
        self.browse_btn.grid_remove()
        self.krn_lbl.grid_remove()
        self.krn_ent.grid_remove()
        self.krn_btn.grid_remove()
        self.lat_lbl.grid_remove()
        self.lat_entry.grid_remove()
        self.k_lbl.grid_remove()
        self.k_entry.grid_remove()
        self.zen_lbl.grid_remove()
        self.zen_entry.grid_remove()
        self.azi_lbl.grid_remove()
        self.azi_entry.grid_remove()
        self.map_btn.grid_remove()
        self.gen_krn_btn.grid_remove()
        self.mul_map_btn.grid_remove()
        self.csv_file_lbl.grid_remove()
        self.csv_file_log.grid_remove()
        self.csv_browse_btn.grid_remove()
        self.mul_file_lbl.grid_remove()
        self.mul_file_log.grid_remove()
        self.mul_browse_btn.grid_remove()
        self.output_lbl.grid_remove()
        self.output_log.grid_remove()
        self.output_btn.grid_remove()
        self.hem_gen_btn.grid_remove()
        self.lat_lbl.grid_remove()
        self.lat_entry.grid_remove()
        self.lon_lbl.grid_remove()
        self.lon_entry.grid_remove()
        self.sgmap_folder_lbl.grid_remove()
        self.sgmap_folder_log.grid_remove()
        self.sgmap_folder_btn.grid_remove()

    def checkbtn_val(self):
        """Change interface based on if Import Kernel button is checked."""
        # Import Kernel File widgets when Kernel Checkbutton is marked.
        if self.krn_var.get():
            self.lat_lbl.grid_remove()
            self.lat_entry.grid_remove()
            self.k_lbl.grid_remove()
            self.k_entry.grid_remove()
            self.zen_lbl.grid_remove()
            self.zen_entry.grid_remove()
            self.azi_lbl.grid_remove()
            self.azi_entry.grid_remove()
            self.krn_lbl.grid(column=0, row=2)
            self.krn_ent.grid(column=1, columnspan=3, row=2)
            self.krn_btn.grid(column=4, row=2, sticky=W, padx=3)
            self.krn_chk.place_forget()
            self.krn_chk.place(relx=0.19, rely=.5)
        # Input parameter widgets when Kernel Checkbuttton is unmarked
        else:
            self.krn_lbl.grid_remove()
            self.krn_ent.grid_remove()
            self.krn_btn.grid_remove()
            self.lat_lbl.grid(column=0, row=3)
            self.lat_entry.grid(column=1, row=3)
            self.k_lbl.grid(column=2, row=3)
            self.k_entry.grid(column=3, row=3)
            self.zen_lbl.grid(column=0, row=4)
            self.zen_entry.grid(column=1, row=4)
            self.azi_lbl.grid(column=2, row=4)
            self.azi_entry.grid(column=3, row=4)
            self.krn_chk.place_forget()
            self.krn_chk.place(relx=0.22, rely=.41, anchor=CENTER)

    @staticmethod
    def open_url(url):
        """"Open a url"""
        webbrowser.open_new(url)

    def instructions(self):
        """Open instructions window."""
        # Instantiates separate Toplevel instruction window.
        instr_window = Toplevel(self.root)
        instr_window.geometry('550x575+25+25')
        instr_window.title('Instructions')
        instr_window.wm_iconbitmap(constants.ICO)
        instr_window.resizable(False, False)

        # Creatse Scrollbar and Frame for containing other widgets.
        instr_scroll = Scrollbar(instr_window)
        instr_scroll.pack(fill=Y, side="right")
        instr_frame = Frame(instr_window, bg='white')
        instr_frame.pack(fill=BOTH, side="left")

        # Adds instruction text from constants and adds image of Cinzano's diagram.
        instr = Text(instr_frame,
                     width=65,
                     height=40,
                     padx=10,
                     pady=5,
                     bd=0,
                     wrap="word")
        instr.insert("end", constants.INSTR)
        cdiagram_file = Image.open("./static/cinzano_diagram.PNG")
        cdiagram_file = cdiagram_file.resize((500, 450), Image.ANTIALIAS)
        self.cdiag = ImageTk.PhotoImage(cdiagram_file)
        instr.image_create("end", image=self.cdiag)
        instr.tag_add("top", "1.0", "4.10")
        instr.tag_config("top", font='Times 12 bold')
        instr.tag_add("body", "5.0", "19.20")
        instr.tag_config("body", font='Times 12')
        instr.insert("end", constants.CDIAG)
        instr.pack()
        instr_scroll.config(command=instr.yview)

    def about(self):
        """Open an about window.

        Window gives authors, SET version number, and icon credit.
        """
        # Instantiates a new Toplevel about window.
        about_window = Toplevel(self.root)
        about_window.geometry('350x335+25+25')
        about_window.title('About')
        about_window.wm_iconbitmap(constants.ICO)
        about_window.resizable(False, False)

        # Adds text to about window.
        about = Text(about_window, width=50, height=30, padx=10, pady=3)
        about.insert("end", constants.ABOUT)
        about.tag_add("abt", "1.0", "21.30")
        about.tag_config("abt", font='Times 10 bold', justify=CENTER)
        about.pack()

    def progress(self):
        """Construct a progress window to monitor darksky."""
        # Instantiates a new Toplevel window and frame for progress bar and loading log.
        self.prg_window = Toplevel(self.root)
        self.prg_window.geometry('650x325+250+250')
        self.prg_window.title('Generating Artificial Skyglow Map...')
        self.prg_window.iconbitmap(constants.ICO)
        self.prg_window.resizable(False, False)
        prg_frame = Frame(self.prg_window)
        prg_frame.pack(fill=BOTH)

        # Creates Scrollbar, Progressbar, and Label for checking progress..
        prg_scroll = Scrollbar(prg_frame)
        prg_scroll.pack(fill=Y, side="right")
        self.prg_bar = ttk.Progressbar(prg_frame,
                                       orient=HORIZONTAL,
                                       length=750,
                                       mode='indeterminate')
        self.prg_bar.pack()
        self.prg_bar.start()
        prg_lbl_txt = StringVar()
        prg_lbl = Label(prg_frame, textvariable=prg_lbl_txt)
        prg_lbl.pack()

        # Displays message log that prints from log file and starts darkskypy.
        self.prg_log = Text(prg_frame,
                            width=90,
                            padx=5,
                            pady=5,
                            relief="sunken")
        self.prg_log.pack()
        self.prg_log.insert(
            "end", "*****Progress Log*****\n=======================\n")
        self.prg_log.tag_add("abt", "1.0", "3.0")
        self.prg_log.tag_config("abt", font='Courier 12 bold', justify=CENTER)
        self.txt_redir = LogRedirector(self.prg_log)
        logger.addHandler(self.txt_redir)
        sys.stderr = StderrRedirector(self.prg_log)
        prg_lbl_txt.set("Start time: " + str(time.asctime()))

        self.no_progress = 0

    def update_progress(self):
        """Update progress window to prevent it from freezing."""
        self.prg_log.update()
        # if only one thread exists, stop progress bar and close window
        if len(threading.enumerate()) == 1:
            self.prg_bar.stop()
            self.no_progress += 1
            if self.no_progress == 3:
                self.prg_window.withdraw()
        else:
            self.prg_bar.start()
        self.root.after(1000, self.update_progress)

    def generate_map(self):
        """Call darksky.sgmapper in background thread."""
        # Acquires input arguments.
        lat_in, k_in, zen_in, azi_in, file_in, krn_file_in = 0, 0, 0, 0, '', ''
        if self.krn_var.get():
            krn_file_in = self.krn_ent_var.get()
        else:
            lat_in = float(self.lat_entry.get())
            k_in = float(self.k_entry.get())
            zen_in = float(self.zen_entry.get())
            azi_in = float(self.azi_entry.get())
        file_in = self.file_log_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        t_thread = threading.Thread(target=darksky.sgmapper,
                                    args=(lat_in, k_in, zen_in, azi_in,
                                          file_in, krn_file_in))
        t_thread.setDaemon(True)
        p_thread.start()
        t_thread.start()

    def generate_krn(self):
        """Start kernel generation in background threads."""
        # Acquires input arguments
        csv_in, file_in, lat_in, k_in, hem = '', '', 0, 0, False
        csv_in = self.csv_file_var.get()
        file_in = self.file_log_var.get()
        lat_in = float(self.lat_entry.get())
        k_in = float(self.k_entry.get())
        hem = self.hem_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        with open(csv_in, "rb") as f:
            angle_list = loadtxt(f, delimiter=",", skiprows=1)
        p_thread.start()
        for angle_set in angle_list:
            t_thread = threading.Thread(target=darksky.generate_krn,
                                        args=(lat_in, k_in, angle_set[0],
                                              angle_set[1], file_in, hem))
            t_thread.setDaemon(True)

            t_thread.start()

    def generate_mmap(self):
        """Start brightness map creation from kernels."""
        # Acquires input arguments
        krn_folder_in, file_in, output_in, = '', '', ''
        krn_folder_in = self.krn_folder_var.get()
        file_in = self.file_log_var.get()
        output_in = self.output_folder_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        t_thread = threading.Thread(target=darksky.multisgmapper,
                                    args=(file_in, krn_folder_in, output_in))
        t_thread.setDaemon(True)
        p_thread.start()
        t_thread.start()

    def generate_hem(self):
        """Generate hemisphere."""
        sgmap_folder_in, lat_in, lon_in, = '', 0, 0
        sgmap_folder_in = self.sgmap_folder_var.get()
        lat_in = float(self.lat_entry.get())
        lon_in = float(self.lon_entry.get())
        darksky.generate_hem(lat_in, lon_in, sgmap_folder_in)
Example #18
0
mainframe.resizable(False, False)


def mainexit():
    global cv, cv_frame, viewer, select_ball
    del cv
    del cv_frame
    del viewer
    select_ball[0] = -1
    mainframe.destroy()


mainframe.protocol('WM_DELETE_WINDOW', mainexit)
cv_bg_color = '#d5d5d5'
cv_frame = Canvas(mainframe)  #,bg=cv_bg_color
cv_frame.place(x=0, y=0, relwidth=1.0, relheight=1.0)
point = 0
point_max = 0
point_canvas = cv_frame.create_text(81, 27, font=('Purisa', 24), text=point)
point_max_canvas = cv_frame.create_text(405,
                                        27,
                                        font=('Purisa', 24),
                                        text=point_max)
viewer = Canvas(cv_frame)  #,bg=cv_bg_color)
viewer.place(x=162, y=0, width=162, height=54)
cv = Canvas(cv_frame)  #,bg=cv_bg_color)
cv.place(x=0, y=55, width=490, height=490)

width_board = 9
height_board = 9
map_board = []
class ColourSetter:

	def __init__(self, parent):
		self.parent = parent

		self.root = self.parent.root
		

		self.size = (1, 1)
		self.colours = [(0, 0, 255)]
		
		self.colour_cells = []

		self.draw(init=True)

		return

	def draw(self, init=False):

		if init:
			self.canvas_width, self.canvas_height = 0, 0
			self.canvas = Canvas(self.root, bg="black")
			self.colour_cells = []

		# update colour cells

		while self.colour_cells != []:
			#print('killing...')
			self.colour_cells[0].unbind("<Button-1>")
			self.colour_cells[0].destroy()
			del self.colour_cells[0]


		self.button_index_dict = dict()

		nb_colours = self.size[0]*self.size[1]
		pos = 0
		for ix in range(self.size[0]):
			for iy in range(self.size[1]):
				colour = self.colours[pos]

				# create the new cell
				colour_cell = Button(self.canvas, bg=toHex([v/255. for v in colour]), activebackground=toHex([v/255. for v in colour]))
				colour_cell.bind("<Button-1>", self.handleColourSelector)


				# place the cell
				cell_width = self.canvas_width/self.size[0]
				cell_height = self.canvas_height/self.size[1]

				cell_width = min(cell_width, cell_height)
				cell_height = min(cell_width, cell_height)

				x = ix * cell_width
				y = iy * cell_height
				colour_cell.place(x = x, y = y, width = cell_width, height=cell_height)

				self.button_index_dict[colour_cell] = pos
				self.colour_cells.append(colour_cell)

				pos += 1

	def handleColourSelector(self, event=[]):

		#print("SELECTOR:", event)
		#print(dir(event))

		btn_pos = self.button_index_dict[event.widget]

		#event.widget.configure(bg="black")
		new_colour_rgb, new_colour_hex = tkcolorpicker.askcolor(color=self.colours[btn_pos])

		if new_colour_rgb == None:
			print("No colour selected.")
			return


		
		self.colours[btn_pos] = new_colour_rgb
		self.draw()

		return


	def place(self, x, y, width, height):

		self.canvas_width = width
		self.canvas_height = height

		self.canvas.place(x=x, y=y, width=width, height=height)

		return

	def setGridSize(self, size):

		

		self.size = size

		nb_colours = self.size[0] * self.size[1]

		# need to make sure there are the proper number of colours
		self.colours = self.colours[:nb_colours]
		if len(self.colours) < nb_colours:
			for _ in range(nb_colours - len(self.colours)):
				self.colours.append(self.colours[-1])

		self.draw()

	def randomize(self):

		nb_colours = self.size[0] * self.size[1]

		new_seed_colours = []
		for _ in range(nb_colours):
			c = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
			new_seed_colours.append(c)

		self.colours = new_seed_colours

		self.draw()


		return

	def getSeed(self):

		# return the seed image with specified colours

		N1 = Image.new('RGB', self.size, "white")
		pix1 = N1.load()
		pos = 0
		for x in range(N1.size[0]):
			for y in range(N1.size[1]):

				r, g, b = self.colours[pos]
				pix1[x,y] = (r, g, b)

				pos += 1

		return N1
Example #20
0
win = tk.Tk()
win.title('TRR Eyeglasses Selector 1.0.1')
img = PhotoImage(file='select.gif')
win.tk.call('wm', 'iconphoto', win._w, img)
frame1 = tk.Frame(
	master = win,
	width = 640,
	height = 550,
	bg = '#8B4513'
)
frame3 = tk.Frame(master = win, width=350, height=50, bg='#ffffff')
frame4 = tk.Frame(master = win, width=150, height=50, bg='#000000')
frame1.pack(fill='both', expand='yes')

canvas = Canvas(frame1, width=640, height=450)
canvas.place(in_=frame1,x=0,y=0,width=640,height=450)
frame3.place(in_=frame1, x=5, y=460, width=427, height=75)
rsstext=tk.Text(frame3)
rsstext.insert(END,'ข่าวสาร')
rsstext.pack()

localtime = time.asctime( time.localtime(time.time()) )
frame4.place(in_=frame1, x=435, y=460, width=205, height=56)
label4001 = tk.Label(frame4, text=format(price,'01'),font="Arial 28 bold",fg='#ffffff', bg='#000000')
label4001.place(x=170,y=0)
label4002 = tk.Label(frame4, text=localtime,font="Arial 6",fg='#ffffff', bg='#000000')
label4002.place(x=5,y=40)

def plu_take_a_picture(i):
	global plu_button,image_CV,plu_tkpi,cam_num,plu_pic,nok_air
	win.after_cancel(nok_air)
Example #21
0
class Example(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

        self.img_labels = [Label(self), Label(self)]

    def initUI(self):
        self.bg_color = '#333'

        # self.parent.title("Comparação de imagens")
        self.style = Style()
        self.style.configure('TFrame', background=self.bg_color)

        self.pack(fill=BOTH, expand=1)

        menu_bar = Menu(self.parent)
        self.parent.config(menu=menu_bar)

        size = self.parent.size

        select_image_btn = Button(self, text='Selecionar Imagem', command=self.select_image_file)
        select_image_btn.place(x=10, y=10)

        quit_button = Button(self, text='Sair', command=self.quit)
        quit_button.place(x=size[0] - 100, y=size[1] - 50)

        self.canvas = Canvas(self, bg=self.bg_color, bd=10)
        self.canvas.pack()
        self.canvas.place(x=0, y=600, height=200, width=650)

    def text_dialog_box(self, box_title, msg):
        return tkSimpleDialog.askstring(box_title, msg)

    def draw_result(self, results):
        self.canvas.grid_forget()
        self.canvas = Canvas(self, bg=self.bg_color, bd=10)
        self.canvas.pack()

        self.canvas.place(x=0, y=600, height=200, width=650)

        font = ('Helvetica', '12')
        self.canvas.create_text(20, 40, anchor=Tkinter.W, font=font, text='Probability of being the same image according different algorithms:', fill='white')
        self.canvas.create_text(20, 65, anchor=Tkinter.W, font=font, text=results[0], fill='white')
        self.canvas.create_text(20, 90, anchor=Tkinter.W, font=font, text=results[1], fill='white')
        self.canvas.create_text(20, 115, anchor=Tkinter.W, font=font, text=results[2], fill='white')

    def load_image(self, file_name, position, label):
        image = Image.open(file_name)
        image = ImageTk.PhotoImage(image)
        label.__setitem__('image', image)
        label.image = image
        label.place(x=position[0], y=position[1])


    def select_image_file(self):
        file_types = [('PNG Image', '*.png'), ('Todos arquivos', '*')]
        dialog_box = tkFileDialog.Open(self, filetypes=file_types)

        file_name = dialog_box.show()
        self.file_name = file_name

        msg = 'Qual a largura desejada (em pixels) da imagem?\nO menor valor aceito é 20, e o maior, 200'
        image_width = self.text_dialog_box('Largura da imagem', msg)
        while not image_width.isdigit() or int(image_width) < 20 or int(image_width) > 200:
            msg = 'Valor Inválido! Os valores aceitos para largura (em pixels) vão de 20 a 200\nEntre com novo valor:'
            image_width = self.text_dialog_box('Largura da imagem', msg)
        msg = 'Qual a altura desejada (em pixels) da imagem?\nO menor valor aceito é 20, e o maior, 150'
        image_height = self.text_dialog_box('Altura da imagem', msg)
        while not image_height.isdigit() or int(image_height) < 20 or int(image_height) > 150:
            msg = 'Valor Inválido! Os valores aceitos para altura (em pixels) vão de 20 a 150\nEntre com novo valor:'
            image_height = self.text_dialog_box('Altura da imagem', msg)
        image_size = (int(image_width), int(image_height))

        if file_name is not None:
            logging.debug('Imagem selecionada: ' + file_name)

            file_names, results = create_images(file_name, image_size)

            self.load_image(file_names[0], (10, 50), self.img_labels[0])

            x_position = self.parent.size[0] / 2 - 200
            self.load_image(file_names[1], (x_position, 50), self.img_labels[1])

            print results
            self.draw_result(results)
        else:
            logging.debug('Nenhum arquivo de imagem foi selecionado')
Example #22
0
class Gui(Frame, threading.Thread):
  
    def __init__(self, parent):
        threading.Thread.__init__(self)
        Frame.__init__(self, parent)   
        self.parent = parent
        self.closeRequest = False
        
        self.initUI()
        self.start()
        
    
    def initUI(self):
        self.parent.title("Crazyflie Client")

        Label(self, text="Pitch").place(x=5, y=5)
        self.label_pitch = Label(self, text="0.00")
        self.label_pitch.place(x=60, y=5)
        
        Label(self, text="Roll").place(x=5, y=25)
        self.label_roll = Label(self, text="0.00")
        self.label_roll.place(x=60, y=25)
        
        Label(self, text="Yaw").place(x=5, y=50)
        self.label_yaw = Label(self, text="0.00")
        self.label_yaw.place(x=60, y=50)
        
        Label(self, text="Throttle").place(x=5, y=70)
        self.label_thrust = Label(self, text="0.00")
        self.label_thrust.place(x=60, y=70)
        
        self.canvas1 = Canvas(self, bg="#ddd", width=150, height=150)
        self.canvas1.place(x=395, y=25)
        
        self.canvas2 = Canvas(self, bg="#eee", width=340, height=280)
        self.canvas2.place(x=300, y=200)
        
        self.pack(fill=BOTH, expand=1)
        
    def onClose(self):
        self.closeRequest = True
        
    def drawCanvas1(self, status):
        self.canvas1.delete("all")
        
        max = 30.
        x = (status.roll / max) * 75 + 76
        y = (status.pitch / max) * 75 + 76
        
        w0 = 2
        w10 = 75 * 1 / 3.
        w20 = 75 * 2 / 3. 
        w30 = 75 * 3 / 3.
        self.canvas1.create_line(76, 0, 76, 150, fill="#bbb")
        self.canvas1.create_line(0, 76, 150, 76, fill="#bbb")
        self.canvas1.create_oval(76 - w0, 76 - w0, 76 + w0, 76 + w0, outline="#bbb")
        self.canvas1.create_oval(76 - w10, 76 - w10, 76 + w10, 76 + w10, outline="#bbb")
        self.canvas1.create_oval(76 - w20, 76 - w20, 76 + w20, 76 + w20, outline="#bbb")
        self.canvas1.create_oval(76 - w30, 76 - w30, 76 + w30, 76 + w30, outline="#bbb")
        
        self.canvas1.create_oval(x - 4, y - 4, x + 4, y + 4, fill="#000")
        
    
    def drawCanvas2(self, status):
        self.canvas2.delete("all")
        
        w = 40
        w2 = 80
        self.canvas2.create_rectangle(0 * w2, 0, w + 0 * w2, 200, outline="#aaa")
        self.canvas2.create_rectangle(1 * w2, 0, w + 1 * w2, 200, outline="#aaa")
        self.canvas2.create_rectangle(2 * w2, 0, w + 2 * w2, 200, outline="#aaa")
        self.canvas2.create_rectangle(3 * w2, 0, w + 3 * w2, 200, outline="#aaa")
        
        pixel_M1 = (status.motor_1 / 60000.) * 200
        pixel_M2 = (status.motor_2 / 60000.) * 200
        pixel_M3 = (status.motor_3 / 60000.) * 200
        pixel_M4 = (status.motor_4 / 60000.) * 200
        
        self.canvas2.create_rectangle(0 * w2, 200 - pixel_M1, w + 0 * w2, 200, fill="#0f0", outline="#0f0")
        self.canvas2.create_rectangle(1 * w2, 200 - pixel_M2, w + 1 * w2, 200, fill="#0f0", outline="#0f0")
        self.canvas2.create_rectangle(2 * w2, 200 - pixel_M3, w + 2 * w2, 200, fill="#0f0", outline="#0f0")
        self.canvas2.create_rectangle(3 * w2, 200 - pixel_M4, w + 3 * w2, 200, fill="#0f0", outline="#0f0")
    
        self.canvas2.create_rectangle(75, 230, 275, 270, outline="#aaa")
        pixel_bat = (status.bat / 4.) * 200
        self.canvas2.create_rectangle(75, 230, 75 + pixel_bat, 270, fill="#0f0", outline="#0f0")

    
    def run(self):
        while self.closeRequest == False:
            fc = flight.getFlightController()
            
            self.label_pitch.config(text="%2.2f" % fc.pitch)
            self.label_roll.config(text="%2.2f" % fc.roll)
            self.label_yaw.config(text="%2.2f" % fc.yawrate)
            self.label_thrust.config(text="%2.2f" % fc.throttle)
            
            self.drawCanvas1(flight.getCFStatus())
            self.drawCanvas2(flight.getCFStatus())
            
            time.sleep(0.05)
            
        self.quit()
Example #23
0
class liuyao:
	def __init__(self,root,gua64):
		self.cntoint={u'少阳-----':'1',u'少阴-- --':'2',u'老阳--O--':'3',u'老阴--X--':'4'}
		self.tfont=tkFont.Font(family='Fixdsys',size=25,weight=tkFont.BOLD)
		self.gfont=tkFont.Font(family='Fixdsys',size=13,weight=tkFont.BOLD)
		self.dgua=[] #动爻
		self.ygua=[] #原始卦
		self.bbgua=[] #变卦
		self.yguastr=[] #原始卦
		self.gua=[] #只有12的卦
		self.pabout=True #右键显示消失淮南标题
		self.guax=200
		self.guay=100
		self.liushen={'甲':0,'乙':0,'丙':1,'丁':1,'戊':2,'己':3,'庚':4,'辛':4,'壬':5,'癸':5}
		self.liushencn=['青龙','朱雀','勾陈','腾蛇','白虎','玄武']
		self.tiangan={'甲':1,'乙':2,'丙':3,'丁':4,'戊':5,'己':6,'庚':7,'辛':8,'壬':9,'癸':10}
		self.dizhi={'子':1,'丑':2,'寅':3,'卯':4,'辰':5,'巳':6,'午':7,'未':8,'申':9,'酉':10,'戌':11,'亥':12}
		self.kongwangzu=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥']
		self.root=root
		self.root.title(u'===六爻排盘===[淮南内部专用]')
		self.root.minsize(550,380)
		self.root.maxsize(550,380)
		self.canvas=Canvas(root,width=460,height=380,bg='gray')
		# self.picyang=PhotoImage(file='tk\\yang.gif')
		# self.picyin=PhotoImage(file='tk\\yin.gif')
		self.canvas.place(relx=0,rely=0)
		self.com={}
		for i in xrange(6):
			self.com[i]=Combobox(root,state='readonly')
			self.com[i]['values']=(u'少阳-----',u'少阴-- --',u'老阳--O--',u'老阴--X--')
			self.com[i].current(0)
			self.com[i].place(relx=0.85,rely=0.36-0.07*i,width=80)


		bt1=Button(self.root,text=u'排盘',command=self.paipan)
		bt2=Button(self.root,text=u'清除',command=self.cls)
		l1=Label(self.root,text=u'右键水印')
		l1.place(x=480,y=327)
		# bt1.place(relx=0.85,rely=0.35+0.7)
		# bt1.pack(side='right')
		bt1.place(x=467,y=170,width=78)
		bt2.place(x=467,y=350,width=78)
		self.date() #干支
		#===========================
		self.root.bind('<Button-3>',self.about)
	def cls(self):
		self.canvas.delete('pic')   #删除所有上次产生的ITEMS
		self.canvas.delete('liushen')



	def liushenf(self):  #配六神
		xu=self.liushen[self.ritian.encode('utf-8')]
		for i in xrange(6):
			self.canvas.create_text(self.guax-170,100+150-30*i,font=self.gfont,text=self.liushencn[xu],tag='liushen')
			xu+=1
			if xu>5:
				xu-=6

	def date(self):
		turl=urllib2.urlopen('http://www.nongli.com/item4/index.asp',timeout=10).read()
		soup=BeautifulSoup(turl)
		zu=soup.findAll('td',{'width':'74%','bgcolor':'#FFFFFF'})[1].text
		# print zu
		wanzu=[] #wanzu里面是完成的年月日干支
		wanzu.append(zu.split(' ')[0])
		wanzu.append(zu.split(' ')[2])
		wanzu.append(zu.split(' ')[3])
		for i in xrange(3):
			# print u'干支',wanzu[i]
			self.canvas.create_text(self.guax-90+60*i,30,text=wanzu[i],font=self.gfont,tag='riqi')
		ri=wanzu[2]
		self.ritian=list(ri)[0]
		self.ridi=list(ri)[1]
		self.kongwang()

	def kongwang(self):
		# print u'日干支:',self.ridi,self.ritian
		cha=self.dizhi[self.ridi.encode('utf-8')]-self.tiangan[self.ritian.encode('utf-8')]
		if cha<0:
			cha+=+10
		self.canvas.create_text(self.guax-90+120+30,30,font=self.gfont,text='(',tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+15,30,font=self.gfont,text=self.kongwangzu[cha-2],tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+30,30,font=self.gfont,text=self.kongwangzu[cha-1],tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+45,30,font=self.gfont,text=')',tag='riqi')

	def about(self,event):
		if self.pabout:
			self.canvas.create_text(self.guax,100+250,text='淮南法教专用水印',fill='tan',font=self.tfont,tag='about')
			self.canvas.create_text(self.guax+140,370,text='--无名',fill='tan',tag='about')
			self.pabout=False
		else:
			self.canvas.delete('about')
			self.pabout=True


	def paipan(self):
		for i in xrange(6):
			self.ygua.append(self.cntoint[self.com[i].get()]) #得到原始爻名,转换为1234,添加入gua
		self.gua=self.ygua
		bbgua=self.gua
		print '======================='
		print 'sel.gua',self.gua
		for i in xrange(6):
			if self.ygua[i]=='3':
				self.gua[i]='1'
				self.dgua.append(str(i))
				self.dgua.append('1') 
			elif  self.ygua[i]=='4':
				self.gua[i]='2'
				self.dgua.append(str(i))
				self.dgua.append('2')
		self.guastr=''.join(self.gua)
		# print u'变卦',bbgua
		# print u'字符串卦数',self.guastr
		# print u'数列卦',self.gua
		# print u'动卦',self.dgua
		# print gua64[guastr]
		self.draw()
		self.liushenf()#六神


	def draw(self):
		self.canvas.delete('pic')   #删除所有上次产生的ITEMS
		self.canvas.delete('liushen')
		# print u'当前itme数',self.canvas.find_all()
		#本卦
		for i in xrange(6):
			if self.gua[i]=='1':
				# self.canvas.create_image(self.guax,100+150-30*i,image=self.picyang,tag='pic')
				self.canvas.create_text(self.guax,95+150-30*i,text='▅▅▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic')
			else:
				# self.canvas.create_image(self.guax,100+150-30*i,image=self.picyin,tag='pic')	
				self.canvas.create_text(self.guax,95+150-30*i,text='▅  ▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic')
		
				#下面是六亲
		for i in xrange(6):
			self.canvas.create_text(self.guax-70,100+30*i,font=self.gfont,text=gua64[self.guastr][i],tag='pic')

			#动爻标记
		for i in xrange(0,len(self.dgua),2):
			if self.dgua[i+1]=='1':
				self.canvas.create_text(self.guax+70,247-30*int(self.dgua[i]),font=self.gfont,text='O',tag='pic',fill='red')
			else:
				self.canvas.create_text(self.guax+70,247-30*int(self.dgua[i]),font=self.gfont,text='X',tag='pic',fill='red')
			#世
		syw=gua64[self.guastr][6]
		self.canvas.create_text(self.guax+55,280-30*syw,font=self.gfont,text='世',tag='pic')
			#应
		yyw=gua64[self.guastr][7]
		self.canvas.create_text(self.guax+55,280-30*yyw,font=self.gfont,text='应',tag='pic')
			#六合、冲
		hc=gua64[self.guastr][8]
		self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=hc,tag='pic')
			#游魂、归魂
		zg=gua64[self.guastr][9]
		self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=zg,tag='pic')
			#卦宫
		gg=gua64[self.guastr][10]
		self.canvas.create_text(self.guax,100-30,font=self.gfont,text=gg,tag='pic')
		#变卦	
		self.biangua()
		self.guastr=''
		self.dgua=[] #动爻
		self.ygua=[] #原始卦
		self.bbgua=[] #变卦
		self.yguastr=[] #原始卦
		self.gua=[] #只有12的卦

	def biangua(self):
		self.bbgua=self.gua
		# print 'biangua',self.bbgua
		'''
sel.gua ['4', '4', '3', '3', '4', '3']
字符串卦数 221121
数列卦 ['2', '2', '1', '1', '2', '1']
动卦 ['0', '2', '1', '2', '2', '1', '3', '1', '4', '2', '5', '1']
当前itme数 (1, 2, 3, 4, 5, 6, 7)
biangua ['1', '1', '2', '2', '1', '2']
bguastr 112212
		'''
		for i in xrange(0,len(self.dgua),2):
			if self.dgua[i+1]=='1':
				self.bbgua[int(self.dgua[i])]='2'
			else:
				self.bbgua[int(self.dgua[i])]='1'
		print 'biangua',self.bbgua
		self.bguastr=''.join(self.bbgua)
		print 'bguastr',self.bguastr
		for i in xrange(6):
			if self.bbgua[i]=='1':
				# self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyang,tag='pic')
				self.canvas.create_text(self.guax+130,95+150-30*i,text=u'▅▅▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic')
			else:
				# self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyin,tag='pic')
				self.canvas.create_text(self.guax+130,95+150-30*i,text=u'▅  ▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic')
						#下面是六亲
		for i in xrange(6):
			self.canvas.create_text(self.guax+200,100+30*i,font=self.gfont,text=gua64[self.bguastr][i],tag='pic')
Example #24
0
class LeftNavView(Canvas):

    def __init__(self, controller, parent):     # prev: def __init__(self, main_window, player_, left_nav):
        self.controller = controller
        self.parent = parent
        self.app = self.parent.app
        self.enabled = False

    def build(self):

        if self.enabled:
            self.redraw()
        else:
            self.build_left_nav_menu()
            self.enabled = True

    def build_left_nav_menu(self):

        app = self.app
        main_window = self.app.main_controller.view
        player = self.app.game.player

        # global left_nav, left_canvas, left

        left_nav = Frame(main_window, height=main_window.sh, width=200, background=app.conf.left_nav_background)
        left_nav.place(x=0, y=0)

        # left = LeftNav(main_window, player, left_nav)

        self.selected_planet = player.selected_planet
        if isset(player.selected_ship):
            self.selected_ship_name = player.selected_ship.name
        else:
            self.selected_ship_name = ""

        self.main_window = main_window
        self.selected_ship_id = 0

        self.planet_images = []

        self.left_canvas = Canvas(left_nav)
        self.left_canvas.config(background=app.conf.left_nav_background, highlightthickness=0, height=main_window.sh, width=200)
        self.left_canvas.place(x=0, y=0)

        if app.conf.debug_lines == 1:
            self.left_canvas.create_line(0, 0, 200, main_window.sh, fill='red')
            self.left_canvas.create_line(200, 0, 0, main_window.sh, fill='red')

        # left nav values

        self.logo_image = Image.open(app.conf.title_image_path)
        self.logo_image.thumbnail([198, 48], Image.ANTIALIAS)
        self.logo_image_res = ImageTk.PhotoImage(self.logo_image)
        self.new_planet_image = self.logo_image_res
        self.planet_images.append(self.new_planet_image)
        self.label_logo = Label(self.left_canvas, image=self.logo_image_res)
        self.label_logo.config(background=app.conf.left_nav_background)
        self.label_logo.planet_image_res = self.logo_image_res           # keep a reference!
        self.label_logo.place(anchor='n', x=100, y=0)

        # Resources Set
        row = 0
        self.resources_start_y = 55
        self.resources_canvas = Canvas(self.left_canvas)
        self.resources_canvas.config(background=app.conf.left_nav_background,
                                     width=198,
                                     highlightthickness=0,
                                     border=0)
        self.resources_canvas.grid_propagate(False)

        self.resources_canvas.place(anchor='nw', x=0, y=self.resources_start_y)
        self.label_resources = Label(self.resources_canvas, text="Resources:", fg=app.conf.main_text_color)
        self.label_resources.config(background=app.conf.left_nav_background)
        self.label_resources.grid(row=row, column=0, sticky='w')
        row += 1
        self.label_planets = Label(self.resources_canvas, text="Planets:", fg=app.conf.second_text_color)
        self.label_planets.config(background=app.conf.left_nav_background)
        self.label_planets.grid(row=row, column=0, sticky='w')
        self.label_planets_val = Label(self.resources_canvas, text=str(len(player.owned_planets))
                                       , fg=app.conf.second_text_color)
        self.label_planets_val.config(background=app.conf.left_nav_background)
        self.label_planets_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_ships = Label(self.resources_canvas, text="Ships:", fg=app.conf.second_text_color)
        self.label_ships.config(background=app.conf.left_nav_background)
        self.label_ships.grid(row=row, column=0, sticky='w')
        self.label_ships_val = Label(self.resources_canvas, text=len(player.ships), fg=app.conf.second_text_color)
        self.label_ships_val.config(background=app.conf.left_nav_background)
        self.label_ships_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_allies = Label(self.resources_canvas, text="Allies:", fg=app.conf.second_text_color)
        self.label_allies.config(background=app.conf.left_nav_background)
        self.label_allies.grid(row=row, column=0, sticky='w')
        self.label_allies_val = Label(self.resources_canvas, text=len(player.allies), fg=app.conf.second_text_color)
        self.label_allies_val.config(background=app.conf.left_nav_background)
        self.label_allies_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_enemies = Label(self.resources_canvas, text="Enemies:", fg=app.conf.second_text_color)
        self.label_enemies.config(background=app.conf.left_nav_background)
        self.label_enemies.grid(row=row, column=0, sticky='w')
        self.label_enemies_val = Label(self.resources_canvas, text=len(player.enemies), fg=app.conf.second_text_color)
        self.label_enemies_val.config(background=app.conf.left_nav_background)
        self.label_enemies_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_separator = Label(self.resources_canvas, text="", fg=app.conf.left_nav_background, width=24)
        self.label_separator.config(background=app.conf.left_nav_background)
        self.label_separator.grid(row=row, columnspan=2, sticky='e,w')

        # left nav buttons
        self.left_buttons_start_y = main_window.sh-112
        if self.left_buttons_start_y < 500:
            self.left_buttons_start_y = 500

        self.left_buttons_canvas = Canvas(self.left_canvas)
        self.left_buttons_canvas.config(background=app.conf.left_nav_background,
                                        height=200,
                                        width=200,
                                        highlightthickness=0,
                                        border=0)
        self.left_buttons_canvas.place(anchor='n', x=100, y=self.left_buttons_start_y)

        self.button_next_planet = Button(self.left_buttons_canvas, text="Next Planet", padx=60
                                         , highlightbackground=app.conf.left_nav_background)
        self.button_next_ship = Button(self.left_buttons_canvas, text="Next Ship"
                                       , highlightbackground=app.conf.left_nav_background)
        self.button_home_planet = Button(self.left_buttons_canvas, text="Home Planet"
                                         , highlightbackground=app.conf.left_nav_background)
        self.button_end_turn = Button(self.left_buttons_canvas, text="End Turn"
                                      , highlightbackground=app.conf.left_nav_background)
        self.button_next_planet.bind("<Button-1>", self.controller.button_next_planet_clicked)
        self.button_next_ship.bind("<Button-1>", self.controller.button_next_ship_clicked)
        self.button_home_planet.bind("<Button-1>", self.controller.button_home_planet_clicked)
        self.button_end_turn.bind("<Button-1>", self.controller.button_end_turn_clicked)
        self.button_next_planet.grid(row=0, column=0, sticky='w,e')
        self.button_next_ship.grid(row=1, column=0, sticky='w,e')
        self.button_home_planet.grid(row=2, column=0, sticky='w,e')
        self.button_end_turn.grid(row=3, column=0, sticky='w,e')

        # Planet Info Set

        row = 0
        self.planet_info_start_y = self.resources_start_y + 115
        self.planet_info_canvas = Canvas(self.left_canvas)
        self.planet_info_canvas.config(background=app.conf.left_nav_background,
                                       width=198,
                                       highlightthickness=0,
                                       border=0)
        self.planet_info_canvas.grid_propagate(False)
        self.planet_info_canvas.place(anchor='nw', x=0, y=self.planet_info_start_y)
        self.label_planet_info = Label(self.planet_info_canvas, text="Planet Info:", fg=app.conf.main_text_color)
        self.label_planet_info.config(background=app.conf.left_nav_background)
        self.label_planet_info.grid(row=row, column=0, sticky='w')
        row += 1
        self.label_planet_name = Label(self.planet_info_canvas, text="Name:", fg=app.conf.second_text_color)
        self.label_planet_name.config(background=app.conf.left_nav_background)
        self.label_planet_name.grid(row=row, column=0, sticky='w')
        self.label_planet_name_val = Label(self.planet_info_canvas, text=str(player.selected_planet.name)
                                           , fg=app.conf.second_text_color)
        self.label_planet_name_val.config(background=app.conf.left_nav_background)
        self.label_planet_name_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_metals = Label(self.planet_info_canvas, text="Metals:", fg=app.conf.second_text_color)
        self.label_planet_metals.config(background=app.conf.left_nav_background)
        self.label_planet_metals.grid(row=row, column=0, sticky='w')
        self.label_planet_metals_val = Label(self.planet_info_canvas, text=str(player.selected_planet.metals)
                                             , fg=app.conf.second_text_color)
        self.label_planet_metals_val.config(background=app.conf.left_nav_background)
        self.label_planet_metals_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_food = Label(self.planet_info_canvas, text="Food:", fg=app.conf.second_text_color)
        self.label_planet_food.config(background=app.conf.left_nav_background)
        self.label_planet_food.grid(row=row, column=0, sticky='w')
        self.label_planet_food_val = Label(self.planet_info_canvas, text=str(player.selected_planet.food)
                                           , fg=app.conf.second_text_color)
        self.label_planet_food_val.config(background=app.conf.left_nav_background)
        self.label_planet_food_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_terrain = Label(self.planet_info_canvas, text="Terrain:", fg=app.conf.second_text_color)
        self.label_planet_terrain.config(background=app.conf.left_nav_background)
        self.label_planet_terrain.grid(row=row, column=0, sticky='w')
        self.label_planet_terrain_val = Label(self.planet_info_canvas, text=str(get_terrain(player.selected_planet.terrain))
                                              , fg=app.conf.second_text_color)
        self.label_planet_terrain_val.config(background=app.conf.left_nav_background)
        self.label_planet_terrain_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_separator_p = Label(self.planet_info_canvas, text="", fg=app.conf.left_nav_background, width=24)
        self.label_separator_p.config(background=app.conf.left_nav_background)
        self.label_separator_p.grid(row=row, columnspan=2, sticky='e,w')

        # ship info

        row = 0
        self.ship_select_start_y = self.planet_info_start_y + 115
        self.ship_select_canvas = Canvas(self.left_canvas)
        self.ship_select_canvas.config(background=app.conf.left_nav_background,
                                       width=198,
                                       highlightthickness=0,
                                       border=0)
        self.ship_select_canvas.grid_propagate(False)
        self.ship_select_canvas.place(anchor='nw', x=0, y=self.ship_select_start_y)
        self.label_ship_select = Label(self.ship_select_canvas, text="Select Ship:", fg=app.conf.main_text_color)
        self.label_ship_select.config(background=app.conf.left_nav_background)
        self.label_ship_select.grid(row=row, column=0, sticky='w')

        # future implementation

        # if selected_ship.name != '':
        if isset(self.selected_ship_name):

            if app.conf.debug == 1:
                print "Showing Selected Ship (init)"

            current_ship = player.get_ship(self.selected_ship_name)

            row += 1
            self.listbox_ship = Listbox(self.ship_select_canvas, width=198
                                        , background=app.conf.alternate_left_nav_background, borderwidth=1)
            self.listbox_ship.config(selectmode=SINGLE)
            for ship in player.ships:
                self.listbox_ship.insert(END, ship.name)
            self.listbox_ship.selection_set(self.selected_ship_id)
            self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e')
            self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list)

            row = 0
            self.ship_info_start_y = self.ship_select_start_y + 200
            self.ship_info_canvas = Canvas(self.left_canvas)
            self.ship_info_canvas.config(background=app.conf.left_nav_background,
                                         width=198,
                                         highlightthickness=0,
                                         border=0)
            self.ship_info_canvas.grid_propagate(False)
            self.ship_info_canvas.place(anchor='nw', x=0, y=self.ship_info_start_y)
            self.label_ship_info = Label(self.ship_info_canvas, text="Ship Info:", fg=app.conf.main_text_color)
            self.label_ship_info.config(background=app.conf.left_nav_background)
            self.label_ship_info.grid(row=row, column=0, sticky='w')

            row += 1
            self.label_ship_name = Label(self.ship_info_canvas, text="Name:", fg=app.conf.second_text_color)
            self.label_ship_name.config(background=app.conf.left_nav_background)
            self.label_ship_name.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_name_val = Label(self.ship_info_canvas, text=current_ship.name
                                             , fg=app.conf.second_text_color)
            self.label_ship_name_val.config(background=app.conf.left_nav_background)
            self.label_ship_name_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_ship_attack = Label(self.ship_info_canvas, text="Attack:", fg=app.conf.second_text_color)
            self.label_ship_attack.config(background=app.conf.left_nav_background)
            self.label_ship_attack.grid(row=row, column=0, sticky='w')
            self.label_ship_attack_val = Label(self.ship_info_canvas, text=current_ship.attack
                                             , fg=app.conf.second_text_color)
            self.label_ship_attack_val.config(background=app.conf.left_nav_background)
            self.label_ship_attack_val.grid(row=row, column=1, sticky='e')
            self.label_ship_defense = Label(self.ship_info_canvas, text="Defense:", fg=app.conf.second_text_color)
            self.label_ship_defense.config(background=app.conf.left_nav_background)
            self.label_ship_defense.grid(row=row, column=2, sticky='w')
            self.label_ship_defense_val = Label(self.ship_info_canvas, text=current_ship.defense
                                             , fg=app.conf.second_text_color)
            self.label_ship_defense_val.config(background=app.conf.left_nav_background)
            self.label_ship_defense_val.grid(row=row, column=3, sticky='e')

            row += 1
            self.label_ship_storage = Label(self.ship_info_canvas, text="Storage:", fg=app.conf.second_text_color)
            self.label_ship_storage.config(background=app.conf.left_nav_background)
            self.label_ship_storage.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_storage_val = Label(self.ship_info_canvas, text=current_ship.storage
                                             , fg=app.conf.second_text_color)
            self.label_ship_storage_val.config(background=app.conf.left_nav_background)
            self.label_ship_storage_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_ship_seats = Label(self.ship_info_canvas, text="Seats:", fg=app.conf.second_text_color)
            self.label_ship_seats.config(background=app.conf.left_nav_background)
            self.label_ship_seats.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_seats_val = Label(self.ship_info_canvas, text=current_ship.seats
                                             , fg=app.conf.second_text_color)
            self.label_ship_seats_val.config(background=app.conf.left_nav_background)
            self.label_ship_seats_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_separator_s = Label(self.ship_info_canvas, text="", fg=app.conf.left_nav_background, width=24)
            self.label_separator_s.config(background=app.conf.left_nav_background)
            self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w')

        else:

            if app.conf.debug == 1:
                print "No Selected Ship Detected (init)"

            row += 1
            self.listbox_ship = Listbox(self.ship_select_canvas, width=198
                                        , background=app.conf.alternate_left_nav_background, borderwidth=1)
            for ship in player.ships:
                self.listbox_ship.insert(END, ship.name)
            self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e')
            self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list)
            row += 1
            self.label_ship_name = Label(self.ship_select_canvas, text="No Ship Selected", fg=app.conf.second_text_color)
            self.label_ship_name.config(background=app.conf.left_nav_background)
            self.label_ship_name.grid(row=row, columnspan=4, sticky='w')

            row += 1
            self.label_separator_s = Label(self.ship_select_canvas, text="", fg=app.conf.left_nav_background, width=24)
            self.label_separator_s.config(background=app.conf.left_nav_background)
            self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w')

        if app.conf.debug == 1:
            print "CreatedLine:", 0, " ", 0, " ", main_window.sw-200, " ", main_window.sh-200
            print "CreatedLine:", main_window.sw-200, " ", 0, " ", 0, " ", main_window.sh-200
            print "CurrWin0:", convert_coords_x(main_window, 0), convert_coords_y(main_window, 0)

        if app.conf.debug == 1:
            print "Displayed: left_nav,", main_window.sh, ",200"

    def poll_ship_list(self, event):

        w = event.widget
        index = int(w.curselection()[0])
        new_ship_name = w.get(index)
        if isset(self.selected_ship_name):
            if self.selected_ship_name == "":
                if new_ship_name != self.selected_ship_name:
                    self.ship_selction_has_changed(new_ship_name)
                    self.selected_ship_name = new_ship_name
                    self.selected_ship_id = w.curselection()
                    if app.conf.debug == 1:
                        print "SelectedShip:", self.selected_ship_name
                    self.redraw(self.main_window, self.player)
        else:
            self.selected_ship_name = new_ship_name
            self.selected_ship_id = w.curselection()
            self.app.debug(("SelectedShip:", self.selected_ship_name))
            self.redraw()

    def redraw(self):

        app = self.app
        main_window = app.main_controller.view
        player = app.game.player

        self.player = player

        app.debug("Redrawing Left Nav")

        self.label_logo.place(anchor='n', x=100, y=0)
        self.resources_canvas.config(background=app.conf.left_nav_background,
                                     height=main_window.sh-self.resources_start_y-202,
                                     width=198,
                                     highlightthickness=0,
                                     border=0)
        self.resources_canvas.place(anchor='nw', x=0, y=self.resources_start_y)
        row = 0
        self.label_resources.grid(row=row, column=0, sticky='w')
        row += 1
        self.label_planets.grid(row=row, column=0, sticky='w')
        self.label_planets_val.config(text=str(len(player.owned_planets)))
        self.label_planets_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_ships.grid(row=row, column=0, sticky='w')
        self.label_ships_val.config(text=len(player.ships))
        self.label_ships_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_allies.grid(row=row, column=0, sticky='w')
        self.label_allies_val.config(text=len(player.allies))
        self.label_allies_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_enemies.grid(row=row, column=0, sticky='w')
        self.label_enemies_val.config(text=len(player.enemies))
        self.label_enemies_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_separator.grid(row=row, columnspan=2, sticky='e,w')

        # left nav buttons

        self.left_buttons_start_y = main_window.sh-112
        if self.left_buttons_start_y < 500:
            self.left_buttons_start_y = 500
        self.left_buttons_canvas.place(anchor='n', x=100, y=self.left_buttons_start_y)
        self.button_next_planet.grid(row=0, column=0, sticky='w,e')
        self.button_next_ship.grid(row=1, column=0, sticky='w,e')
        self.button_home_planet.grid(row=2, column=0, sticky='w,e')
        self.button_end_turn.grid(row=3, column=0, sticky='w,e')

        app.debug(("Left Buttons Start Y:", self.left_buttons_start_y))

        # Planet Info Set

        row = 0
        self.planet_info_start_y = self.resources_start_y + 115
        self.planet_info_canvas.place(anchor='nw', x=0, y=self.planet_info_start_y)
        self.label_planet_info.grid(row=row, column=0, sticky='w')
        row += 1
        self.label_planet_name.grid(row=row, column=0, sticky='w')
        self.label_planet_name_val.config(text=str(player.selected_planet.name))
        self.label_planet_name_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_metals.grid(row=row, column=0, sticky='w')
        self.label_planet_metals_val.config(text=str(player.selected_planet.metals))
        self.label_planet_metals_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_food.grid(row=row, column=0, sticky='w')
        self.label_planet_food_val.config(text=str(player.selected_planet.food))
        self.label_planet_food_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_planet_terrain.grid(row=row, column=0, sticky='w')
        self.label_planet_terrain_val.config(text=str(get_terrain(player.selected_planet.terrain)))
        self.label_planet_terrain_val.grid(row=row, column=1, sticky='e')
        row += 1
        self.label_separator_p.grid(row=row, columnspan=2, sticky='e,w')

        # prep for ship section

        if isset(self.ship_select_canvas):
            self.ship_select_canvas.destroy()

        # ship info

        row = 0
        self.ship_select_start_y = self.planet_info_start_y + 115
        self.ship_select_canvas = Canvas(self.left_canvas)
        self.ship_select_canvas.config(background=app.conf.left_nav_background,
                                       width=198,
                                       highlightthickness=0,
                                       border=0)
        self.ship_select_canvas.grid_propagate(False)
        self.ship_select_canvas.place(anchor='nw', x=0, y=self.ship_select_start_y)
        self.label_ship_select = Label(self.ship_select_canvas, text="Select Ship:", fg=app.conf.main_text_color)
        self.label_ship_select.config(background=app.conf.left_nav_background)
        self.label_ship_select.grid(row=row, column=0, sticky='w')

        # future implementation

        # if selected_ship.name != '':
        if self.selected_ship_name != "":

            app.debug("Showing Selected Ship (redraw)")

            current_ship = player.get_ship(self.selected_ship_name)

            row += 1
            self.listbox_ship = Listbox(self.ship_select_canvas, width=198
                                        , background=app.conf.alternate_left_nav_background, borderwidth=1)
            self.listbox_ship.config(selectmode=SINGLE)
            for ship in player.ships:
                self.listbox_ship.insert(END, ship.name)
            self.listbox_ship.selection_set(self.selected_ship_id)
            self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e')
            self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list)

            row = 0
            self.ship_info_start_y = self.ship_select_start_y + 200
            self.ship_info_canvas = Canvas(self.left_canvas)
            self.ship_info_canvas.config(background=app.conf.left_nav_background,
                                         width=198,
                                         highlightthickness=0,
                                         border=0)
            self.ship_info_canvas.grid_propagate(False)
            self.ship_info_canvas.place(anchor='nw', x=0, y=self.ship_info_start_y)
            self.label_ship_info = Label(self.ship_info_canvas, text="Ship Info:", fg=app.conf.main_text_color)
            self.label_ship_info.config(background=app.conf.left_nav_background)
            self.label_ship_info.grid(row=row, column=0, sticky='w')

            row += 1
            self.label_ship_name = Label(self.ship_info_canvas, text="Name:", fg=app.conf.second_text_color)
            self.label_ship_name.config(background=app.conf.left_nav_background)
            self.label_ship_name.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_name_val = Label(self.ship_info_canvas, text=current_ship.name
                                             , fg=app.conf.second_text_color)
            self.label_ship_name_val.config(background=app.conf.left_nav_background)
            self.label_ship_name_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_ship_attack = Label(self.ship_info_canvas, text="Attack:", fg=app.conf.second_text_color)
            self.label_ship_attack.config(background=app.conf.left_nav_background)
            self.label_ship_attack.grid(row=row, column=0, sticky='w')
            self.label_ship_attack_val = Label(self.ship_info_canvas, text=current_ship.attack
                                             , fg=app.conf.second_text_color)
            self.label_ship_attack_val.config(background=app.conf.left_nav_background)
            self.label_ship_attack_val.grid(row=row, column=1, sticky='e')
            self.label_ship_defense = Label(self.ship_info_canvas, text="Defense:", fg=app.conf.second_text_color)
            self.label_ship_defense.config(background=app.conf.left_nav_background)
            self.label_ship_defense.grid(row=row, column=2, sticky='w')
            self.label_ship_defense_val = Label(self.ship_info_canvas, text=current_ship.defense
                                             , fg=app.conf.second_text_color)
            self.label_ship_defense_val.config(background=app.conf.left_nav_background)
            self.label_ship_defense_val.grid(row=row, column=3, sticky='e')

            row += 1
            self.label_ship_storage = Label(self.ship_info_canvas, text="Storage:", fg=app.conf.second_text_color)
            self.label_ship_storage.config(background=app.conf.left_nav_background)
            self.label_ship_storage.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_storage_val = Label(self.ship_info_canvas, text=current_ship.storage
                                             , fg=app.conf.second_text_color)
            self.label_ship_storage_val.config(background=app.conf.left_nav_background)
            self.label_ship_storage_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_ship_seats = Label(self.ship_info_canvas, text="Seats:", fg=app.conf.second_text_color)
            self.label_ship_seats.config(background=app.conf.left_nav_background)
            self.label_ship_seats.grid(row=row, column=0, columnspan=2, sticky='w')
            self.label_ship_seats_val = Label(self.ship_info_canvas, text=current_ship.seats
                                             , fg=app.conf.second_text_color)
            self.label_ship_seats_val.config(background=app.conf.left_nav_background)
            self.label_ship_seats_val.grid(row=row, column=2, columnspan=2, sticky='e')

            row += 1
            self.label_separator_s = Label(self.ship_info_canvas, text="", fg=app.conf.left_nav_background, width=24)
            self.label_separator_s.config(background=app.conf.left_nav_background)
            self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w')

        else:

            app.debug("No Selected Ship Detected (redraw)")

            row += 1
            self.listbox_ship = Listbox(self.ship_select_canvas, width=198
                                        , background=app.conf.alternate_left_nav_background, borderwidth=1)
            for ship in player.ships:
                self.listbox_ship.insert(END, ship.name)
            self.listbox_ship.grid(row=row, columnspan=2, sticky='w,e')
            self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list)
            row += 1
            self.label_ship_name = Label(self.ship_select_canvas, text="No Ship Selected", fg=app.conf.second_text_color)
            self.label_ship_name.config(background=app.conf.left_nav_background)
            self.label_ship_name.grid(row=row, columnspan=2, sticky='w')

            row += 1
            self.label_separator_s = Label(self.ship_select_canvas, text="", fg=app.conf.left_nav_background, width=24)
            self.label_separator_s.config(background=app.conf.left_nav_background)
            self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w')
Example #25
0
class histogramWidget:
    BACKGROUND = "#222222"
    EDGE_HISTOGRAM_COLOR = "#999999"
    NODE_HISTOGRAM_COLOR = "#555555"
    TOOLTIP_COLOR="#FFFF55"
    
    PADDING = 8
    CENTER_WIDTH = 1
    CENTER_COLOR = "#444444"
    ZERO_GAP = 1
    UPDATE_WIDTH = 9
    UPDATE_COLOR = "#FFFFFF"
    HANDLE_WIDTH = 5
    HANDLE_COLOR = "#FFFFFF"
    HANDLE_LENGTH = (HEIGHT-2*PADDING)
    TICK_COLOR = "#FFFFFF"
    TICK_WIDTH = 10
    TICK_FACTOR = 2
    
    LOG_BASE = 10.0
    
    def __init__(self, parent, x, y, width, height, data, logScale=False, callback=None):
        self.canvas = Canvas(parent,background=histogramWidget.BACKGROUND, highlightbackground=histogramWidget.BACKGROUND,width=width,height=height)
        self.canvas.place(x=x,y=y,width=width,height=height,bordermode="inside")
        
        self.logScale = logScale
        
        self.callback = callback
        
        self.edgeBars = []
        self.nodeBars = []
        
        self.binValues = []
        self.numBins = len(data) - 1
        
        self.currentBin = self.numBins     # start the slider at the highest bin
        
        edgeRange = 0.0
        nodeRange = 0.0
        
        for values in data.itervalues():
            if values[0] > edgeRange:
                edgeRange = values[0]
            if values[1] > nodeRange:
                nodeRange = values[1]
        
        edgeRange = float(edgeRange)    # ensure that it will yield floats when used in calculations...
        nodeRange = float(nodeRange)
        
        if logScale:
            edgeRange = math.log(edgeRange,histogramWidget.LOG_BASE)
            nodeRange = math.log(nodeRange,histogramWidget.LOG_BASE)
        
        # calculate the center line - but don't draw it yet
        self.center_x = histogramWidget.PADDING
        if self.logScale:
            self.center_x += histogramWidget.TICK_WIDTH+histogramWidget.PADDING
        self.center_y = height/2
        self.center_x2 = width-histogramWidget.PADDING
        self.center_y2 = self.center_y + histogramWidget.CENTER_WIDTH
        
        # draw the histograms with background-colored baseline rectangles (these allow tooltips to work on very short bars with little area)
        self.bar_interval = float(self.center_x2 - self.center_x) / (self.numBins+1)
        bar_x = self.center_x
        edge_y2 = self.center_y-histogramWidget.PADDING
        edge_space = edge_y2-histogramWidget.PADDING
        node_y = self.center_y2+histogramWidget.PADDING
        node_space = (height-node_y)-histogramWidget.PADDING
        
        thresholds = sorted(data.iterkeys())
        for threshold in thresholds:
            self.binValues.append(threshold)
            edgeWeight = data[threshold][0]
            nodeWeight = data[threshold][1]
            if logScale:
                if edgeWeight > 0:
                    edgeWeight = math.log(edgeWeight,histogramWidget.LOG_BASE)
                else:
                    edgeWeight = 0
                if nodeWeight > 0:
                    nodeWeight = math.log(nodeWeight,histogramWidget.LOG_BASE)
                else:
                    nodeWeight = 0
            
            bar_x2 = bar_x + self.bar_interval
            
            edge_y = histogramWidget.PADDING + int(edge_space*(1.0-edgeWeight/edgeRange))
            edge = self.canvas.create_rectangle(bar_x,edge_y,bar_x2,edge_y2,fill=histogramWidget.EDGE_HISTOGRAM_COLOR,width=0)
            baseline = self.canvas.create_rectangle(bar_x,edge_y2+histogramWidget.ZERO_GAP,bar_x2,edge_y2+histogramWidget.PADDING,fill=histogramWidget.BACKGROUND,width=0)
            self.canvas.addtag_withtag("Threshold: %f" % threshold,edge)
            self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],edge)
            self.canvas.tag_bind(edge,"<Enter>",self.updateToolTip)
            self.canvas.tag_bind(edge,"<Leave>",self.updateToolTip)
            self.edgeBars.append(edge)
            self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline)
            self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],baseline)
            self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip)
            self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip)
            
            node_y2 = node_y + int(node_space*(nodeWeight/nodeRange))
            node = self.canvas.create_rectangle(bar_x,node_y,bar_x2,node_y2,fill=histogramWidget.NODE_HISTOGRAM_COLOR,width=0)
            baseline = self.canvas.create_rectangle(bar_x,node_y-histogramWidget.PADDING,bar_x2,node_y-histogramWidget.ZERO_GAP,fill=histogramWidget.BACKGROUND,width=0)
            self.canvas.addtag_withtag("Threshold: %f" % threshold,node)
            self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],node)
            self.canvas.tag_bind(node,"<Enter>",self.updateToolTip)
            self.canvas.tag_bind(node,"<Leave>",self.updateToolTip)
            self.nodeBars.append(node)
            self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline)
            self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],baseline)
            self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip)
            self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip)
            
            bar_x = bar_x2
        
        # now draw the center line
        self.centerLine = self.canvas.create_rectangle(self.center_x,self.center_y,self.center_x2,self.center_y2,fill=histogramWidget.CENTER_COLOR,width=0)
        
        # draw the tick marks if logarithmic
        if self.logScale:
            tick_x = histogramWidget.PADDING
            tick_x2 = histogramWidget.PADDING+histogramWidget.TICK_WIDTH
            
            start_y = edge_y2
            end_y = histogramWidget.PADDING
            dist = start_y-end_y
            while dist > 1:
                dist /= histogramWidget.TICK_FACTOR
                self.canvas.create_rectangle(tick_x,end_y+dist-1,tick_x2,end_y+dist,fill=histogramWidget.TICK_COLOR,width=0)
            
            start_y = node_y
            end_y = height-histogramWidget.PADDING
            dist = end_y-start_y
            while dist > 1:
                dist /= histogramWidget.TICK_FACTOR
                self.canvas.create_rectangle(tick_x,end_y-dist,tick_x2,end_y-dist+1,fill=histogramWidget.TICK_COLOR,width=0)
        
        # draw the update bar
        bar_x = self.currentBin*self.bar_interval + self.center_x
        bar_x2 = self.center_x2
        bar_y = self.center_y-histogramWidget.UPDATE_WIDTH/2
        bar_y2 = bar_y+histogramWidget.UPDATE_WIDTH
        self.updateBar = self.canvas.create_rectangle(bar_x,bar_y,bar_x2,bar_y2,fill=histogramWidget.UPDATE_COLOR,width=0)
        
        # draw the handle
        handle_x = self.currentBin*self.bar_interval-histogramWidget.HANDLE_WIDTH/2+self.center_x
        handle_x2 = handle_x+histogramWidget.HANDLE_WIDTH
        handle_y = self.center_y-histogramWidget.HANDLE_LENGTH/2
        handle_y2 = handle_y+histogramWidget.HANDLE_LENGTH
        self.handleBar = self.canvas.create_rectangle(handle_x,handle_y,handle_x2,handle_y2,fill=histogramWidget.HANDLE_COLOR,width=0)
        self.canvas.tag_bind(self.handleBar, "<Button-1>",self.adjustHandle)
        self.canvas.tag_bind(self.handleBar, "<B1-Motion>",self.adjustHandle)
        self.canvas.tag_bind(self.handleBar, "<ButtonRelease-1>",self.adjustHandle)
        parent.bind("<Left>",lambda e: self.nudgeHandle(e,-1))
        parent.bind("<Right>",lambda e: self.nudgeHandle(e,1))
        
        # init the tooltip as nothing
        self.toolTipBox = self.canvas.create_rectangle(0,0,0,0,state="hidden",fill=histogramWidget.TOOLTIP_COLOR,width=0)
        self.toolTip = self.canvas.create_text(0,0,state="hidden",anchor="nw")
        self.canvas.bind("<Enter>",self.updateToolTip)
        self.canvas.bind("<Leave>",self.updateToolTip)
    
    def adjustHandle(self, event):
        newBin = int(self.numBins*(event.x-self.center_x)/float(self.center_x2-self.center_x)+0.5)
        if newBin == self.currentBin or newBin < 0 or newBin > self.numBins:
            return
        
        self.canvas.move(self.handleBar,(newBin-self.currentBin)*self.bar_interval,0)
        self.currentBin = newBin
        if self.callback != None:
            self.callback(self.binValues[newBin])
    
    def nudgeHandle(self, event, distance):
        temp = self.currentBin+distance
        if temp < 0 or temp > self.numBins:
            return
        
        self.canvas.move(self.handleBar,distance*self.bar_interval,0)
        self.currentBin += distance
        
        if self.callback != None:
            self.callback(self.binValues[self.currentBin])
    
    def update(self, currentBins):
        currentBar = self.canvas.coords(self.updateBar)
        self.canvas.coords(self.updateBar,currentBins*self.bar_interval+self.center_x,currentBar[1],currentBar[2],currentBar[3])
    
    def updateToolTip(self, event):
        allTags = self.canvas.gettags(self.canvas.find_overlapping(event.x,event.y,event.x+1,event.y+1))
        
        if len(allTags) == 0:
            self.canvas.itemconfig(self.toolTipBox,state="hidden")
            self.canvas.itemconfig(self.toolTip,state="hidden")
            return
        
        outText = ""
        for t in allTags:
            if t == "current":
                continue
            outText += t + "\n"
        
        outText = outText[:-1]  # strip the last return
        
        self.canvas.coords(self.toolTip,event.x+20,event.y)
        self.canvas.itemconfig(self.toolTip,state="normal",text=outText,anchor="nw")
        # correct if our tooltip is off screen
        textBounds = self.canvas.bbox(self.toolTip)
        if textBounds[2] >= WIDTH-2*histogramWidget.PADDING:
            self.canvas.itemconfig(self.toolTip, anchor="ne")
            self.canvas.coords(self.toolTip,event.x-20,event.y)
            if textBounds[3] >= HEIGHT-2*histogramWidget.PADDING:
                self.canvas.itemconfig(self.toolTip, anchor="se")
        elif textBounds[3] >= HEIGHT-2*histogramWidget.PADDING:
            self.canvas.itemconfig(self.toolTip, anchor="sw")
        
        # draw the box behind it
        self.canvas.coords(self.toolTipBox,self.canvas.bbox(self.toolTip))
        self.canvas.itemconfig(self.toolTipBox, state="normal")
Example #26
0
class PigChaseHumanAgent(GuiAgent):
    def __init__(self, name, environment, keymap, max_episodes, max_actions,
                 visualizer, quit):
        self._max_episodes = max_episodes
        self._max_actions = max_actions
        self._action_taken = 0
        self._episode = 1
        self._scores = []
        self._rewards = []
        self._episode_has_ended = False
        self._episode_has_started = False
        self._quit_event = quit
        super(PigChaseHumanAgent, self).__init__(name, environment, keymap,
                                                 visualizer=visualizer)

    def _build_layout(self, root):
        # Left part of the GUI, first person view
        self._first_person_header = ttk.Label(root, text='First Person View', font=(None, 14, 'bold')) \
            .grid(row=0, column=0)
        self._first_person_view = ttk.Label(root)
        self._first_person_view.grid(row=1, column=0, rowspan=10)

        # Right part, top
        self._first_person_header = ttk.Label(root, text='Symbolic View', font=(None, 14, 'bold')) \
            .grid(row=0, column=1)
        self._symbolic_view = Canvas(root)
        self._symbolic_view.configure(width=ENV_BOARD_SHAPE[0]*CELL_WIDTH,
                                      height=ENV_BOARD_SHAPE[1]*CELL_WIDTH)
        self._symbolic_view.grid(row=1, column=1)

        # Bottom information
        self._information_panel = ttk.Label(root, text='Game stats', font=(None, 14, 'bold'))
        self._current_episode_lbl = ttk.Label(root, text='Episode: 0', font=(None, 12))
        self._cum_reward_lbl = ttk.Label(root, text='Score: 0', font=(None, 12, 'bold'))
        self._last_action_lbl = ttk.Label(root, text='Previous action: None', font=(None, 12))
        self._action_done_lbl = ttk.Label(root, text='Actions taken: 0', font=(None, 12))
        self._action_remaining_lbl = ttk.Label(root, text='Actions remaining: 0', font=(None, 12))

        self._information_panel.grid(row=2, column=1)
        self._current_episode_lbl.grid(row=3, column=1, sticky=W, padx=20)
        self._cum_reward_lbl.grid(row=4, column=1, sticky=W, padx=20)
        self._last_action_lbl.grid(row=5, column=1, sticky=W, padx=20)
        self._action_done_lbl.grid(row=6, column=1, sticky=W, padx=20)
        self._action_remaining_lbl.grid(row=7, column=1, sticky=W, padx=20)
        self._overlay = None

        # Main rendering callback
        self._pressed_binding = root.bind('<Key>', self._on_key_pressed)
        self._user_pressed_enter = False

        # UI Update callback
        root.after(self._tick, self._poll_frame)
        root.after(1000, self._on_episode_start)

        root.focus()

    def _draw_arrow(self, yaw, x, y, cell_width, colour):
        if yaw == 0.:
            x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width
            x2, y2 = (x + .5) * cell_width, (y + .4) * cell_width
            x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width

            self._symbolic_view.create_polygon(x1, y1, x2, y3, x3, y1, x2, y2, fill=colour)
        elif yaw == 90.:
            x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width
            x2, y2 = (x + .6) * cell_width, (y + .5) * cell_width
            x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width

            self._symbolic_view.create_polygon(x1, y2, x3, y1, x2, y2, x3, y3, fill=colour)
        elif yaw == 180.:
            x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width
            x2, y2 = (x + .5) * cell_width, (y + .6) * cell_width
            x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width

            self._symbolic_view.create_polygon(x1, y3, x2, y1, x3, y3, x2, y2, fill=colour)
        else:
            x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width
            x2, y2 = (x + .4) * cell_width, (y + .5) * cell_width
            x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width

            self._symbolic_view.create_polygon(x1, y3, x2, y2, x1, y1, x3, y2, fill=colour)

    def _poll_frame(self):
        """
        Main callback for UI rendering.
        Called at regular intervals.
        The method will ask the environment to provide a frame if available (not None).
        :return:
        """
        cell_width = CELL_WIDTH
        circle_radius = 10

        # are we done?
        if self._env.done and not self._episode_has_ended:
            self._on_episode_end()

        # build symbolic view
        board, _ = self._env._internal_symbolic_builder.build(self._env)
        if board is not None:
            board = board.T
            self._symbolic_view.delete('all')  # Remove all previous items from Tkinter tracking
            width, height = board.shape
            for x in range(width):
                for y in range(height):
                    cell_contents = str.split(str(board[x][y]), '/')
                    for block in cell_contents:
                        if block == 'sand':
                            self._symbolic_view.create_rectangle(x * cell_width, y * cell_width,
                                                                 (x + 1) * cell_width, (y + 1) * cell_width,
                                                                 outline="black", fill="orange", tags="square")
                        elif block == 'grass':
                            self._symbolic_view.create_rectangle(x * cell_width, y * cell_width,
                                                                 (x + 1) * cell_width, (y + 1) * cell_width,
                                                                 outline="black", fill="lawn green", tags="square")
                        elif block == 'lapis_block':
                            self._symbolic_view.create_rectangle(x * cell_width, y * cell_width,
                                                                 (x + 1) * cell_width, (y + 1) * cell_width,
                                                                 outline="black", fill="black", tags="square")
                        elif block == ENV_TARGET_NAMES[0]:
                            self._symbolic_view.create_oval((x + .5) * cell_width - circle_radius,
                                                            (y + .5) * cell_width - circle_radius,
                                                            (x + .5) * cell_width + circle_radius,
                                                            (y + .5) * cell_width + circle_radius,
                                                            fill='pink')
                        elif block == self.name:
                            yaw = self._env._world_obs['Yaw'] % 360
                            self._draw_arrow(yaw, x, y, cell_width, 'red')
                        elif block == ENV_AGENT_NAMES[0]:
                            # Get yaw of other agent:
                            entities = self._env._world_obs[ENV_ENTITIES]
                            other_agent = list(
                                map(Entity.create, filter(lambda e: e['name'] == ENV_AGENT_NAMES[0], entities)))
                            if len(other_agent) == 1:
                                other_agent = other_agent.pop()
                                yaw = other_agent.yaw % 360
                                self._draw_arrow(yaw, x, y, cell_width, 'blue')

        # display the most recent frame
        frame = self._env.frame
        if frame is not None:
            from PIL import ImageTk
            self._first_person_view.image = ImageTk.PhotoImage(image=frame)
            self._first_person_view.configure(image=self._first_person_view.image)
            self._first_person_view.update()

        self._first_person_view.update()

        # process game state (e.g., has the episode started?)
        if self._episode_has_started and time.time() - self._episode_start_time < 3:
            if not hasattr(self, "_init_overlay") or not self._init_overlay:
                self._create_overlay()
            self._init_overlay.delete("all")
            self._init_overlay.create_rectangle(
                10, 10, 590, 290, fill="white", outline="red", width="5")
            self._init_overlay.create_text(
                300, 80, text="Get ready to catch the pig!",
                font=('Helvetica', '18'))
            self._init_overlay.create_text(
                300, 140, text=str(3 - int(time.time() - self._episode_start_time)),
                font=('Helvetica', '18'), fill="red")
            self._init_overlay.create_text(
                300, 220, width=460,
                text="How to play: \nUse the left/right arrow keys to turn, "
                     "forward/back to move. The pig is caught if it is "
                     "cornered without a free block to escape to.",
                font=('Helvetica', '14'), fill="black")
            self._root.update()

        elif self._episode_has_ended:

            if not hasattr(self, "_init_overlay") or not self._init_overlay:
                self._create_overlay()
            self._init_overlay.delete("all")
            self._init_overlay.create_rectangle(
                10, 10, 590, 290, fill="white", outline="red", width="5")
            self._init_overlay.create_text(
                300, 80, text='Finished episode %d of %d' % (self._episode, self._max_episodes),
                font=('Helvetica', '18'))
            self._init_overlay.create_text(
                300, 120, text='Score: %d' % sum(self._rewards),
                font=('Helvetica', '18'))
            if self._episode > 1:
                self._init_overlay.create_text(
                    300, 160, text='Average over %d episodes: %.2f' % (self._episode, np.mean(self._scores)),
                    font=('Helvetica', '18'))
            self._init_overlay.create_text(
                300, 220, width=360,
                text="Press RETURN to start the next episode, ESC to exit.",
                font=('Helvetica', '14'), fill="black")
            self._root.update()

        elif hasattr(self, "_init_overlay") and self._init_overlay:
            self._destroy_overlay()

        # trigger the next update
        self._root.after(self._tick, self._poll_frame)

    def _create_overlay(self):
        self._init_overlay = Canvas(self._root, borderwidth=0, highlightthickness=0, width=600, height=300, bg="gray")
        self._init_overlay.place(relx=0.5, rely=0.5, anchor='center')

    def _destroy_overlay(self):
        self._init_overlay.destroy()
        self._init_overlay = None

    def _on_key_pressed(self, e):
        """
        Main callback for keyboard events
        :param e:
        :return:
        """
        if e.keysym == 'Escape':
            self._quit()

        if e.keysym == 'Return' and self._episode_has_ended:

            if self._episode >= self._max_episodes:
                self._quit()

            # start the next episode
            self._action_taken = 0
            self._rewards = []
            self._episode += 1
            self._env.reset()

            self._on_episode_start()
            print('Starting episode %d' % self._episode)

        if self._episode_has_started and time.time() - self._episode_start_time >= 3:
            if e.keysym in self._keymap:
                mapped_action = self._keymap.index(e.keysym)

                _, reward, done = self._env.do(mapped_action)
                self._action_taken += 1
                self._rewards.append(reward)
                self._on_experiment_updated(mapped_action, reward, done)

    def _on_episode_start(self):
        self._episode_has_ended = False
        self._episode_has_started = True
        self._episode_start_time = time.time()
        self._on_experiment_updated(None, 0, self._env.done)

    def _on_episode_end(self):
        self._episode_has_started = False
        self._episode_has_ended = True
        self._scores.append(sum(self._rewards))
        self.visualize(self._episode, 'Reward', sum(self._rewards))

    def _on_experiment_updated(self, action, reward, is_done):
        self._current_episode_lbl.config(text='Episode: %d' % self._episode)
        self._cum_reward_lbl.config(text='Score: %d' % sum(self._rewards))
        self._last_action_lbl.config(text='Previous action: %s' % action)
        self._action_done_lbl.config(text='Actions taken: {0}'.format(self._action_taken))
        self._action_remaining_lbl.config(text='Actions remaining: %d' % (self._max_actions - self._action_taken))
        self._first_person_view.update()

    def _quit(self):
        self._quit_event.set()
        self._root.quit()
        sys.exit()
Example #27
0
def screen_draw():
    global window, canvas_frame, canvas_play, canvas_play1, canvas_play2, canvas_future, level, point, max_point, canvas_pause
    level = 1
    point = 0
    max_point = 0
    canvas_frame = Canvas(window)  #,bg='red')
    canvas_frame.place(x=0, y=0, relwidth=1.0, relheight=1.0)
    global frame1, frame2
    frame1 = Frame(window)
    frame2 = Frame(window)
    frame1.place(x=0, y=0, width=300, height=600)
    frame2.place(x=0, y=0, width=300, height=600)
    canvas_play1 = Canvas(frame1, bg='#000000')
    canvas_play1.place(x=0, y=0, width=300, height=600)
    for x in range(1, 10):
        for y in range(1, 20):
            canvas_play1.create_line(30 * x, 0, 30 * x, 600,
                                     fill='#111111')  #,tag='play')
            canvas_play1.create_line(0, 30 * y, 300, 30 * y,
                                     fill='#111111')  #,tag='play')
    canvas_play2 = Canvas(frame2, bg='#000000')
    canvas_play2.place(x=0, y=0, width=300, height=600)
    for x in range(1, 10):
        for y in range(1, 20):
            canvas_play2.create_line(30 * x, 0, 30 * x, 600, fill='#111111')
            canvas_play2.create_line(0, 30 * y, 300, 30 * y, fill='#111111')
    canvas_play = frame2
    canvas_frame.create_text(370,
                             200,
                             font=('Purisa', 24),
                             text='Level',
                             anchor='n')
    canvas_frame.create_text(370,
                             336,
                             font=('Purisa', 24),
                             text='Point',
                             anchor='n')
    canvas_frame.create_text(370,
                             436,
                             font=('Purisa', 24),
                             text='Max',
                             anchor='n')
    canvas_frame.create_text(370,
                             270,
                             text=str(level),
                             font=('', 24),
                             fill='#0000ff',
                             tag='level')
    canvas_frame.create_text(370,
                             400,
                             text=str(point),
                             font=('', 24),
                             fill='#0000ff',
                             tag='point')
    canvas_frame.create_text(370,
                             500,
                             text=str(max_point),
                             font=('', 24),
                             fill='#ff0000',
                             tag='max')
    canvas_future = Canvas(window)  #,bg='#0000ff')
    canvas_future.place(x=310, y=10, width=120, height=120)
    canvas_pause = Canvas(canvas_frame)  #,bg='yellow')
    canvas_pause.place(x=345, y=540, width=50, height=50)
    draw_play()
    canvas_pause.bind('<ButtonPress-1>', event_pause)
# plot a point 
# import mathplotlib.pyplot as plt
from Tkinter import Tk, Canvas, PhotoImage, Label





if __name__ == '__main__':
	root = Tk()
	w = Label(root, text="Draw a Point on Canvas in Python")
	canvas= Canvas(root, width=250, height=250, bg='#E2E2E2')
	canvas.place(x=20,y=26,height=250,width=250)
	#img= PhotoImage(width=200, height=200)
	# img.putpixel(1,2)
	w.pack()
	canvas.pack()
	root.mainloop()
Example #29
0
class Window(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent, background="white")            
        self.parent = parent        
        self.initUI()
        
        home='/home/little_light/Desktop/workspace/python/data/GSTRB'
        modelFile=home+'/model/demo2.pkl'
        input_var = T.tensor4('inputs',dtype=theano.config.floatX)
        target_var = T.ivector('targets')
        network,loss,params=build_2f(input_var,target_var,regularW=0.0001)
        pvals=cPickle.load(open(modelFile))
        [p.set_value(pval) for (p, pval) in zip(lasagne.layers.get_all_params(network), pvals)]
    
        predict=lasagne.layers.get_output(network, deterministic=True)
        input=lasagne.layers.get_all_layers(network)[0].input_var
        #lasagne.layers.input.input
        self.predict_fn=theano.function(inputs=[input],outputs=predict)
        
    def initUI(self):
        self.parent.title("Simple")
        self.pack(fill=BOTH, expand=1)
        self.tbImg=Entry(self.parent,width=50)
        self.tbImg.place(x=10,y=10)
        self.bLoad=Button(master=self,text="Load", command = self.load)
        self.bLoad.pack()
        self.bLoad.place(x=10,y=30)
        
        self.canvas = Canvas(self, width=400, height=400)      
        self.canvas.pack()
        
        fileName='/home/little_light/Desktop/workspace/python/data/GSTRB/Final_Training/Images/00000/00004_00029.ppm'
        
        
        img = ImageTk.PhotoImage(Image.open(fileName))      
        
        self.canvas.image=img
        self.image_on_canvas=self.canvas.create_image(0,0,image=img,anchor='nw')   
        
        self.canvas.place(x=10,y=60)
        
        self.v = StringVar()
        self.label=Label(master=self,textvariable=self.v)
        self.v.set("Target label:")
        self.label.place(x=10,y=470)
        
        
    def load(self):
        print "load"
        fileName=self.tbImg.get()
        img = ImageTk.PhotoImage(Image.open(fileName))
        self.canvas.image=img
        #self.canvas.create_image(0,0,image=img)
        self.canvas.itemconfig(self.image_on_canvas, image =self.canvas.image)
        img=Image.open(fileName)
        img.load() 
        img2=img.resize((32,32))
        img2.load()
        data = np.asarray(img2, dtype="int32")
        mean=86.2111433696
        data=np.transpose(data,(2,0,1))
        data=np.asarray((data-mean)/256.0,dtype=theano.config.floatX)
        data2=np.zeros((1,3,32,32),dtype=theano.config.floatX)
        data2[0]=data
        data=data2
        print np.argmax(self.predict_fn(data)[0])
        self.v.set("Target label:"+str(np.argmax(self.predict_fn(data)[0])))
        st_lepptcb.set(0)
        chooseleppt()


lyes = Checkbutton(frame1,
                   text="Choose number of charged leptons",
                   bg="LightCyan2",
                   variable=st_lepcb,
                   onvalue=1,
                   offvalue=0,
                   command=chooseNlep)
lyes.grid(row=0, column=0, sticky=W)  #Define and show checkbox

#Question mark to be next to "choose lep" option
qlep = Canvas(frame1, width=16, height=16)
qlep.place(relx=0.61, rely=0.001, anchor=N)
qlep.create_image(8, 8, image=questionmark)
infolep = Message(frame1,
                  text="""The number of charged leptons in the event""",
                  bg="White",
                  aspect=300)  #Information message


def on_enterlep(event):
    """shows an explanation if cursor placed over question mark"""
    infolep.place(relx=0.625, rely=0.0155, anchor=NW)


def on_leavelep(event):
    """hides explanation if cursor not placed over question mark"""
    infolep.place_forget()
Example #31
0
class MSTM_studio:

    splash_time = 0.5  # time to show splash window, seconds

    def __init__(self, top=None):
        '''This class configures and populates the toplevel window.
           top is the toplevel containing window.'''
        top.withdraw()
        time_start = time.time()
        splash = sup.SplashWindow(top)
        self.style = ttk.Style()
        if sys.platform == 'win32':
            self.style.theme_use('winnative')
        self.style.configure('.', font='TkDefaultFont')

        #~ top.geometry('838x455+364+117')
        top.geometry('850x440')
        top.title('MSTM studio')
        #~ top.configure(highlightcolor='black')
        self.load_images()
        self.root_panedwin = ttk.Panedwindow(top, orient='horizontal')
        self.root_panedwin.place(relx=0.0,
                                 rely=0.0,
                                 relheight=1.0,
                                 relwidth=1.0)

        self.root_panedwin.configure(width=200)
        self.left_frame = ttk.Frame(width=220.0)
        self.root_panedwin.add(self.left_frame)
        #~ self.middle_frame = ttk.Labelframe(width=350, text='View')
        self.middle_frame = ttk.Frame(width=350)
        self.root_panedwin.add(self.middle_frame)
        self.right_frame = ttk.Frame()
        self.root_panedwin.add(self.right_frame)
        self.__funcid0 = self.root_panedwin.bind('<Map>', self.__adjust_sash0)

        self.left_panedwin = ttk.Panedwindow(self.left_frame,
                                             orient='vertical')
        self.left_panedwin.place(relx=0.0,
                                 rely=0.0,
                                 relheight=1.0,
                                 relwidth=1.0)
        self.left_panedwin.configure(width=200)

        self.materials_frame = ttk.Labelframe(height=105, text='Materials')
        self.left_panedwin.add(self.materials_frame)
        self.spheres_frame = ttk.Labelframe(text='Spheres')
        self.left_panedwin.add(self.spheres_frame)
        self.__funcid1 = self.left_panedwin.bind('<Map>', self.__adjust_sash1)

        self.style.configure('Treeview.Heading', font='TkDefaultFont')
        self.stvMaterial = ScrolledTreeView(self.materials_frame)
        self.stvMaterial.place(relx=0.0, y=30, relheight=0.8, relwidth=1.0)
        self.configure_stvMaterial()
        self.stvMaterial.bind('<Double-1>', sup.btChangeMatColClick)

        self.btAddMat = ttk.Button(self.materials_frame,
                                   command=sup.btAddMatClick,
                                   text='A',
                                   image=self.imAdd)
        self.btAddMat.place(x=5, y=0, height=25, width=25)

        self.btLoadMat = ttk.Button(self.materials_frame,
                                    command=sup.btLoadMatClick,
                                    text='L',
                                    image=self.imLoad)
        self.btLoadMat.place(x=30, y=0, height=25, width=25)

        self.btPlotMat = ttk.Button(self.materials_frame,
                                    command=sup.btPlotMatClick,
                                    text='P',
                                    image=self.imPlot)
        self.btPlotMat.place(x=55, y=0, height=25, width=25)

        self.btDelMat = ttk.Button(self.materials_frame,
                                   command=sup.btDelMatClick,
                                   text='D',
                                   image=self.imDelete)
        self.btDelMat.place(relx=1, x=-30, rely=0, height=25, width=25)

        self.stvSpheres = ScrolledTreeView(self.spheres_frame)
        self.stvSpheres.place(relx=0.0, y=30, relheight=0.85, relwidth=1.0)
        self.configure_stvSpheres()
        self.stvSpheres.bind('<Double-1>', sup.btEditSphClick)

        self.btAddSph = ttk.Button(self.spheres_frame,
                                   command=sup.btAddSphClick,
                                   text='A',
                                   image=self.imAdd)
        self.btAddSph.place(x=5, y=0, height=25, width=25)

        self.btEditSph = ttk.Button(self.spheres_frame,
                                    command=sup.btEditSphClick,
                                    text='E',
                                    image=self.imEdit)
        self.btEditSph.place(x=30, y=0, height=25, width=25)

        self.btPlotSph = ttk.Button(self.spheres_frame,
                                    command=sup.btPlotSphClick,
                                    text='R',
                                    image=self.imRefresh)
        self.btPlotSph.place(x=55, y=0, height=25, width=25)

        self.lbEnvMat = ttk.Label(self.spheres_frame, text='Matrix')
        self.lbEnvMat.place(relx=0.45, y=-5)
        self.cbEnvMat = ttk.Combobox(self.spheres_frame)
        self.cbEnvMat.place(relx=0.45, y=10, width=55)

        self.btDelSph = ttk.Button(self.spheres_frame,
                                   command=sup.btDelSphClick,
                                   text='D',
                                   image=self.imDelete)
        self.btDelSph.place(relx=1.0, y=0, x=-30, height=25, width=25)

        self.middle_panedwin = ttk.Panedwindow(self.middle_frame,
                                               orient='vertical')
        self.middle_panedwin.place(relx=0.0,
                                   rely=0.0,
                                   relheight=1.0,
                                   relwidth=1.0)
        #~ self.middle_panedwin.configure(relwidth=1.0)
        self.canvas_frame = ttk.Labelframe(height=360, text='View')
        self.middle_panedwin.add(self.canvas_frame)
        self.spectrum_frame = ttk.Labelframe(height=-40, text='Spectrum')
        self.middle_panedwin.add(self.spectrum_frame)
        self.__funcid2 = self.left_panedwin.bind('<Map>', self.__adjust_sash2)

        self.canvas = Canvas(self.canvas_frame)
        self.canvas.place(relx=0.0, rely=0, relheight=1.0, relwidth=1.0)
        self.canvas.configure(background='white')
        self.canvas.configure(borderwidth='2')
        self.canvas.configure(relief='ridge')
        self.canvas.configure(selectbackground='#c4c4c4')
        self.canvas.bind('<Button-4>', sup.mouse_wheel)  # for Linux
        self.canvas.bind('<Button-5>', sup.mouse_wheel)  # for Linux
        self.canvas.bind('<MouseWheel>', sup.mouse_wheel)  # for Windowz
        self.canvas.bind('<Button-3>', sup.mouse_down)
        self.canvas.bind('<B3-Motion>', sup.mouse_move)
        self.canvas.bind('<ButtonRelease-3>', sup.mouse_up)

        self.lbZoom = ttk.Label(
            self.canvas, text='x1.00',
            background='white')  #font=('courier', 18, 'bold'), width=10)
        self.lbZoom.place(relx=1.0, x=-50, rely=1.0, y=-25)

        self.lbLambdaMin = ttk.Label(self.spectrum_frame, text='min')
        self.lbLambdaMin.place(x=5, y=0)
        self.edLambdaMin = ttk.Entry(self.spectrum_frame)
        self.edLambdaMin.place(x=5, y=15, width=35)
        self.edLambdaMin.insert(0, '300')

        self.lbLambdaMax = ttk.Label(self.spectrum_frame, text='max')
        self.lbLambdaMax.place(x=45, y=0)
        self.edLambdaMax = ttk.Entry(self.spectrum_frame)
        self.edLambdaMax.place(x=45, y=15, width=35)
        self.edLambdaMax.insert(0, '800')

        self.lbLambdaCount = ttk.Label(self.spectrum_frame, text='count')
        self.lbLambdaCount.place(x=85, y=0)
        self.edLambdaCount = ttk.Entry(self.spectrum_frame)
        self.edLambdaCount.place(x=85, y=15, width=35)
        self.edLambdaCount.insert(0, '51')

        self.btCalcSpec = ttk.Button(self.spectrum_frame,
                                     command=sup.btCalcSpecClick,
                                     text='Calculate',
                                     image=self.imCalc,
                                     compound='left')
        self.btCalcSpec.place(x=130, y=10, width=90, height=25)

        self.lbSpecScale = ttk.Label(self.spectrum_frame, text='scale')
        self.lbSpecScale.place(relx=1, x=-115, y=0)
        self.edSpecScale = ttk.Entry(self.spectrum_frame)
        self.edSpecScale.place(relx=1, x=-115, y=15, width=50)
        self.edSpecScale.insert(0, '1')

        self.btSaveSpec = ttk.Button(self.spectrum_frame,
                                     command=sup.btSaveSpecClick,
                                     text='S',
                                     image=self.imSave)
        self.btSaveSpec.place(relx=1, x=-55, y=10, width=25, height=25)

        self.btPlotSpec = ttk.Button(self.spectrum_frame,
                                     command=sup.btPlotSpecClick,
                                     text='P',
                                     image=self.imPlot)
        self.btPlotSpec.place(relx=1, x=-30, y=10, width=25, height=25)

        self.right_panedwin = ttk.Panedwindow(self.right_frame,
                                              orient='vertical')
        self.right_panedwin.place(relx=0.0,
                                  rely=0.0,
                                  relheight=1.0,
                                  relwidth=1.0)

        self.right_panedwin.configure(width=200)
        self.plot_frame = ttk.Labelframe(height=200, text='Plot')
        self.right_panedwin.add(self.plot_frame)
        self.contribs_frame = ttk.Labelframe(height=150,
                                             text='Other contributions')
        self.right_panedwin.add(self.contribs_frame)
        self.fitting_frame = ttk.Labelframe(height=-50, text='Fitting')
        self.right_panedwin.add(self.fitting_frame)
        self.__funcid3 = self.right_panedwin.bind('<Map>', self.__adjust_sash3)

        # CONTRIBUTIONS
        self.btAddContrib = ttk.Button(self.contribs_frame,
                                       command=sup.btAddContribClick,
                                       text='A',
                                       image=self.imAdd)
        self.btAddContrib.place(x=5, y=0, height=25, width=25)

        self.btPlotAllContribs = ttk.Button(self.contribs_frame,
                                            command=sup.btPlotAllContribsClick,
                                            text='P',
                                            image=self.imPlot)
        self.btPlotAllContribs.place(x=30, y=0, height=25, width=25)

        self.btDelContrib = ttk.Button(self.contribs_frame,
                                       command=sup.btDelContribClick,
                                       text='D',
                                       image=self.imDelete)
        self.btDelContrib.place(relx=1.0, y=0, x=-30, height=25, width=25)

        self.cbContribs = []
        self.edContribs = []  # actually, it will be the list of lists [[]]
        self.btPlotsContrib = []
        self.contribs_list = [
            'ConstBkg', 'LinearBkg', 'LorentzBkg', 'Mie single', 'Mie LN',
            'Lorentz peak', 'Gauss peak', 'Au film', 'bst-3Au/glass'
        ]
        self.cbContribMats = []
        self.btContribDistribPlots = []

        # Fitting frame
        self.edExpFileName = ttk.Entry(self.fitting_frame,
                                       text='Exp. file name')
        self.edExpFileName.place(x=5, y=0, height=25, relwidth=0.8)

        self.btLoadExp = ttk.Button(self.fitting_frame,
                                    command=sup.btLoadExpClick,
                                    text='L',
                                    image=self.imLoad)
        self.btLoadExp.place(relx=1.0, x=-55, y=0, height=25, width=25)

        self.btPlotExp = ttk.Button(self.fitting_frame,
                                    command=sup.btPlotExpClick,
                                    text='P',
                                    image=self.imPlot)
        self.btPlotExp.place(relx=1.0, x=-30, y=0, height=25, width=25)

        self.btStartFit = ttk.Button(self.fitting_frame,
                                     command=sup.btStartFitClick,
                                     text='>',
                                     image=self.imPlay)
        self.btStartFit.place(x=5, y=30, height=25, width=25)

        self.btStopFit = ttk.Button(self.fitting_frame,
                                    command=sup.btStopFitClick,
                                    text='|',
                                    image=self.imStop)
        self.btStopFit.place(x=30, y=30, height=25, width=25)

        self.lbChiSq = ttk.Label(self.fitting_frame, text='ChiSq:')
        self.lbChiSq.place(x=60, y=35)

        self.btConstraints = ttk.Button(self.fitting_frame,
                                        command=sup.btConstraintsClick,
                                        text='Constraints...')
        self.btConstraints.place(relx=1, x=-100, y=30, height=25, width=95)

        self._create_menu(top)

        time_delta = time.time() - time_start  # in seconds
        if time_delta < self.splash_time:
            time.sleep(self.splash_time - time_delta)
        top.deiconify()
        splash.destroy()

    def configure_stvMaterial(self):
        self.stvMaterial.configure(columns='Col1')
        self.stvMaterial.heading('#0', text='MatID')
        self.stvMaterial.heading('#0', anchor='center')
        self.stvMaterial.column('#0', width='46')
        self.stvMaterial.column('#0', minwidth='20')
        self.stvMaterial.column('#0', stretch='1')
        self.stvMaterial.column('#0', anchor='w')
        self.stvMaterial.heading('Col1', text='Name')
        self.stvMaterial.heading('Col1', anchor='center')
        self.stvMaterial.column('Col1', width='150')
        self.stvMaterial.column('Col1', minwidth='20')
        self.stvMaterial.column('Col1', stretch='1')
        self.stvMaterial.column('Col1', anchor='w')

    def configure_stvSpheres(self):
        self.stvSpheres.configure(columns='Col1 Col2 Col3 Col4 Col5')
        self.stvSpheres.heading('#0', text='ID')
        self.stvSpheres.heading('#0', anchor='center')
        self.stvSpheres.column('#0', width='34')
        self.stvSpheres.column('#0', minwidth='20')
        self.stvSpheres.column('#0', stretch='1')
        self.stvSpheres.column('#0', anchor='w')
        self.stvSpheres.heading('Col1', text='R')
        self.stvSpheres.heading('Col1', anchor='center')
        self.stvSpheres.column('Col1', width='37')
        self.stvSpheres.column('Col1', minwidth='20')
        self.stvSpheres.column('Col1', stretch='1')
        self.stvSpheres.column('Col1', anchor='w')
        self.stvSpheres.heading('Col2', text='X')
        self.stvSpheres.heading('Col2', anchor='center')
        self.stvSpheres.column('Col2', width='31')
        self.stvSpheres.column('Col2', minwidth='20')
        self.stvSpheres.column('Col2', stretch='1')
        self.stvSpheres.column('Col2', anchor='w')
        self.stvSpheres.heading('Col3', text='Y')
        self.stvSpheres.heading('Col3', anchor='center')
        self.stvSpheres.column('Col3', width='34')
        self.stvSpheres.column('Col3', minwidth='20')
        self.stvSpheres.column('Col3', stretch='1')
        self.stvSpheres.column('Col3', anchor='w')
        self.stvSpheres.heading('Col4', text='Z')
        self.stvSpheres.heading('Col4', anchor='center')
        self.stvSpheres.column('Col4', width='34')
        self.stvSpheres.column('Col4', minwidth='20')
        self.stvSpheres.column('Col4', stretch='1')
        self.stvSpheres.column('Col4', anchor='w')
        self.stvSpheres.heading('Col5', text='mID')
        self.stvSpheres.heading('Col5', anchor='center')
        self.stvSpheres.column('Col5', width='32')
        self.stvSpheres.column('Col5', minwidth='20')
        self.stvSpheres.column('Col5', stretch='1')
        self.stvSpheres.column('Col5', anchor='w')

    def load_images(self):
        def tryload(fn):
            try:
                im = ImageTk.PhotoImage(file=os.path.normpath(
                    os.path.join(os.path.dirname(__file__), 'images', fn)))
            except Exception as err:
                print('Can not load %s\n%s' % (fn, err))
                return None
            return im

        self.imLoad = tryload('folder_open_icon&16.png')
        self.imDelete = tryload('delete_icon&16.png')
        self.imPlot = tryload('chart_bar_icon&16.png')
        self.imPlot2 = tryload('chart_bar2_icon&16.png')
        self.imAdd = tryload('sq_plus_icon&16.png')
        self.imSave = tryload('save_icon&16.png')
        self.imRefresh = tryload('refresh_icon&16.png')
        self.imExport = tryload('export_icon&16.png')
        self.imImport = tryload('import_icon&16.png')
        self.imPlay = tryload('playback_play_icon&16.png')
        self.imStop = tryload('playback_stop_icon&16.png')
        self.imCalc = tryload('cogs_icon&16.png')
        self.imEdit = tryload('doc_edit_icon&16.png')
        self.imExit = tryload('on-off_icon&16.png')
        self.imBrush = tryload('brush_icon&16.png')
        self.imZoomIn = tryload('round_plus_icon&16.png')
        self.imZoomOut = tryload('round_minus_icon&16.png')

    def __adjust_sash0(
            self,
            event):  # mysterious functions left from previous civilizations
        paned = event.widget
        pos = [
            220,
            575,
        ]
        i = 0
        for sash in pos:
            paned.sashpos(i, sash)
            i += 1
        paned.unbind('<map>', self.__funcid0)
        del self.__funcid0

    def __adjust_sash1(self, event):
        paned = event.widget
        pos = [
            145,
        ]
        i = 0
        for sash in pos:
            paned.sashpos(i, sash)
            i += 1
        paned.unbind('<map>', self.__funcid1)
        del self.__funcid1

    def __adjust_sash2(self, event):
        paned = event.widget
        pos = [
            200,
        ]
        i = 0
        for sash in pos:
            paned.sashpos(i, sash)
            i += 1
        paned.unbind('<map>', self.__funcid2)
        del self.__funcid2

    def __adjust_sash3(self, event):
        paned = event.widget
        pos = [
            200,
        ]
        i = 0
        for sash in pos:
            paned.sashpos(i, sash)
            i += 1
        paned.unbind('<map>', self.__funcid3)
        del self.__funcid3

    def _create_menu(self, top):
        self.menubar = Menu(top)

        self.filemenu = Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(label='Import spheres...',
                                  command=sup.btImportSpheres,
                                  image=self.imImport,
                                  compound='left')
        self.filemenu.add_command(label='Export spheres...',
                                  command=sup.btExportSpheres,
                                  image=self.imExport,
                                  compound='left')
        self.filemenu.add_separator()
        self.filemenu.add_command(label='Exit',
                                  command=sup.destroy_window,
                                  image=self.imExit,
                                  compound='left')
        self.menubar.add_cascade(label='File', menu=self.filemenu)

        self.matmenu = Menu(self.menubar, tearoff=0)
        self.matmenu.add_command(label='Add constant...',
                                 command=sup.btAddMatClick,
                                 image=self.imAdd,
                                 compound='left')
        self.matmenu.add_command(label='Load function...',
                                 command=sup.btLoadMatClick,
                                 image=self.imLoad,
                                 compound='left')
        self.matmenu.add_separator()
        self.matmenu.add_command(label='Delete selected',
                                 command=sup.btDelMatClick,
                                 image=self.imDelete,
                                 compound='left')
        self.matmenu.add_separator()
        self.matmenu.add_command(label='Plot selected',
                                 command=sup.btPlotMatClick,
                                 image=self.imPlot,
                                 compound='left')
        self.matmenu.add_separator()
        self.matmenu.add_command(label='Change view color...',
                                 command=sup.btChangeMatColClick,
                                 image=self.imBrush,
                                 compound='left')
        self.menubar.add_cascade(label='Materials', menu=self.matmenu)

        self.sphmenu = Menu(self.menubar, tearoff=0)
        self.sphmenu.add_command(label='Add...',
                                 command=sup.btAddSphClick,
                                 image=self.imAdd,
                                 compound='left')
        self.sphmenu.add_separator()
        self.sphmenu.add_command(label='Edit selected...',
                                 command=sup.btEditSphClick,
                                 image=self.imEdit,
                                 compound='left')
        self.sphmenu.add_command(label='Delete selected',
                                 command=sup.btDelSphClick,
                                 image=self.imDelete,
                                 compound='left')
        self.sphmenu.add_separator()
        self.sphmenu.add_command(label='Generate on mesh...',
                                 command=sup.btGenerateSpheresClick)
        self.menubar.add_cascade(label='Spheres', menu=self.sphmenu)

        self.viewmenu = Menu(self.menubar, tearoff=0)
        self.viewmenu.add_command(label='Zoom in',
                                  command=lambda: sup.mouse_wheel(
                                      type('', (), {
                                          'num': 4,
                                          'delta': 0
                                      })()),
                                  image=self.imZoomIn,
                                  compound='left')
        self.viewmenu.add_command(label='Zoom out',
                                  command=lambda: sup.mouse_wheel(
                                      type('', (), {
                                          'num': 5,
                                          'delta': 0
                                      })()),
                                  image=self.imZoomOut,
                                  compound='left')
        self.viewmenu.add_command(label='Reset view',
                                  command=sup.btPlotSphClick,
                                  image=self.imRefresh,
                                  compound='left')
        self.menubar.add_cascade(label='View', menu=self.viewmenu)

        self.opticsmenu = Menu(self.menubar, tearoff=0)
        self.opticsmenu.add_command(label='Calculate',
                                    command=sup.btCalcSpecClick,
                                    image=self.imCalc,
                                    compound='left')
        self.menubar.add_cascade(label='Spectrum', menu=self.opticsmenu)

        self.fittingmenu = Menu(self.menubar, tearoff=0)
        self.fittingmenu.add_command(label='Load experiment...',
                                     command=sup.btLoadExpClick,
                                     image=self.imLoad,
                                     compound='left')
        self.fittingmenu.add_separator()
        self.fittingmenu.add_command(label='Constraints...',
                                     command=sup.btConstraintsClick)
        self.fittingmenu.add_separator()
        self.fittingmenu.add_command(label='Start fit',
                                     command=sup.btStartFitClick,
                                     image=self.imPlay,
                                     compound='left')
        self.fittingmenu.add_command(label='Stop fit',
                                     command=sup.btStopFitClick,
                                     image=self.imStop,
                                     compound='left')
        self.menubar.add_cascade(label='Fitting', menu=self.fittingmenu)

        self.helpmenu = Menu(self.menubar, tearoff=0)
        self.helpmenu.add_command(label='About', command=sup.btAboutClick)
        self.menubar.add_cascade(label='Help', menu=self.helpmenu)
        # display the menu
        top.config(menu=self.menubar)
Example #32
0
class liuyao:
	def __init__(self,root,gua64):
		self.cntoint={u'少阳-----':'1',u'少阴-- --':'2',u'老阳--O--':'3',u'老阴--X--':'4'}
		self.tfont=tkFont.Font(family='Fixdsys',size=25,weight=tkFont.BOLD)
		self.gfont=tkFont.Font(family='Fixdsys',size=13,weight=tkFont.BOLD)
		self.dgua=[] #动爻
		self.ygua=[] #原始卦
		self.bbgua=[] #变卦
		self.yguastr=[] #原始卦
		self.gua=[] #只有12的卦
		self.pabout=True #右键显示消失淮南标题
		self.guax=200
		self.guay=100
		self.liushen={'甲':0,'乙':0,'丙':1,'丁':1,'戊':2,'己':3,'庚':4,'辛':4,'壬':5,'癸':5}
		self.liushencn=['青龙','朱雀','勾陈','腾蛇','白虎','玄武']
		self.tiangan={'甲':1,'乙':2,'丙':3,'丁':4,'戊':5,'己':6,'庚':7,'辛':8,'壬':9,'癸':10}
		self.dizhi={'子':1,'丑':2,'寅':3,'卯':4,'辰':5,'巳':6,'午':7,'未':8,'申':9,'酉':10,'戌':11,'亥':12}
		self.kongwangzu=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥']
		self.root=root
		self.root.title(u'===六爻排盘===[淮南内部专用]')
		self.root.minsize(550,380)
		self.root.maxsize(550,380)
		self.canvas=Canvas(root,width=460,height=380,bg='gray')
		self.picyang=PhotoImage(file='tk\\yang.gif')
		self.picyin=PhotoImage(file='tk\\yin.gif')
		self.canvas.place(relx=0,rely=0)
		self.com={}
		for i in xrange(6):
			self.com[i]=Combobox(root,state='readonly')
			self.com[i]['values']=(u'少阳-----',u'少阴-- --',u'老阳--O--',u'老阴--X--')
			self.com[i].current(0)
			self.com[i].place(relx=0.85,rely=0.36-0.07*i,width=80)
		bt1=Button(root,text=u'排盘',command=self.paipan)
		# bt1.place(relx=0.85,rely=0.35+0.7)
		bt1.pack(side='right')
		self.date() #干支
		#===========================
		self.root.bind('<Button-3>',self.about)

	def liushenf(self):  #配六神
		xu=self.liushen[self.ritian.encode('utf-8')]
		for i in xrange(6):
			self.canvas.create_text(self.guax-170,100+150-30*i,font=self.gfont,text=self.liushencn[xu],tag='liushen')
			xu+=1
			if xu>5:
				xu-=6

	def date(self):
		turl=urllib2.urlopen('http://www.nongli.com/item4/index.asp',timeout=10).read()
		soup=BeautifulSoup(turl)
		zu=soup.findAll('td',{'width':'74%','bgcolor':'#FFFFFF'})[1].text
		# print zu
		wanzu=[] #wanzu里面是完成的年月日干支
		wanzu.append(zu.split(' ')[0])
		wanzu.append(zu.split(' ')[2])
		wanzu.append(zu.split(' ')[3])
		for i in xrange(3):
			# print u'干支',wanzu[i]
			self.canvas.create_text(self.guax-90+60*i,30,text=wanzu[i],font=self.gfont,tag='riqi')
		ri=wanzu[2]
		self.ritian=list(ri)[0]
		self.ridi=list(ri)[1]
		self.kongwang()

	def kongwang(self):
		# print u'日干支:',self.ridi,self.ritian
		cha=self.dizhi[self.ridi.encode('utf-8')]-self.tiangan[self.ritian.encode('utf-8')]
		if cha<0:
			cha+=+10
		self.canvas.create_text(self.guax-90+120+30,30,font=self.gfont,text='(',tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+15,30,font=self.gfont,text=self.kongwangzu[cha-2],tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+30,30,font=self.gfont,text=self.kongwangzu[cha-1],tag='riqi')
		self.canvas.create_text(self.guax-90+120+30+45,30,font=self.gfont,text=')',tag='riqi')

	def about(self,event):
		if self.pabout:
			self.canvas.create_text(self.guax,100+250,text='淮南法教专用水印',fill='tan',font=self.tfont,tag='about')
			self.canvas.create_text(self.guax+140,370,text='--无名',fill='tan',tag='about')
			self.pabout=False
		else:
			self.canvas.delete('about')
			self.pabout=True


	def paipan(self):
		for i in xrange(6):
			self.ygua.append(self.cntoint[self.com[i].get()]) #得到原始爻名,转换为1234,添加入gua
		self.gua=self.ygua
		bbgua=self.gua
		print '======================='
		print 'sel.gua',self.gua
		for i in xrange(6):
			if self.ygua[i]=='3':
				self.gua[i]='1'
				self.dgua.append(str(i))
				self.dgua.append('1') 
			elif  self.ygua[i]=='4':
				self.gua[i]='2'
				self.dgua.append(str(i))
				self.dgua.append('2')
		self.guastr=''.join(self.gua)
		# print u'变卦',bbgua
		# print u'字符串卦数',self.guastr
		# print u'数列卦',self.gua
		# print u'动卦',self.dgua
		# print gua64[guastr]
		self.draw()
		self.liushenf()#六神


	def draw(self):
		self.canvas.delete('pic')   #删除所有上次产生的ITEMS
		self.canvas.delete('liushen')
		# print u'当前itme数',self.canvas.find_all()
		#本卦
		for i in xrange(6):
			if self.gua[i]=='1':
				self.canvas.create_image(self.guax,100+150-30*i,image=self.picyang,tag='pic')
			else:
				self.canvas.create_image(self.guax,100+150-30*i,image=self.picyin,tag='pic')	
		
				#下面是六亲
		for i in xrange(6):
			self.canvas.create_text(self.guax-70,100+30*i,font=self.gfont,text=gua64[self.guastr][i],tag='pic')

			#动爻标记
		for i in xrange(0,len(self.dgua),2):
			if self.dgua[i+1]=='1':
				self.canvas.create_text(self.guax+70,250-30*int(self.dgua[i]),font=self.gfont,text='O',tag='pic')
			else:
				self.canvas.create_text(self.guax+70,250-30*int(self.dgua[i]),font=self.gfont,text='X',tag='pic')
			#世
		syw=gua64[self.guastr][6]
		self.canvas.create_text(self.guax+55,280-30*syw,font=self.gfont,text='世',tag='pic')
			#应
		yyw=gua64[self.guastr][7]
		self.canvas.create_text(self.guax+55,280-30*yyw,font=self.gfont,text='应',tag='pic')
			#六合、冲
		hc=gua64[self.guastr][8]
		self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=hc,tag='pic')
			#游魂、归魂
		zg=gua64[self.guastr][9]
		self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=zg,tag='pic')
			#卦宫
		gg=gua64[self.guastr][10]
		self.canvas.create_text(self.guax,100-30,font=self.gfont,text=gg,tag='pic')
		#变卦	
		self.biangua()
		self.guastr=''
		self.dgua=[] #动爻
		self.ygua=[] #原始卦
		self.bbgua=[] #变卦
		self.yguastr=[] #原始卦
		self.gua=[] #只有12的卦

	def biangua(self):
		self.bbgua=self.gua
		# print 'biangua',self.bbgua
		'''
sel.gua ['4', '4', '3', '3', '4', '3']
字符串卦数 221121
数列卦 ['2', '2', '1', '1', '2', '1']
动卦 ['0', '2', '1', '2', '2', '1', '3', '1', '4', '2', '5', '1']
当前itme数 (1, 2, 3, 4, 5, 6, 7)
biangua ['1', '1', '2', '2', '1', '2']
bguastr 112212
		'''
		for i in xrange(0,len(self.dgua),2):
			if self.dgua[i+1]=='1':
				self.bbgua[int(self.dgua[i])]='2'
			else:
				self.bbgua[int(self.dgua[i])]='1'
		print 'biangua',self.bbgua
		self.bguastr=''.join(self.bbgua)
		print 'bguastr',self.bguastr
		for i in xrange(6):
			if self.bbgua[i]=='1':
				self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyang,tag='pic')
			else:
				self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyin,tag='pic')
						#下面是六亲
		for i in xrange(6):
			self.canvas.create_text(self.guax+200,100+30*i,font=self.gfont,text=gua64[self.bguastr][i],tag='pic')
Example #33
-1
class PiPresents(object):

    def pipresents_version(self):
        vitems=self.pipresents_issue.split('.')
        if len(vitems)==2:
            # cope with 2 digit version numbers before 1.3.2
            return 1000*int(vitems[0])+100*int(vitems[1])
        else:
            return 1000*int(vitems[0])+100*int(vitems[1])+int(vitems[2])


    def __init__(self):
        # gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL)
        gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_SAVEALL)
        self.pipresents_issue="1.3.5"
        self.pipresents_minorissue = '1.3.5d'
        # position and size of window without -f command line option
        self.nonfull_window_width = 0.45 # proportion of width
        self.nonfull_window_height= 0.7 # proportion of height
        self.nonfull_window_x = 0 # position of top left corner
        self.nonfull_window_y=0   # position of top left corner


        StopWatch.global_enable=False

        # set up the handler for SIGTERM
        signal.signal(signal.SIGTERM,self.handle_sigterm)
        

# ****************************************
# Initialisation
# ***************************************
        # get command line options
        self.options=command_options()

        # get Pi Presents code directory
        pp_dir=sys.path[0]
        self.pp_dir=pp_dir
        
        if not os.path.exists(pp_dir+"/pipresents.py"):
            if self.options['manager']  is False:
                tkMessageBox.showwarning("Pi Presents","Bad Application Directory")
            exit(102)

        
        # Initialise logging and tracing
        Monitor.log_path=pp_dir
        self.mon=Monitor()
        # Init in PiPresents only
        self.mon.init()

        # uncomment to enable control of logging from within a class
        # Monitor.enable_in_code = True # enables control of log level in the code for a class  - self.mon.set_log_level()

        
        # make a shorter list to log/trace only some classes without using enable_in_code.
        Monitor.classes  = ['PiPresents',
                            
                            'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow',
                            'GapShow','Show','ArtShow',
                            'AudioPlayer','BrowserPlayer','ImagePlayer','MenuPlayer','MessagePlayer','VideoPlayer','Player',
                            'MediaList','LiveList','ShowList',
                            'PathManager','ControlsManager','ShowManager','PluginManager','IOPluginManager',
                            'MplayerDriver','OMXDriver','UZBLDriver',
                            'TimeOfDay','ScreenDriver','Animate','OSCDriver','CounterManager',
                            'Network','Mailer'
                            ]
        

        # Monitor.classes=['PiPresents','MediaShow','GapShow','Show','VideoPlayer','Player','OMXDriver']
        # Monitor.classes=['OSCDriver']
        
        # get global log level from command line
        Monitor.log_level = int(self.options['debug'])
        Monitor.manager = self.options['manager']
        # print self.options['manager']
        self.mon.newline(3)
        self.mon.sched (self,None, "Pi Presents is starting, Version:"+self.pipresents_minorissue + ' at '+time.strftime("%Y-%m-%d %H:%M.%S"))
        self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue+ ' at '+time.strftime("%Y-%m-%d %H:%M.%S"))
        # self.mon.log (self," OS and separator:" + os.name +'  ' + os.sep)
        self.mon.log(self,"sys.path[0] -  location of code: "+sys.path[0])

        # log versions of Raspbian and omxplayer, and GPU Memory
        with open("/boot/issue.txt") as ifile:
            self.mon.log(self,'\nRaspbian: '+ifile.read())

        self.mon.log(self,'\n'+check_output(["omxplayer", "-v"]))
        self.mon.log(self,'\nGPU Memory: '+check_output(["vcgencmd", "get_mem", "gpu"]))

        if os.geteuid() == 0:
            print 'Do not run Pi Presents with sudo'
            self.mon.log(self,'Do not run Pi Presents with sudo')
            self.mon.finish()
            sys.exit(102)

        
        if "DESKTOP_SESSION" not in os.environ:
            print 'Pi Presents must be run from the Desktop'
            self.mon.log(self,'Pi Presents must be run from the Desktop')
            self.mon.finish()
            sys.exit(102)
        else:
            self.mon.log(self,'Desktop is '+ os.environ['DESKTOP_SESSION'])
        
        # optional other classes used
        self.root=None
        self.ppio=None
        self.tod=None
        self.animate=None
        self.ioplugin_manager=None
        self.oscdriver=None
        self.osc_enabled=False
        self.tod_enabled=False
        self.email_enabled=False
        
        user=os.getenv('USER')

        if user is None:
            tkMessageBox.showwarning("You must be logged in to run Pi Presents")
            exit(102)

        if user !='pi':
            self.mon.warn(self,"You must be logged as pi to use GPIO")

        self.mon.log(self,'User is: '+ user)
        # self.mon.log(self,"os.getenv('HOME') -  user home directory (not used): " + os.getenv('HOME')) # does not work
        # self.mon.log(self,"os.path.expanduser('~') -  user home directory: " + os.path.expanduser('~'))   # does not work



        # check network is available
        self.network_connected=False
        self.network_details=False
        self.interface=''
        self.ip=''
        self.unit=''
        
        # sets self.network_connected and self.network_details
        self.init_network()

        
        # start the mailer and send email when PP starts
        self.email_enabled=False
        if self.network_connected is True:
            self.init_mailer()
            if self.email_enabled is True and self.mailer.email_at_start is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Started on ' + time.strftime("%Y-%m-%d %H:%M")
                message = time.strftime("%Y-%m-%d %H:%M") + '\nUnit: ' + self.unit + '   Profile: '+ self.options['profile']+ '\n ' + self.interface + '\n ' + self.ip 
                self.send_email('start',subject,message) 

         
        # get profile path from -p option
        if self.options['profile'] != '':
            self.pp_profile_path="/pp_profiles/"+self.options['profile']
        else:
            self.mon.err(self,"Profile not specified in command ")
            self.end('error','Profile not specified with the commands -p option')
        
       # get directory containing pp_home from the command,
        if self.options['home']  == "":
            home = os.sep+ 'home' + os.sep + user + os.sep+"pp_home"
        else:
            home = self.options['home'] + os.sep+ "pp_home"         
        self.mon.log(self,"pp_home directory is: " + home)


        # check if pp_home exists.
        # try for 10 seconds to allow usb stick to automount
        found=False
        for i in range (1, 10):
            self.mon.log(self,"Trying pp_home at: " + home +  " (" + str(i)+')')
            if os.path.exists(home):
                found=True
                self.pp_home=home
                break
            time.sleep (1)
        if found is True:
            self.mon.log(self,"Found Requested Home Directory, using pp_home at: " + home)
        else:
            self.mon.err(self,"Failed to find pp_home directory at " + home)
            self.end('error',"Failed to find pp_home directory at " + home)


        # check profile exists
        self.pp_profile=self.pp_home+self.pp_profile_path
        if os.path.exists(self.pp_profile):
            self.mon.sched(self,None,"Running profile: " + self.pp_profile_path)
            self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile)
        else:
            self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile)
            self.end('error',"Failed to find requested profile: "+ self.pp_profile)

        self.mon.start_stats(self.options['profile'])
        
        if self.options['verify'] is True:
            self.mon.err(self,"Validation option not supported - use the editor")
            self.end('error','Validation option not supported - use the editor')

         
        # initialise and read the showlist in the profile
        self.showlist=ShowList()
        self.showlist_file= self.pp_profile+ "/pp_showlist.json"
        if os.path.exists(self.showlist_file):
            self.showlist.open_json(self.showlist_file)
        else:
            self.mon.err(self,"showlist not found at "+self.showlist_file)
            self.end('error',"showlist not found at "+self.showlist_file)

        # check profile and Pi Presents issues are compatible
        if self.showlist.profile_version() != self.pipresents_version():
            self.mon.err(self,"Version of showlist " + self.showlist.profile_version_string + " is not  same as Pi Presents")
            self.end('error',"Version of showlist " + self.showlist.profile_version_string + " is not  same as Pi Presents")


        # get the 'start' show from the showlist
        index = self.showlist.index_of_start_show()
        if index >=0:
            self.showlist.select(index)
            self.starter_show=self.showlist.selected_show()
        else:
            self.mon.err(self,"Show [start] not found in showlist")
            self.end('error',"Show [start] not found in showlist")


# ********************
# SET UP THE GUI
# ********************
        # turn off the screenblanking and saver
        if self.options['noblank'] is True:
            call(["xset","s", "off"])
            call(["xset","s", "-dpms"])

        self.root=Tk()   
       
        self.title='Pi Presents - '+ self.pp_profile
        self.icon_text= 'Pi Presents'
        self.root.title(self.title)
        self.root.iconname(self.icon_text)
        self.root.config(bg=self.starter_show['background-colour'])

        self.mon.log(self, 'monitor screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixels')
        if self.options['screensize'] =='':        
            self.screen_width = self.root.winfo_screenwidth()
            self.screen_height = self.root.winfo_screenheight()
        else:
            reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize'])
            if reason =='error':
                self.mon.err(self,message)
                self.end('error',message)

        self.mon.log(self, 'forced screen dimensions (--screensize) are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixels')
       
        # set window dimensions and decorations
        if self.options['fullscreen'] is False:
            self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width)
            self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height)
            self.window_x=self.nonfull_window_x
            self.window_y=self.nonfull_window_y
            self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y))
        else:
            self.window_width=self.screen_width
            self.window_height=self.screen_height
            self.root.attributes('-fullscreen', True)
            os.system('unclutter &')
            self.window_x=0
            self.window_y=0  
            self.root.geometry("%dx%d%+d%+d"  % (self.window_width,self.window_height,self.window_x,self.window_y))
            self.root.attributes('-zoomed','1')

        # canvas cover the whole screen whatever the size of the window. 
        self.canvas_height=self.screen_height
        self.canvas_width=self.screen_width
  
        # make sure focus is set.
        self.root.focus_set()

        # define response to main window closing.
        self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort)

        # setup a canvas onto which will be drawn the images or text
        self.canvas = Canvas(self.root, bg=self.starter_show['background-colour'])


        if self.options['fullscreen'] is True:
            self.canvas.config(height=self.canvas_height,
                               width=self.canvas_width,
                               highlightthickness=0)
        else:
            self.canvas.config(height=self.canvas_height,
                    width=self.canvas_width,
                        highlightthickness=1,
                               highlightcolor='yellow')
            
        self.canvas.place(x=0,y=0)
        # self.canvas.config(bg='black')
        self.canvas.focus_set()


                
# ****************************************
# INITIALISE THE TOUCHSCREEN DRIVER
# ****************************************

        # each driver takes a set of inputs, binds them to symboic names
        # and sets up a callback which returns the symbolic name when an input event occurs

        self.sr=ScreenDriver()
        # read the screen click area config file
        reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile)
        if reason == 'error':
            self.end('error','cannot find, or error in screen.cfg')


        # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes
        # click areas are made on the Pi Presents canvas not the show canvases.
        reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event)
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)


# ****************************************
# INITIALISE THE APPLICATION AND START
# ****************************************
        self.shutdown_required=False
        self.reboot_required=False
        self.terminate_required=False
        self.exitpipresents_required=False

        # initialise the I/O plugins by importing their drivers
        self.ioplugin_manager=IOPluginManager()
        reason,message=self.ioplugin_manager.init(self.pp_dir,self.pp_profile,self.root,self.handle_input_event)
        if reason == 'error':
            # self.mon.err(self,message)
            self.end('error',message)

        
        # kick off animation sequencer
        self.animate = Animate()
        self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event)
        self.animate.poll()

        #create a showmanager ready for time of day scheduler and osc server
        show_id=-1
        self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home)
        # first time through set callback to terminate Pi Presents if all shows have ended.
        self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist)
        # Register all the shows in the showlist
        reason,message=self.show_manager.register_shows()
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)


        # Init OSCDriver, read config and start OSC server
        self.osc_enabled=False
        if self.network_connected is True:
            if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'):
                self.oscdriver=OSCDriver()
                reason,message=self.oscdriver.init(self.pp_profile,
                                                   self.unit,self.interface,self.ip,
                                                   self.handle_command,self.handle_input_event,self.e_osc_handle_animate)
                if reason == 'error':
                    self.mon.err(self,message)
                    self.end('error',message)
                else:
                    self.osc_enabled=True
                    self.root.after(1000,self.oscdriver.start_server())

        
        # initialise ToD scheduler calculating schedule for today
        self.tod=TimeOfDay()
        reason,message,self.tod_enabled = self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.showlist,self.root,self.handle_command)
        if reason == 'error':
            self.mon.err(self,message)
            self.end('error',message)
            
        # warn if the network not available when ToD required
        if self.tod_enabled is True and self.network_connected is False:
            self.mon.warn(self,'Network not connected  so Time of Day scheduler may be using the internal clock')

        # init the counter manager
        self.counter_manager=CounterManager()
        self.counter_manager.init()


        # warn about start shows and scheduler

        if self.starter_show['start-show']=='' and self.tod_enabled is False:
            self.mon.sched(self,None,"No Start Shows in Start Show and no shows scheduled") 
            self.mon.warn(self,"No Start Shows in Start Show and no shows scheduled")

        if self.starter_show['start-show'] !='' and self.tod_enabled is True:
            self.mon.sched(self,None,"Start Shows in Start Show and shows scheduled - conflict?") 
            self.mon.warn(self,"Start Shows in Start Show and shows scheduled - conflict?")

        # run the start shows
        self.run_start_shows()           

        # kick off the time of day scheduler which may run additional shows
        if self.tod_enabled is True:
            self.tod.poll()

        # start the I/O plugins input event generation
        self.ioplugin_manager.start()


        # start Tkinters event loop
        self.root.mainloop( )


    def parse_screen(self,size_text):
        fields=size_text.split('*')
        if len(fields)!=2:
            return 'error','do not understand --screensize comand option',0,0
        elif fields[0].isdigit()  is False or fields[1].isdigit()  is False:
            return 'error','dimensions are not positive integers in --screensize',0,0
        else:
            return 'normal','',int(fields[0]),int(fields[1])
        

# *********************
#  RUN START SHOWS
# ********************   
    def run_start_shows(self):
        self.mon.trace(self,'run start shows')
        # parse the start shows field and start the initial shows       
        show_refs=self.starter_show['start-show'].split()
        for show_ref in show_refs:
            reason,message=self.show_manager.control_a_show(show_ref,'open')
            if reason == 'error':
                self.mon.err(self,message)
                


# *********************
# User inputs
# ********************

    def e_osc_handle_animate(self,line):
        #jump  out of server thread
        self.root.after(1, lambda arg=line: self.osc_handle_animate(arg))

    def osc_handle_animate(self,line):
        self.mon.log(self,"animate command received: "+ line)
        #osc sends output events as a string
        reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line)
        if reason == 'error':
            self.mon.err(self,message)
            self.end(reason,message)
        self.handle_output_event(name,param_type,param_values,0)

    # output events are animate commands       
    def handle_output_event(self,symbol,param_type,param_values,req_time):
            reason,message=self.ioplugin_manager.handle_output_event(symbol,param_type,param_values,req_time)
            if reason =='error':
                self.mon.err(self,message)
                self.end(reason,message)



    # all input events call this callback providing a symbolic name.
    # handle events that affect PP overall, otherwise pass to all active shows
    def handle_input_event(self,symbol,source):
        self.mon.log(self,"event received: "+symbol + ' from '+ source)
        if symbol == 'pp-terminate':
            self.handle_user_abort()
            
        elif symbol == 'pp-shutdown':
            self.mon.err(self,'pp-shutdown removed in version 1.3.3a, see Release Notes')
            self.end('error','pp-shutdown removed in version 1.3.3a, see Release Notes')

            
        elif symbol == 'pp-shutdownnow':
            # need root.after to grt out of st thread
            self.root.after(1,self.shutdownnow_pressed)
            return
        
        elif symbol == 'pp-exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to grt out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            reason,message= self.show_manager.exit_all_shows()
        else:
            # pass the input event to all registered shows
            for show in self.show_manager.shows:
                show_obj=show[ShowManager.SHOW_OBJ]
                if show_obj is not None:
                    show_obj.handle_input_event(symbol)



    # commands are generaed by tracks and shows
    # they can open or close shows, generate input events and do special tasks
    # commands also generate osc outputs to other computers
    # handles one command provided as a line of text
    
    def handle_command(self,command_text,source='',show=''):
        # print 'PIPRESENTS ',command_text,'\n   Source',source,'from',show
        self.mon.log(self,"command received: " + command_text)
        if command_text.strip()=="":
            return

        fields= command_text.split()

        if fields[0] in ('osc','OSC'): 
            if self.osc_enabled is True:
                status,message=self.oscdriver.parse_osc_command(fields[1:])
                if status=='warn':
                    self.mon.warn(self,message)
                if status=='error':
                    self.mon.err(self,message)
                    self.end('error',message)
                return
        

        if fields[0] =='counter':
            status,message=self.counter_manager.parse_counter_command(fields[1:])
            if status=='error':
                self.mon.err(self,message)
                self.end('error',message)
            return

                           
        show_command=fields[0]
        if len(fields)>1:
            show_ref=fields[1]
        else:
            show_ref=''
        if show_command in ('open','close','closeall','openexclusive'):
            self.mon.sched(self, TimeOfDay.now,command_text + ' received from show:'+show)
            if self.shutdown_required is False and self.terminate_required is False:
                reason,message=self.show_manager.control_a_show(show_ref,show_command)
            else:
                return
            
        elif show_command =='monitor':
            self.handle_monitor_command(show_ref)
            return

        elif show_command =='cec':
            self.handle_cec_command(show_ref)
            return
        
        elif show_command == 'event':
            self.handle_input_event(show_ref,'Show Control')
            return
        
        elif show_command == 'exitpipresents':
            self.exitpipresents_required=True
            if self.show_manager.all_shows_exited() is True:
                # need root.after to get out of st thread
                self.root.after(1,self.e_all_shows_ended_callback)
                return
            else:
                reason,message= self.show_manager.exit_all_shows()

        elif show_command == 'shutdownnow':
            # need root.after to get out of st thread
            self.root.after(1,self.shutdownnow_pressed)
            return

        elif show_command == 'reboot':
            # need root.after to get out of st thread
            self.root.after(1,self.reboot_pressed)
            return
        
        else:
            reason='error'
            message = 'command not recognised: '+ show_command
            
        if reason=='error':
            self.mon.err(self,message)
        return


    def handle_monitor_command(self,command):
        if command == 'on':
            os.system('vcgencmd display_power 1 >/dev/null')
        elif command == 'off':
            os.system('vcgencmd display_power 0 >/dev/null')

    def handle_cec_command(self,command):
        if command == 'on':
            os.system('echo "on 0" | cec-client -s')
        elif command == 'standby':
            os.system('echo "standby 0" | cec-client -s')

        elif command == 'scan':
            os.system('echo scan | cec-client -s -d 1')
                      
    # deal with differnt commands/input events

    def shutdownnow_pressed(self):
        self.shutdown_required=True
        if self.show_manager.all_shows_exited() is True:
           self.all_shows_ended_callback('normal','no shows running')
        else:
            # calls exit method of all shows, results in all_shows_closed_callback
            self.show_manager.exit_all_shows()

    def reboot_pressed(self):
        self.reboot_required=True
        if self.show_manager.all_shows_exited() is True:
           self.all_shows_ended_callback('normal','no shows running')
        else:
            # calls exit method of all shows, results in all_shows_closed_callback
            self.show_manager.exit_all_shows() 


    def handle_sigterm(self,signum,fframe):
        self.mon.log(self,'SIGTERM received - '+ str(signum))
        self.terminate()


    def handle_user_abort(self):
        self.mon.log(self,'User abort received')
        self.terminate()

    def terminate(self):
        self.mon.log(self, "terminate received")
        self.terminate_required=True
        needs_termination=False
        for show in self.show_manager.shows:
            # print  show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF]
            if show[ShowManager.SHOW_OBJ] is not None:
                needs_termination=True
                self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF])
                # call shows terminate method
                # eventually the show will exit and after all shows have exited all_shows_callback will be executed.
                show[ShowManager.SHOW_OBJ].terminate()
        if needs_termination is False:
            self.end('killed','killed - no termination of shows required')



# ******************************
# Ending Pi Presents after all the showers and players are closed
# **************************

    def e_all_shows_ended_callback(self):
        self.all_shows_ended_callback('normal','no shows running')

    # callback from ShowManager when all shows have ended
    def all_shows_ended_callback(self,reason,message):
        self.canvas.config(bg=self.starter_show['background-colour'])
        if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True or self.reboot_required is True:
            self.end(reason,message)

    def end(self,reason,message):
        self.mon.log(self,"Pi Presents ending with reason: " + reason)
        if self.root is not None:
            self.root.destroy()
        self.tidy_up()
        if reason == 'killed':
            if self.email_enabled is True and self.mailer.email_on_terminate is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Terminated'
                message = time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip 
                self.send_email(reason,subject,message)
            self.mon.sched(self, None,"Pi Presents Terminated, au revoir\n")
            self.mon.log(self, "Pi Presents Terminated, au revoir")
                          
            # close logging files
            self.mon.finish()
            print 'Uncollectable Garbage',gc.collect()
            # objgraph.show_backrefs(objgraph.by_type('Monitor'))
            sys.exit(101)
                          
        elif reason == 'error':
            if self.email_enabled is True and self.mailer.email_on_error is True:
                subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Error'
                message_text = 'Error message: '+ message + '\n'+ time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip 
                self.send_email(reason,subject,message_text)   
            self.mon.sched(self,None, "Pi Presents closing because of error, sorry\n")
            self.mon.log(self, "Pi Presents closing because of error, sorry")
                          
            # close logging files 
            self.mon.finish()
            print 'uncollectable garbage',gc.collect()
            sys.exit(102)

        else:           
            self.mon.sched(self,None,"Pi Presents  exiting normally, bye\n")
            self.mon.log(self,"Pi Presents  exiting normally, bye")
            
            # close logging files 
            self.mon.finish()
            if self.reboot_required is True:
                # print 'REBOOT'
                call (['sudo','reboot'])
            if self.shutdown_required is True:
                # print 'SHUTDOWN'
                call (['sudo','shutdown','now','SHUTTING DOWN'])
            print 'uncollectable garbage',gc.collect()
            sys.exit(100)


    # tidy up all the peripheral bits of Pi Presents
    def tidy_up(self):
        self.handle_monitor_command('on')
        self.mon.log(self, "Tidying Up")
        # turn screen blanking back on
        if self.options['noblank'] is True:
            call(["xset","s", "on"])
            call(["xset","s", "+dpms"])
            
        # tidy up animation
        if self.animate is not None:
            self.animate.terminate()

        # tidy up i/o plugins
        if self.ioplugin_manager != None:
            self.ioplugin_manager.terminate()

        if self.osc_enabled is True:
            self.oscdriver.terminate()
            
        # tidy up time of day scheduler
        if self.tod_enabled is True:
            self.tod.terminate()



# *******************************
# Connecting to network and email
# *******************************

    def init_network(self):

        timeout=int(self.options['nonetwork'])
        if timeout== 0:
            self.network_connected=False
            self.unit=''
            self.ip=''
            self.interface=''
            return
        
        self.network=Network()
        self.network_connected=False

        # try to connect to network
        self.mon.log (self, 'Waiting up to '+ str(timeout) + ' seconds for network')
        success=self.network.wait_for_network(timeout)
        if success is False:
            self.mon.warn(self,'Failed to connect to network after ' + str(timeout) + ' seconds')
            # tkMessageBox.showwarning("Pi Presents","Failed to connect to network so using fake-hwclock")
            return

        self.network_connected=True
        self.mon.sched (self, None,'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S"))
        self.mon.log (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S"))

        # Get web configuration
        self.network_details=False
        network_options_file_path=self.pp_dir+os.sep+'pp_config'+os.sep+'pp_web.cfg'
        if not os.path.exists(network_options_file_path):
            self.mon.warn(self,"pp_web.cfg not found at "+network_options_file_path)
            return
        self.mon.log(self, 'Found pp_web.cfg in ' + network_options_file_path)

        self.network.read_config(network_options_file_path)
        self.unit=self.network.unit

        # get interface and IP details of preferred interface
        self.interface,self.ip = self.network.get_preferred_ip()
        if self.interface == '':
            self.network_connected=False
            return
        self.network_details=True
        self.mon.log (self, 'Network details ' + self.unit + ' ' + self.interface + ' ' +self.ip)


    def init_mailer(self):

        self.email_enabled=False
        email_file_path = self.pp_dir+os.sep+'pp_config'+os.sep+'pp_email.cfg'
        if not os.path.exists(email_file_path):
            self.mon.log(self,'pp_email.cfg not found at ' + email_file_path)
            return
        self.mon.log(self,'Found pp_email.cfg at ' + email_file_path)
        self.mailer=Mailer()
        self.mailer.read_config(email_file_path)
        # all Ok so can enable email if config file allows it.
        if self.mailer.email_allowed is True:
            self.email_enabled=True
            self.mon.log (self,'Email Enabled')


    def try_connect(self):
        tries=1
        while True:
            success, error = self.mailer.connect()
            if success is True:
                return True
            else:
                self.mon.log(self,'Failed to connect to email SMTP server ' + str(tries) +  '\n ' +str(error))
                tries +=1
                if tries >5:
                    self.mon.log(self,'Failed to connect to email SMTP server after ' + str(tries))
                    return False


    def send_email(self,reason,subject,message):
        if self.try_connect() is False:
            return False
        else:
            success,error = self.mailer.send(subject,message)
            if success is False:
                self.mon.log(self, 'Failed to send email: ' + str(error))
                success,error=self.mailer.disconnect()
                if success is False:
                    self.mon.log(self,'Failed disconnect after send:' + str(error))
                return False
            else:
                self.mon.log(self,'Sent email for ' + reason)
                success,error=self.mailer.disconnect()
                if success is False:
                    self.mon.log(self,'Failed disconnect from email server ' + str(error))
                return True