def __init__(self, *args, **kwds):
        # Última leitura
        self.last_letter = ''
        self.last_valid_letter = ''
        self.letter_count = 0

        # Valores padrões da serial
        self.serial = serial.Serial()
        self.serial.port = 0;
        self.serial.baudrate = 19200;
        self.serial.bytesize = 8;
        self.serial.parity = serial.PARITY_NONE;
        self.serial.stopbits = 1;
        self.serial.timeout = TIMEOUT_SERIAL;
        self.serial.rtscts = False;
        self.serial.xonxoff = False;

        # Tradutor
        contraido = [1, 2, 1, 1, 2]
        relaxado = [30, 30, 25, 20, 30]
        esticado = [180, 170, 180, 168, 120]
        self.translator = HTTranslator ()
        self.translator.adjust (esticado, relaxado, contraido)

        # Threading
        self.thread = None
        self.alive = threading.Event()               

        # begin wxGlade: HTMain.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.divisor = wx.SplitterWindow(self, -1, style=wx.SP_PERMIT_UNSPLIT)
        self.ladoDireito = wx.Panel(self.divisor, -1)
        self.ladoEsquerdo = wx.Panel(self.divisor, -1)
        self.sizerSaida_staticbox = wx.StaticBox(self.ladoEsquerdo, -1, u"Saída")
        self.sizerHistorico_staticbox = wx.StaticBox(self.ladoDireito, -1, u"Histórico")
        self.sizerEntrada_staticbox = wx.StaticBox(self.ladoEsquerdo, -1, "Entrada")
        
        # Menu Bar
        self.janela_menubar = wx.MenuBar()
        self.SetMenuBar(self.janela_menubar)
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_NOVO, "&Novo", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(ID_ABRIR, "&Abrir...", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_GRAVAR, "&Gravar", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(ID_GRAVAR_COMO, "Gravar &Como...", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_AJUSTAR, "Ajus&tar...", "", wx.ITEM_NORMAL)
        self.janela_menubar.Append(wxglade_tmp_menu, u"&Usuários")
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_CONFIG, "Confi&gurar...", "Ajusta detalhes da porta serial", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_COMUNIC, "&Comunicar", u"Inicia/Interrompe comunicação", wx.ITEM_CHECK)
        self.janela_menubar.Append(wxglade_tmp_menu, u"&Comunicação")
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_SOBRE, "So&bre...", u"Informações sobre o HandTalks!", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_SAIR, "&Sair", "Fecha o HandTalks!", wx.ITEM_NORMAL)
        self.janela_menubar.Append(wxglade_tmp_menu, "&Geral")
        # Menu Bar end
        self.janela_statusbar = self.CreateStatusBar(7, wx.ST_SIZEGRIP)
        
        # Tool Bar
        self.janela_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_DOCKABLE)
        self.SetToolBar(self.janela_toolbar)
        self.janela_toolbar.AddLabelTool(ID_ABRIR, u"Abrir usuário...", wx.Bitmap("imagem/Abrir.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, u"Abrir usuário...", u"Carrega os ajustes da luva de um usuário")
        self.janela_toolbar.AddLabelTool(ID_GRAVAR, u"Gravar usuário...", wx.Bitmap("imagem/Gravar.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, u"Gravar usuário...", u"Grava os ajustes da luva de um usuário")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_AJUSTAR, "Ajustar...", wx.Bitmap("imagem/Usuario.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Ajustar...", u"Faz o ajuste das letras com a mão do usuário")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_CONFIG, "Configurar...", wx.Bitmap("imagem/Config.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Configurar...", "Ajusta detalhes da porta serial")
        self.janela_toolbar.AddLabelTool(ID_COMUNIC, "Comunicar", wx.Bitmap("imagem/Parado.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_CHECK, "Comunicar", u"Inicia/Interrompe comunicação")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_SOBRE, "Sobre...", wx.Bitmap("imagem/Info.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Sobre...", u"Informações sobre o HandTalks!")
        self.janela_toolbar.AddLabelTool(ID_SAIR, "Sair", wx.Bitmap("imagem/Fechar.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Sair", "Fecha o HandTalks!")
        # Tool Bar end
        self.resposta = wx.TextCtrl(self.ladoEsquerdo, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.letraExibida = wx.StaticText(self.ladoEsquerdo, -1, "A", style=wx.ALIGN_CENTRE|wx.ST_NO_AUTORESIZE)
        self.historico = wx.TextCtrl(self.ladoDireito, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.btLimpar = wx.Button(self.ladoDireito, -1, "Limpar")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_MENU, self.configuraSerial, id=ID_CONFIG)
        self.Bind(wx.EVT_MENU, self.alternaComunicacao, id=ID_COMUNIC)
        self.Bind(wx.EVT_MENU, self.sobreHandtalks, id=ID_SOBRE)
        self.Bind(wx.EVT_MENU, self.sair, id=ID_SAIR)
        self.Bind(wx.EVT_BUTTON, self.limpaHistorico, self.btLimpar)
        # end wxGlade

        # Mais eventos
        self.Bind(wx.EVT_CLOSE, self.fechaAplicacao)
        self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.mostraAjuda)
        self.Bind(wx.EVT_TOOL_ENTER, self.mostraAjuda)
        self.Bind(EVT_SERIALRX, self.OnSerialRead)

        # Associa um Ícone
        ib = wx.IconBundle()
        ib.AddIconFromFile("imagem/handtalks.ico",wx.BITMAP_TYPE_ANY)
        self.SetIcons(ib)
class HTMain(wx.Frame):
    def __init__(self, *args, **kwds):
        # Última leitura
        self.last_letter = ''
        self.last_valid_letter = ''
        self.letter_count = 0

        # Valores padrões da serial
        self.serial = serial.Serial()
        self.serial.port = 0;
        self.serial.baudrate = 19200;
        self.serial.bytesize = 8;
        self.serial.parity = serial.PARITY_NONE;
        self.serial.stopbits = 1;
        self.serial.timeout = TIMEOUT_SERIAL;
        self.serial.rtscts = False;
        self.serial.xonxoff = False;

        # Tradutor
        contraido = [1, 2, 1, 1, 2]
        relaxado = [30, 30, 25, 20, 30]
        esticado = [180, 170, 180, 168, 120]
        self.translator = HTTranslator ()
        self.translator.adjust (esticado, relaxado, contraido)

        # Threading
        self.thread = None
        self.alive = threading.Event()               

        # begin wxGlade: HTMain.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.divisor = wx.SplitterWindow(self, -1, style=wx.SP_PERMIT_UNSPLIT)
        self.ladoDireito = wx.Panel(self.divisor, -1)
        self.ladoEsquerdo = wx.Panel(self.divisor, -1)
        self.sizerSaida_staticbox = wx.StaticBox(self.ladoEsquerdo, -1, u"Saída")
        self.sizerHistorico_staticbox = wx.StaticBox(self.ladoDireito, -1, u"Histórico")
        self.sizerEntrada_staticbox = wx.StaticBox(self.ladoEsquerdo, -1, "Entrada")
        
        # Menu Bar
        self.janela_menubar = wx.MenuBar()
        self.SetMenuBar(self.janela_menubar)
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_NOVO, "&Novo", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(ID_ABRIR, "&Abrir...", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_GRAVAR, "&Gravar", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(ID_GRAVAR_COMO, "Gravar &Como...", "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_AJUSTAR, "Ajus&tar...", "", wx.ITEM_NORMAL)
        self.janela_menubar.Append(wxglade_tmp_menu, u"&Usuários")
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_CONFIG, "Confi&gurar...", "Ajusta detalhes da porta serial", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_COMUNIC, "&Comunicar", u"Inicia/Interrompe comunicação", wx.ITEM_CHECK)
        self.janela_menubar.Append(wxglade_tmp_menu, u"&Comunicação")
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_SOBRE, "So&bre...", u"Informações sobre o HandTalks!", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ID_SAIR, "&Sair", "Fecha o HandTalks!", wx.ITEM_NORMAL)
        self.janela_menubar.Append(wxglade_tmp_menu, "&Geral")
        # Menu Bar end
        self.janela_statusbar = self.CreateStatusBar(7, wx.ST_SIZEGRIP)
        
        # Tool Bar
        self.janela_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_DOCKABLE)
        self.SetToolBar(self.janela_toolbar)
        self.janela_toolbar.AddLabelTool(ID_ABRIR, u"Abrir usuário...", wx.Bitmap("imagem/Abrir.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, u"Abrir usuário...", u"Carrega os ajustes da luva de um usuário")
        self.janela_toolbar.AddLabelTool(ID_GRAVAR, u"Gravar usuário...", wx.Bitmap("imagem/Gravar.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, u"Gravar usuário...", u"Grava os ajustes da luva de um usuário")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_AJUSTAR, "Ajustar...", wx.Bitmap("imagem/Usuario.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Ajustar...", u"Faz o ajuste das letras com a mão do usuário")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_CONFIG, "Configurar...", wx.Bitmap("imagem/Config.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Configurar...", "Ajusta detalhes da porta serial")
        self.janela_toolbar.AddLabelTool(ID_COMUNIC, "Comunicar", wx.Bitmap("imagem/Parado.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_CHECK, "Comunicar", u"Inicia/Interrompe comunicação")
        self.janela_toolbar.AddSeparator()
        self.janela_toolbar.AddLabelTool(ID_SOBRE, "Sobre...", wx.Bitmap("imagem/Info.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Sobre...", u"Informações sobre o HandTalks!")
        self.janela_toolbar.AddLabelTool(ID_SAIR, "Sair", wx.Bitmap("imagem/Fechar.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Sair", "Fecha o HandTalks!")
        # Tool Bar end
        self.resposta = wx.TextCtrl(self.ladoEsquerdo, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.letraExibida = wx.StaticText(self.ladoEsquerdo, -1, "A", style=wx.ALIGN_CENTRE|wx.ST_NO_AUTORESIZE)
        self.historico = wx.TextCtrl(self.ladoDireito, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.btLimpar = wx.Button(self.ladoDireito, -1, "Limpar")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_MENU, self.configuraSerial, id=ID_CONFIG)
        self.Bind(wx.EVT_MENU, self.alternaComunicacao, id=ID_COMUNIC)
        self.Bind(wx.EVT_MENU, self.sobreHandtalks, id=ID_SOBRE)
        self.Bind(wx.EVT_MENU, self.sair, id=ID_SAIR)
        self.Bind(wx.EVT_BUTTON, self.limpaHistorico, self.btLimpar)
        # end wxGlade

        # Mais eventos
        self.Bind(wx.EVT_CLOSE, self.fechaAplicacao)
        self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.mostraAjuda)
        self.Bind(wx.EVT_TOOL_ENTER, self.mostraAjuda)
        self.Bind(EVT_SERIALRX, self.OnSerialRead)

        # Associa um Ícone
        ib = wx.IconBundle()
        ib.AddIconFromFile("imagem/handtalks.ico",wx.BITMAP_TYPE_ANY)
        self.SetIcons(ib)


    def __set_properties(self):
        # begin wxGlade: HTMain.__set_properties
        self.SetTitle("Hand Talks!")
        self.SetSize(wx.DLG_SZE(self, (340, 296)))
        self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
        self.janela_statusbar.SetStatusWidths([-1, 80, 60, 20, 20, 20, 80])
        # statusbar fields
        janela_statusbar_fields = ["", "", "", "", "", "", ""]
        for i in range(len(janela_statusbar_fields)):
            self.janela_statusbar.SetStatusText(janela_statusbar_fields[i], i)
        self.janela_toolbar.SetToolBitmapSize((16, 16))
        self.janela_toolbar.Realize()
        self.resposta.SetToolTipString("Resposta da luva")
        self.resposta.Enable(False)
        self.letraExibida.SetFont(wx.Font(150, wx.DECORATIVE, wx.NORMAL, wx.NORMAL, 0, ""))
        self.historico.SetFont(wx.Font(30, wx.DECORATIVE, wx.NORMAL, wx.NORMAL, 0, ""))
        self.historico.SetToolTipString(u"Histórico da comunicação com a luva")
        self.historico.Enable(False)
        # end wxGlade

        # Popula a caixa de letras
#        self.caixaLetras.AppendItems( [chr (ord('A') + x) for x in range (26)] )
#        self.caixaLetras.Select(0)
        
        # Vai ser um timer
        self.timerStatus = None

        # Barra de estado
        self.reportaErro (u'Bem-vindo ao HandTalks!')
        self.atualizaStatusSerial()


    def __do_layout(self):
        # begin wxGlade: HTMain.__do_layout
        sizerJanela = wx.BoxSizer(wx.HORIZONTAL)
        sizerHistorico = wx.StaticBoxSizer(self.sizerHistorico_staticbox, wx.VERTICAL)
        sizerPrincipal = wx.BoxSizer(wx.VERTICAL)
        sizerSaida = wx.StaticBoxSizer(self.sizerSaida_staticbox, wx.VERTICAL)
        sizerEntrada = wx.StaticBoxSizer(self.sizerEntrada_staticbox, wx.HORIZONTAL)
        sizerEntrada.Add(self.resposta, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 3)
        sizerPrincipal.Add(sizerEntrada, 0, wx.ALL|wx.EXPAND, 3)
        sizerSaida.Add((1, 1), 1, wx.ADJUST_MINSIZE, 0)
        sizerSaida.Add(self.letraExibida, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 3)
        sizerSaida.Add((1, 1), 1, wx.ADJUST_MINSIZE, 0)
        sizerPrincipal.Add(sizerSaida, 1, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 3)
        self.ladoEsquerdo.SetAutoLayout(True)
        self.ladoEsquerdo.SetSizer(sizerPrincipal)
        sizerPrincipal.Fit(self.ladoEsquerdo)
        sizerPrincipal.SetSizeHints(self.ladoEsquerdo)
        sizerHistorico.Add(self.historico, 1, wx.ALL|wx.EXPAND, 3)
        sizerHistorico.Add(self.btLimpar, 0, wx.ALL, 3)
        self.ladoDireito.SetAutoLayout(True)
        self.ladoDireito.SetSizer(sizerHistorico)
        sizerHistorico.Fit(self.ladoDireito)
        sizerHistorico.SetSizeHints(self.ladoDireito)
        self.divisor.SplitVertically(self.ladoEsquerdo, self.ladoDireito)
        sizerJanela.Add(self.divisor, 1, wx.ALL|wx.EXPAND, 3)
        self.SetAutoLayout(True)
        self.SetSizer(sizerJanela)
        self.Layout()
        self.Centre()
        # end wxGlade


    def mostraAjuda(self, event):
        try:
            msg = self.GetMenuBar().GetHelpString(event.GetId())
        except:
            try:
                msg = self.GetMenuBar().GetHelpString(event.GetSelection())
            except:
                msg = ''
        self.reportaErro (msg)


    def atualizaStatusSerial(self):
        janela_statusbar_fields = [ self.serial.portstr,
                                    str(self.serial.baudrate),
                                    str(self.serial.bytesize),
                                    self.serial.parity,
                                    str(self.serial.stopbits),
                                    (self.serial.rtscts and 'RTS/CTS ' or '') +
                                    (self.serial.xonxoff and 'XON/XOFF' or '') ]
        for i in range(len(janela_statusbar_fields)):
            self.janela_statusbar.SetStatusText(janela_statusbar_fields[i], i+1)

    def reportaErro (self, frase=''):
        self.janela_statusbar.SetStatusText(frase, 0)
        if len(frase) > 0:
            if self.timerStatus is not None:
                self.timerStatus.cancel()
            self.timerStatus = threading.Timer(3.0, self.reportaErro)
            self.timerStatus.start()


    def configuraSerial(self, event): # wxGlade: HTMain.<event_handler>
        if self.serial.isOpen():
            self.alternaComunicacao (event)

        dlg = HTSerialConfig (None, -1, "", serial=self.serial)
        
        if (dlg.ShowModal() == wx.ID_OK):
            self.atualizaStatusSerial()
        else:
            self.reportaErro (u"Operação cancelada!")

        dlg.Destroy()

    def exibeLetra (self, letra=None):
        if letra is None:
            letra = ''
            
        self.letraExibida.SetLabel (letra)
        self.reportaErro(u'Reproduzindo Áudio...')


#        if not self.IsMaximized():
#            self.GetSizer().SetSizeHints(self)
#            self.Refresh()
#            self.Update()
        
        # Toca wav, mp3 etc, usando pymedia
#        if tocador.toca_tudo ("audio/" + letra):
#            self.reportaErro()
#        else:
#            self.reportaErro(u'Falha na execução!')

    def tocaLetra (self, letra=None):
        # Toca apenas wav, mas usa o próprio wxPython
        try:
            sound = wx.SoundFromData( open("audio/" + letra + ".wav", 'rb').read() )
            sound.Play(wx.SOUND_ASYNC)
            wx.YieldIfNeeded()
        except NotImplementedError, v:
            self.reportaErro(u'Recurso não implementado!')
        except IOError, v:
            self.reportaErro(u'Som não encontrado!')