#! /usr/bin/env python
# -*- coding:Utf-8 -*-

"""
Code des couleurs des résistances à 3 bandes.

fichier : code_couleurs.py
auteur : G. Swinnen (modifié Bob)
"""

# Import ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from math import log10               # logarithmes en base 10
import tkinter as tk

# Définition de classe ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Application:
    """Code des couleurs."""
    
    def __init__(self):
        """Constructeur de la fenêtre principale."""
        self.root = tk.Tk()  # fenêtre de base
        self.root.title('Code des couleurs')
        self.dessineResistance()
        tk.Label(self.root, text="Entrez la valeur de la résistance (ohms) :").\
                grid(row=2, column=1, columnspan=2)
        tk.Button(self.root, text ='Quitter', command=self.root.destroy).\
                grid(row=3, column=2)
        self.entree = tk.Entry(self.root, width=14)
        self.entree.grid(row=3, column=1)
        self.entree.focus()
        self.entree.bind('<Return>', self.changeCouleurs)
        # Code des couleurs pour les valeurs de zéro à neuf :
        self.cc = ['black','brown','red','orange','yellow',
                   'green','blue','purple','grey','white']

    def dessineResistance(self):
        """Canevas avec un modèle de résistance à trois lignes colorées."""
        self.can = tk.Canvas(self.root, width=250, height=100, bg ='light blue')
        self.can.grid(row=1, column=1, columnspan=3, pady=5, padx=5)
        self.can.create_line(10, 50, 240, 50, width=3)         # fils
        self.can.create_rectangle(65, 30, 185, 70, fill='beige', width=2)
        self.initCouleurs()

    def initCouleurs(self):
        """Trois lignes noires au départ."""
        self.ligne = []  # on mémorisera les trois lignes dans une liste
        for x in range(85, 150, 24):
            self.ligne.append(self.can.create_rectangle(x, 30, x+15, 70,
                                                        fill='black', width=0))

    def changeCouleurs(self, event):
        """Affichage des couleurs correspondant à la valeur entrée."""
        self.v1_ch = self.entree.get()       # cette méthode renvoie une chaîne
        err = False
        try:
            v = float(self.v1_ch)            # conversion en valeur numérique
        except ValueError:
            err = True                       # erreur : entrée non numérique
            
        if (err) or (v < 10.0) or (v > 1e11):
            self.signaleErreur()            # entrée incorrecte ou hors limites
        else:
            li = [0]*3                      # liste des 3 codes à afficher
            log_v = int(log10(v))           # partie entière du logarithme
            ord_gr = 10**log_v              # ordre de grandeur
            # On arrondit v à 2 chiffres significatifs
            # +0.5 pour arrondir correctement
            v = int(10 * v / ord_gr + 0.5) * ord_gr / 10
            # On recalcule log_v et ord_gr car v a changé
            log_v = int(log10(v))                    
            ord_gr = 10 ** log_v
            # On extrait le premier chiffre significatif :
            li[0] = int(v / ord_gr)            # partie entière
            decim = v / ord_gr - li[0]         # partie décimale
            # On extrait le deuxième chiffre significatif :
            # +0.5 pour arrondir correctement
            li[1] = int(decim * 10 + 0.5)
            # nombre de zéros à accoler aux 2 chiffres significatifs :
            li[2] = log_v - 1
            # Coloration des 3 lignes :
            for n in range(3):
                self.can.itemconfigure(self.ligne[n], fill=self.cc[li[n]])

    def signaleErreur(self):
        self.entree.configure(bg='red')            # colorer le fond du champ
        self.root.after(1000, self.videEntree)     # après 1 seconde, effacer

    def videEntree(self):
        self.entree.configure(bg='white')          # rétablir le fond blanc
        self.entree.delete(0, len(self.v1_ch))     # enlever les car. présents
        self.initCouleurs()                        # init 3 bandes noires

# Auto-test ====================================================================
if __name__ == '__main__':
    
    f = Application()  # instanciation de l'objet application
    f.root.mainloop()  # lancement de la boucle d'événements
