#!/usr/bin/python
# -*- coding: UTF-8 -*-


'''
    Programme tutoriel 6 sur l'utilisation de PyWx.
'''


#############################################################################
# Informations de versions
#############################################################################
__project__   = 'Formation Python'
__author__    = 'Simon CHOLLET (simon.chollet@ens.fr)'
__modifiers__ = ''
__date__      = '18/06/2013'
__version__   = '1.0'


#############################################################################
# Importations
#############################################################################
# Importation du module wx
import wx


#############################################################################
# Definitions specifiques
#############################################################################
# Taille pour la tache
TASK_RANGE = 100


#############################################################################
# Declaration des classes / fonctions
#############################################################################
class MyFrame(wx.Frame):
    '''
    Cette classe permet de creer une fenetre personnalisee.
    -------------------------------------------------------------------------
    Attributs : Aucun.
    '''
 
    def __init__(self, parent, title):
        '''
        Constructeur.
        ---------------------------------------------------------------------
        Arguments :
            - parent : Fenetre parente.
            - title  : Titre de la fenetre.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''

        # Appel de la classe mere
        super(MyFrame, self).__init__(parent, title=title, size=(350, 800))

        # Creation du panneau
        mainPanel = wx.Panel(self)

        # Couleur
        self.m_color = wx.Colour(0, 0, 0)

        # Police de caracteres
        font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)

        # Timer
        self.m_timer = wx.Timer(self, 1)
        self.m_count = 0

        # Creation de differents composants
        testStatic = wx.StaticText(
            mainPanel, label='Composants Standards', pos=(100, 10))
        testStatic.SetFont(font)

        wx.StaticLine(mainPanel, pos=(20, 30), size=(300, 2))

        # Boutons a 2 etats
        redBtn   = wx.ToggleButton(mainPanel, label='Rouge', pos=(20, 40))
        greenBtn = wx.ToggleButton(mainPanel, label='Vert',  pos=(20, 70))
        blueBtn  = wx.ToggleButton(mainPanel, label='Bleu',  pos=(20, 100))

        self.m_colorPanel = wx.Panel(
            mainPanel, pos=(150, 40), size=(110, 110))
        self.m_colorPanel.SetBackgroundColour(self.m_color)

        wx.StaticLine(mainPanel, pos=(20, 160), size=(300, 1))

        wx.StaticBox(
            mainPanel, label='Informations personelles',
            pos=(20, 170), size=(300, 100))
        wx.CheckBox(
            mainPanel, label='Monsieur', pos=(25, 190))
        wx.CheckBox(
            mainPanel, label='Madame', pos=(25, 210))
        wx.StaticText(
            mainPanel, label='Age :', pos=(25, 240))
        wx.SpinCtrl(
            mainPanel, value='1', pos=(55, 235), size=(60, -1),
            min=1, max=120)

        osList = ['Ubuntu', 'Windows', 'Dos', 'MacOS', 'Android']
        comboBox = wx.ComboBox(
            mainPanel, pos=(20, 280), choices=osList, style=wx.CB_READONLY)
        self.m_os = wx.StaticText(mainPanel, label='', pos=(220, 285))

        checkBox = wx.CheckBox(
            mainPanel, label='Montrer titre', pos=(20, 320))
        checkBox.SetValue(True)

        slider = wx.Slider(mainPanel, 5, 6, 1, 100, (20, 350), (110, -1))

        self.m_radioBtn1 = wx.RadioButton(
            mainPanel, label='Value A', pos=(20, 380), style=wx.RB_GROUP)
        self.m_radioBtn2 = wx.RadioButton(
            mainPanel, label='Value B', pos=(20, 400))
        self.m_radioBtn3 = wx.RadioButton(
            mainPanel, label='Value C', pos=(20, 420))
            
        self.m_gauge    = wx.Gauge(
            mainPanel, range=TASK_RANGE, pos=(20, 460), size=(250, 25))
        self.m_gaugeTxt = wx.StaticText(
            mainPanel, label='Tache terminee !', pos=(20, 490))
        self.m_startBtn = wx.Button(
            mainPanel, label='Start', pos=(20, 520))
        self.m_stopBtn  = wx.Button(
            mainPanel, label='Stop', pos=(120, 520))

        closeBtn = wx.Button(mainPanel, label='Fermer', pos=(235, 540))

        # Association des actions
        closeBtn.Bind(wx.EVT_BUTTON, self.OnClose)

        redBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleRed)
        greenBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleGreen)
        blueBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleBlue)

        comboBox.Bind(wx.EVT_COMBOBOX, self.OnSelect)

        checkBox.Bind(wx.EVT_CHECKBOX, self.ShowOrHideTitle)

        slider.Bind(wx.EVT_ENTER_WINDOW, self.OnSlider)
        
        self.m_radioBtn1.Bind(wx.EVT_RADIOBUTTON, self.OnRadio)
        self.m_radioBtn2.Bind(wx.EVT_RADIOBUTTON, self.OnRadio)
        self.m_radioBtn3.Bind(wx.EVT_RADIOBUTTON, self.OnRadio)

        self.Bind(wx.EVT_BUTTON, self.OnStart, self.m_startBtn)
        self.Bind(wx.EVT_BUTTON, self.OnStop,  self.m_stopBtn)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.m_timer)

        # Creation d'une barre de statut
        self.m_statusBar = self.CreateStatusBar(4)
        self.m_statusBar.SetStatusText("True", 1)
        self.m_statusBar.SetStatusText("False", 2)
        self.m_statusBar.SetStatusText("False", 3)

        # Positionne la fenetre
        self.Center()

        # Affichage de la fenetre
        self.Show()

    def OnClose(self, evt):
        '''
        Methode qui permet de fermer l'application.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Fermeture de la fenetre parente
        self.Close()

    def OnStart(self, evt):
        '''
        Methode appelee sur appui du bouton Start.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Selon la valeur du compteur
        if self.m_count >= TASK_RANGE:
            return
        self.m_timer.Start(100)
        self.m_gaugeTxt.SetLabel('Progression ...')

    def OnStop(self, evt):
        '''
        Methode appelee sur appui du bouton Stop.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Selon la valeur du compteur
        if self.m_count == 0 or self.m_count >= TASK_RANGE or not self.m_timer.IsRunning():
            return
        self.m_timer.Stop()
        self.m_gaugeTxt.SetLabel('Tache arretee !')

    def OnTimer(self, evt):
        '''
        Methode appelee sur timer.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Incrementation du compteur
        self.m_count = self.m_count + 1
        self.m_gauge.SetValue(self.m_count)
        if self.m_count == TASK_RANGE:
            self.m_timer.Stop()
            self.m_gaugeTxt.SetLabel('Tache terminee !')

    def OnRadio(self, evt):
        '''
        Methode appelee sur choix d'un bouton radio.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Recuperation des etats
        state1 = str(self.m_radioBtn1.GetValue())
        state2 = str(self.m_radioBtn2.GetValue())
        state3 = str(self.m_radioBtn3.GetValue())

        # Reglage du texte
        self.m_statusBar.SetStatusText(state1, 1)
        self.m_statusBar.SetStatusText(state2, 2)
        self.m_statusBar.SetStatusText(state3, 3)

    def OnSlider(self, evt):
        '''
        Methode appelee sur glissement du Slider.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Mise a jour de la barre de statut
        val = evt.GetEventObject()
        self.m_statusBar.SetStatusText('Slider = %d' % (val.GetValue()), 0)

    def ShowOrHideTitle(self, evt):
        '''
        Methode appelee sur coche ou non.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Recuperation du controle qui a agit
        sender = evt.GetEventObject()
        isChecked = sender.GetValue()
        if isChecked:
            self.SetTitle('code_wx_6.py')
        else:
            self.SetTitle('')

    def OnSelect(self, evt):
        '''
        Methode appelee sur selection dans la ComboBox.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Mise a jour du texte
        osTxt = evt.GetString()
        self.m_os.SetLabel(osTxt)

    def ToggleRed(self, evt):
        '''
        Methode qui permet de modifier la couleur en rouge.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Recuperation du composant
        obj = evt.GetEventObject()

        # Selon l'etat du bouton
        isPressed = obj.GetValue()
        green = self.m_color.Green()
        blue = self.m_color.Blue()
        if isPressed:
            self.m_color.Set(255, green, blue)
        else:
            self.m_color.Set(0, green, blue)

        # Modification de la couleur
        self.m_colorPanel.SetBackgroundColour(self.m_color)

    def ToggleGreen(self, evt):
        '''
        Methode qui permet de modifier la couleur en vert.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Recuperation du composant
        obj = evt.GetEventObject()

        # Selon l'etat du bouton
        isPressed = obj.GetValue()
        red = self.m_color.Red()
        blue = self.m_color.Blue()
        if isPressed:
            self.m_color.Set(red, 255, blue)
        else:
            self.m_color.Set(red, 0, blue)

        # Modification de la couleur
        self.m_colorPanel.SetBackgroundColour(self.m_color)

    def ToggleBlue(self, evt):
        '''
        Methode qui permet de modifier la couleur en bleu.
        ---------------------------------------------------------------------
        Arguments :
            - evt : Evennement.
        ---------------------------------------------------------------------
        Retour : Aucun.
        '''
        # Recuperation du composant
        obj = evt.GetEventObject()

        # Selon l'etat du bouton
        isPressed = obj.GetValue()
        red = self.m_color.Red()
        green = self.m_color.Green()
        if isPressed:
            self.m_color.Set(red, green, 255)
        else:
            self.m_color.Set(red, green, 0)

        # Modification de la couleur
        self.m_colorPanel.SetBackgroundColour(self.m_color)


#############################################################################
# Execution ...
#############################################################################


#
#
# Fonction appelee lors de la demande
# d'execution de la classe/module
if __name__ == "__main__":
    # Creation de l'application principale
    app = wx.App()

    # Creation de la fenetre avec des parametres
    MyFrame(None, title='code_wx_6.py')

    # Lance l'application
    app.MainLoop()

