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

#Import des modules nécessaires

import os
import sys
import random
import time
from tkinter import *
import tkinter.font as tkFont
import math
import pickle
import pathlib
from tkinter import ttk as ttk
from tktooltip import ToolTip
from functools import partial


#Détermination du dossier utilisateur selon l'OS
def get_datadir() -> pathlib.Path:
    home = pathlib.Path.home()
    if sys.platform == "win32":
        return home / "AppData/Roaming"
    elif sys.platform == "linux":
        return home / ".local/share"
    elif sys.platform == "darwin":
        return home / "Library/Application Support"

#Déclaration du dossier utilisateur
my_datadir = get_datadir() / "tuxblocs"

#Test si le dossier existe
try:
    my_datadir.mkdir(parents=True)
except FileExistsError:
    pass


#Début des variables globales ----------------

#Détection des actions souris
DETECTION_CLIC_SUR_OBJET=0
DETECTION_MOLETTE_SUR_OBJET=0
multiplication=False

#Autres
#Permet l'éxécution de certaines fonctions
ok=True
#Définit si la ligne graduée existe
ligne_existe=0
#Permet la mise à jour du Canvas après un redimensionnement de la fenêtre
ok_maj=1

#Couleurs
couleur="#dfe5fe"
couleur_bouton="#b5c3fd"
couleur_rectangle="#fff"
couleur_bordure_rectangle="#2b65db"
couleur_bordure_rectangle_proche="red"
couleur_bordure_externe='#99afba'
couleur_deplacer='#daf7e2'
couleur_ajouter='#dea9ff'
couleur_decouper='#ecea25'
couleur_pin=0
magnetisme_sucettes=True


#Fractions
bordure=6
magnetisme=4*bordure
taille_police=14

#Listes
fractions=[]
objets_annulation=[]
actions_annulation=[]
#Fin des variables globales----------------

#Création de la fenêtre
fenetre = Tk()
fenetre.configure(background="#c0cdff")
fenetre.title("Fracatux")
fenetre.tk.call('source', 'assets/themes/breeze.tcl')
ttk.Style().theme_use('Breeze')
fenetre.rowconfigure(1,weight=1)
fenetre.columnconfigure(1,weight=1)

#Création des cadres
zone_haut=ttk.Frame(fenetre, height=100)
zone_bas=ttk.Frame(fenetre, height=100)
zone_gauche=ttk.Frame(fenetre, width=100)
zone_haut.grid(row=0,column=1, columnspan=2,sticky='nesw')
zone_haut.columnconfigure(5,weight=1)
fenetre.rowconfigure(0,minsize=100)
zone_gauche.grid(row=0,column=0, rowspan=3,sticky='n')
zone_bas.grid(row=2,column=1, sticky='nesw')
zone_princ=Canvas(fenetre, highlightthickness=0,background="#a1d6ee")
zone_princ.grid(row=1,column=1,sticky="nesw")
zone_gauche.columnconfigure(0,minsize=25)
zone_gauche.columnconfigure(1,minsize=25)
zone_gauche.columnconfigure(2,minsize=25)
zone_gauche.columnconfigure(3,minsize=25)

#Images
pix = PhotoImage(file="assets/images/pixel_transparent.png")
img_main = PhotoImage(file="assets/images/main.png")
img_decoupe_unitaire = PhotoImage(file="assets/images/decoupe_uitaire.png")
img_decoupe_denominateur = PhotoImage(file="assets/images/decoupe_denominateur.png")
img_decimale = PhotoImage(file="assets/images/decimale.png")
img_scientifique = PhotoImage(file="assets/images/scientifique.png")
img_pourcentage = PhotoImage(file="assets/images/pourcentage.png")
img_multiplier = PhotoImage(file="assets/images/multiplier.png")
img_fusion = PhotoImage(file="assets/images/fusion.png")
img_corbeille = PhotoImage(file="assets/images/corbeille.png")
img_minicorbeille = PhotoImage(file="assets/images/corbeille2.png")
img_quitter=PhotoImage(file="assets/images/quitter.png")
img_reduire=PhotoImage(file="assets/images/reduire.png")
img_logo=PhotoImage(file="assets/images/logo.png")
img_fond=PhotoImage(file="assets/images/grain.png")
img_pleinecran=PhotoImage(file="assets/images/pleinecran.png")
img_sortiepleinecran=PhotoImage(file="assets/images/sortiepleinecran.png")
img_aide=PhotoImage(file="assets/images/aide.png")
img_info=PhotoImage(file="assets/images/info.png")
img_options=PhotoImage(file="assets/images/options.png")
img_magnetisme=PhotoImage(file="assets/images/magnetisme_on.png")

img_pin=[]
for i in ('bleu','cyan','vert','jaune','orange','rouge','rose','noir'):
    img_pin.append(PhotoImage(file=f"assets/images/pin_{i}.png"))




#Fonction pour permettre à nouveau la mise à jour de la fenêtre après un temps donné
def unlock():
    global ok_maj
    ok_maj = 1

# Répétition d'une image de fond
def deco_fond():
    # Fond
    global fond
    larg_fond = img_fond.width()
    haut_fond = img_fond.height()
    nb_x = int(larg_canvas / larg_fond)
    nb_y = int(haut_canvas // haut_fond)
    y = 0
    for j in range(nb_y + 1):
        x = 0
        for i in range(nb_x + 1):
            fond = zone_princ.create_image(x, y, anchor=NW, image=img_fond,tags="fond")
            zone_princ.tag_lower("fond")
            x = x + larg_fond
        y = y + haut_fond


def annulation(event):
    message("annulation")
    if actions_annulation[-1]=="fusion":
        fusion(objets_annulation[-1])


#Mise à jour des éléments du Canvas si on redimensionne la fenêtre
def maj_canvas(mode):
    # Dimensions du canvas
    global larg_unite,larg_ligne,haut_unite,larg_canvas,haut_canvas,centre_canvasx,centre_canvasy,bboxcorbeille,corbeille,fond,ok_maj, ligne_reference, startx, starty, debut_ligne_reference, fin_ligne_reference, texte_ligne_reference
    if ok_maj==1:
        if mode=="maj":
            ok_maj=0
            #Permet de bloquer une nouvelle mise à jour trop rapide
        zone_princ.update()
        larg_canvas = zone_princ.winfo_width()
        haut_canvas = zone_princ.winfo_height()
        centre_canvasx = larg_canvas / 2
        centre_canvasy = haut_canvas / 2
        larg_unite = larg_ligne = larg_canvas - 100
        haut_unite = 100
        startx=centre_canvasx-larg_ligne/2
        starty=25
        if mode=="debut":
            deco_fond()
            ligne_reference = zone_princ.create_line(startx, starty, startx+larg_ligne, starty, arrow=BOTH, width=2)
            texte_ligne_reference = zone_princ.create_text(centre_canvasx,starty-10,text="une unité")
        else:
            zone_princ.delete(fond)
            deco_fond()
            if ligne_existe:
                ligne_graduee("maj")
                if len(zone_princ.find_withtag('fraction_ligne_1'))>0:
                    fraction_ligne_1=(zone_princ.find_withtag('fraction_ligne_1'))[0]
                    dx = zone_princ.coords(ligne)[0] - zone_princ.coords(fraction_ligne_1)[0] + bordure
                    dy = zone_princ.coords(ligne)[3] - zone_princ.coords(fraction_ligne_1)[3] - bordure // 2
                    zone_princ.move('groupe_ligne', dx, dy)
                for i in marqueurs:
                    posx=zone_princ.coords(ligne)[0]+larg_ligne*float(zone_princ.gettags(i)[-1])-30
                    posy=zone_princ.bbox(i)[1]
                    zone_princ.moveto(i,posx,posy)
            else:
                larg_rel.set("perso")
                redim_fractions(calc_nombre())
            zone_princ.coords(corbeille,centre_canvasx, haut_canvas - 38)
            bboxcorbeille = (zone_princ.bbox(corbeille))
        #Après 0.2 secondesl ,débloque la mise à jour du Canvas
        if mode=="maj":
            fenetre.after(200,unlock())

#Première configuration du Canvas
maj_canvas("debut")

# Variables de contrôle
copie=IntVar()
revenir=IntVar()
fullscreen=IntVar()
type_droite=StringVar()
grad_1=IntVar()
grad_2=IntVar()
grad_3=IntVar()
etiquettes_1=IntVar()
etiquettes_2=IntVar()
etiquette_fin=IntVar()
num=IntVar()
den=IntVar()
div=IntVar()
larg_rel=StringVar()
larg_unite_custom=IntVar()
transparence=IntVar()
couleurs=IntVar()
chiffres=IntVar()
outil=StringVar()
type_droite.set("decimale")
grad_1.set(1)
grad_2.set(1)
grad_3.set(1)
etiquettes_1.set(1)
etiquettes_2.set(1)
etiquette_fin.set(1)
num.set(1)
den.set(1)
div.set(12)
larg_rel.set("perso")
chiffres.set(False)
transparence.set(False)
couleurs.set(False)
outil.set("deplacer")
larg_unite_custom.set(10)
fullscreen.set(False)
revenir.set(True)
copie.set(False)
aideouverte=IntVar()
aproposouverte=IntVar()
aideouverte.set(False)
aproposouverte.set(False)

#Polices

police_fraction = tkFont.Font(family='Arial', size=16, weight='bold')
moyen = tkFont.Font(family='Arial', size=14)
gros = tkFont.Font(family='Arial', size=20, weight='bold')
tres_gros = tkFont.Font(family='Arial', size=30, weight='bold')

#Détection du magnétisme
def estproche(objet1,objet2):
    if objet1!=objet2:
        if zone_princ.coords(objet2)[2] - magnetisme < zone_princ.coords(objet1)[0] < zone_princ.coords(objet2)[2] + magnetisme and zone_princ.coords(objet2)[1]-magnetisme < zone_princ.coords(objet1)[1] < zone_princ.coords(objet2)[1] + magnetisme and 'droite' not in zone_princ.gettags(objet2):
            return "gauche"
        elif zone_princ.coords(objet2)[0]-magnetisme < zone_princ.coords(objet1)[2] < zone_princ.coords(objet2)[0] + magnetisme  and zone_princ.coords(objet2)[1]-magnetisme < zone_princ.coords(objet1)[1] < zone_princ.coords(objet2)[1] + magnetisme and 'gauche' not in zone_princ.gettags(objet2):
            return "droite"
        elif zone_princ.coords(objet2)[1] - magnetisme < zone_princ.coords(objet1)[3] < zone_princ.coords(objet2)[1] + magnetisme and zone_princ.coords(objet2)[0] - magnetisme < zone_princ.coords(objet1)[0] < zone_princ.coords(objet2)[0] + magnetisme:
            return "bas"
        elif zone_princ.coords(objet2)[3] - magnetisme < zone_princ.coords(objet1)[1] < zone_princ.coords(objet2)[3] + magnetisme and zone_princ.coords(objet2)[0] - magnetisme < zone_princ.coords(objet1)[0] < zone_princ.coords(objet2)[0] + magnetisme:
            return "haut"
        else:
            return False
    else:
        return False



#Détermination d'une couleur hexadécimale selon la valeur de la fraction
def couleurhex(objet):
    numerateur=int(zone_princ.gettags(objet)[1])
    denominateur = int(zone_princ.gettags(objet)[2])
    valeur=int((numerateur/denominateur)*255**3)
    hexa=str(hex(valeur))[2:]
    if len(hexa)<6:
        for j in range (6-len(hexa)):
            hexa=hexa+"0"
    if len(hexa)>6:
        hexa=hexa[(6-len(hexa)):]
    return f'#{hexa}'

def alea_x(largeur):
    if largeur>larg_canvas:
        return 50
    else:
        return random.randint(bordure, larg_canvas - int(largeur) - bordure)

#Calcul des dimensions des barres de fractions et de leurs éléments associés (chiffres, barre de fraction)
def dimensions(numerateur,denominateur,x0,y0):
    largeur = (larg_unite * numerateur / denominateur)
    x1 = x0 + largeur - bordure
    y1 = y0 + 100 - bordure
    coords_fractions=x0,y0,x1,y1
    milieu_fraction = ((coords_fractions[0] + coords_fractions[2]) / 2, (coords_fractions[1] + coords_fractions[3]) / 2)
    coords_texte=milieu_fraction[0],milieu_fraction[1]
    coords_bordure_fine=x0-bordure/2, y0-bordure/2, x1+(bordure/2)-1, y1+(bordure/2)-1
    return (largeur,coords_fractions,milieu_fraction,coords_texte,coords_bordure_fine)

def adapte_texte(objet):
    texte = zone_princ.find_withtag(f'texte_{objet}')[0]
    ax0,ay0,ax1,ay1=zone_princ.bbox(texte)
    bx0, by0, bx1, by1 = zone_princ.bbox(objet)
    if ax1-ax0>(bx1-bx0)-bordure:
        zone_princ.itemconfig(texte,font='Arial 10')
    else:
        zone_princ.itemconfig(texte,font='Arial 16')
    if "ecriture_frac" in zone_princ.gettags(objet) or "ecriture_fact" in zone_princ.gettags(objet):
        adapte_trait(objet)

def adapte_trait(objet):
    texte=zone_princ.find_withtag(f'texte_{objet}')[0]
    trait = zone_princ.find_withtag(f'trait_{objet}')[0]
    milieu_texte = (zone_princ.bbox(texte)[1] + zone_princ.bbox(texte)[3]) / 2
    x0,y0,x1,y1=zone_princ.bbox(texte)[0], milieu_texte, zone_princ.bbox(texte)[2], milieu_texte
    zone_princ.coords(trait,x0,y0,x1,y1)


#Création d'une fraction
def cree(numerateur,denominateur,x0,y0,mode):
    largeur=larg_unite*numerateur/denominateur
    #Si la fraction à créer n'est ni trop grande ni trop petite
    if bordure*2<largeur<larg_canvas:
        if mode=="cree":
            x0,y0=random.randint(bordure,int(larg_canvas)-int(larg_unite*numerateur/denominateur)-bordure),int(centre_canvasy)+random.randint(0,int(haut_canvas/2)-100)
        (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur,denominateur,x0,y0)
        if transparence.get():
            couleur_dyn=''
        else:
            couleur_dyn=couleur_rectangle
        if chiffres.get():
            texte_dyn=couleur_dyn
        else:
            texte_dyn='#000'
        fractions.append(zone_princ.create_rectangle(coords_fractions,width=bordure,outline=couleur_bordure_rectangle, fill=couleur_dyn,tags=("fraction",numerateur,denominateur,"objet","ecriture_frac")))
        if couleurs.get():
            zone_princ.itemconfigure(fractions[-1],outline=couleurhex(fractions[-1]))
        zone_princ.addtag_withtag(f"groupe_{fractions[-1]}",fractions[-1])
        texte=zone_princ.create_text(coords_texte,text=f"{numerateur}\n{denominateur}", font=police_fraction,fill=texte_dyn,tags=(f"groupe_{fractions[-1]}","texte_fraction",f"accessoires_{fractions[-1]}",f"texte_{fractions[-1]}","objet"),justify=CENTER)
        milieu_texte=((zone_princ.bbox(texte)[0]+zone_princ.bbox(texte)[2])/2,(zone_princ.bbox(texte)[1]+zone_princ.bbox(texte)[3])/2)
        zone_princ.create_line(zone_princ.bbox(texte)[0],milieu_texte[1],zone_princ.bbox(texte)[2],milieu_texte[1],width=2,fill=texte_dyn,tags=(f"groupe_{fractions[-1]}","texte_fraction",f"accessoires_{fractions[-1]}",f"trait_{fractions[-1]}","objet"))
        zone_princ.create_rectangle(coords_bordure_fine, width=1, outline=couleur_bordure_externe,tags=(f"groupe_{fractions[-1]}",f"accessoires_{fractions[-1]}",f"bordure_{fractions[-1]}","objet"))
        zone_princ.tag_lower(f"groupe_{fractions[-1]}",corbeille)
        adapte_texte(fractions[-1])
    else:
        if largeur>=larg_canvas:
            message("Fraction trop grande pour l'écran.\nRéduire d'abord la largeur relative des fractions.")
        if largeur<=bordure*2:
            message("Fraction trop petite pour l'écran.\nAugmenter d'abord la largeur relative des fractions\nou afficher une droite graduée adaptée..")

#Division de fractions en fractions unitaires 1/n, ou division par deux en multipliant le dénominateur.
def frac_unitaire(objetbouge,mode,diviseur):
    listegroupesobjetbouge= [x for x in zone_princ.gettags(objetbouge) if x.startswith('groupe_')]
    listetags=[]
    x0 = zone_princ.bbox(objetbouge)[0] + bordure / 2
    y0 = zone_princ.bbox(objetbouge)[1] + bordure / 2
    numerateur = int(zone_princ.gettags(objetbouge)[1])
    denominateur = int(zone_princ.gettags(objetbouge)[2])
    if mode=="frac_unitaire":
        nb_de_fractions_a_creer = numerateur
        nouveau_denominateur = denominateur
        nouveau_numerateur = 1
    elif mode=="frac_denominateur":
        nb_de_fractions_a_creer = diviseur
        nouveau_denominateur = denominateur * diviseur
        nouveau_numerateur = numerateur
    liste_objets_annulation=[]
    if (numerateur!=1 or mode=="frac_denominateur") and (not "dec" in zone_princ.gettags(objetbouge) and not "sci" in zone_princ.gettags(objetbouge)):
        if larg_unite * nouveau_numerateur / nouveau_denominateur >= 2*bordure:
            for i in range(nb_de_fractions_a_creer):
                cree(nouveau_numerateur, nouveau_denominateur, x0, y0,"auto")
                liste_objets_annulation.append(fractions[-1])
                if i==0:
                    for l in range(len(listegroupesobjetbouge)):
                        zone_princ.addtag_withtag(listegroupesobjetbouge[l], f"groupe_{fractions[-1]}")
                    if 'gauche' in zone_princ.gettags(objetbouge):
                        zone_princ.addtag_withtag('gauche', fractions[-1])
                        listevoisinsg = zone_princ.find_withtag(f'voisin_g_{objetbouge}')
                        voisingauche = listevoisinsg[0]
                        zone_princ.addtag_withtag(f'voisin_g_{fractions[-1]}',voisingauche)
                        zone_princ.addtag_withtag(f'voisin_d_{voisingauche}', fractions[-1])
                if i >= 1:
                    listetags = [x for x in zone_princ.gettags(fractions[-2]) if x.startswith('groupe_')]
                    for j in range(len(listetags)):
                        zone_princ.addtag_withtag(listetags[j], f"groupe_{fractions[-1]}")
                        zone_princ.addtag_withtag("gauche", f"groupe_{fractions[-1]}")
                    zone_princ.addtag_withtag(f'voisin_g_{fractions[-1]}', fractions[-2])
                    zone_princ.addtag_withtag(f'voisin_d_{fractions[-2]}', fractions[-1])
                if not i == nb_de_fractions_a_creer-1:
                    zone_princ.addtag_withtag('droite', fractions[-1])
                if 'droite' in zone_princ.gettags(objetbouge) and i==nb_de_fractions_a_creer-1:
                    listevoisinsd = zone_princ.find_withtag(f'voisin_d_{objetbouge}')
                    voisindroite = listevoisinsd[0]
                    listetags = [x for x in zone_princ.gettags(fractions[-1]) if x.startswith('groupe_')]
                    for k in range(len(listetags)):
                        zone_princ.addtag_withtag(listetags[k], f"groupe_{voisindroite}")
                    zone_princ.addtag_withtag('droite',fractions[-1])
                    zone_princ.addtag_withtag(f'voisin_d_{fractions[-1]}', voisindroite)
                    zone_princ.addtag_withtag(f'voisin_g_{voisindroite}', fractions[-1])
                x0 = x0 + (larg_unite * nouveau_numerateur / nouveau_denominateur)
            fractions.remove(objetbouge)
            zone_princ.delete(objetbouge)
            zone_princ.delete(f'accessoires_{objetbouge}')
            objets_annulation.append(liste_objets_annulation)
            if revenir.get():
                outil.set("deplacer")
        else:
            message("Impossible de séparer.\nFraction trop petite.\nAugmenter la largeur relative des fractions.")
    else:
        if "ecriture_dec" in zone_princ.gettags(objetbouge) or "ecriture_sci" in zone_princ.gettags(objetbouge):
            message("Convertir d'abord en écriture fractionnaire.")
        elif numerateur==1:
            message("Cette fraction a déjà 1 au numérateur.")


#Détermination d'un groupe de fractions de même dénominateur au survol de la souris
def liste_a_fusionner(objetbouge):
    liste_fusion = []
    if not "ecriture_dec" in zone_princ.gettags(objetbouge) and not "ecriture_sci" in zone_princ.gettags(objetbouge):
        liste_fusion.append(objetbouge)
        voising = objetbouge
        while 'droite' in zone_princ.gettags(voising) and (zone_princ.gettags(voising))[2] == (zone_princ.gettags(objetbouge))[2] and not "ecriture_dec" in zone_princ.gettags(voising) and not "ecriture_sci" in zone_princ.gettags(voising):
            voisind = zone_princ.find_withtag(f'voisin_d_{voising}')[0]
            if (zone_princ.gettags(voising))[2] == (zone_princ.gettags(voisind))[2] and not "ecriture_dec" in zone_princ.gettags(voisind) and not "ecriture_sci" in zone_princ.gettags(voisind) and not "ecriture_pourc" in zone_princ.gettags(voisind):
                liste_fusion.append(voisind)
            voising = voisind
        voisind = objetbouge
        while 'gauche' in zone_princ.gettags(voisind) and (zone_princ.gettags(voisind))[2] == (zone_princ.gettags(objetbouge))[2] and not "ecriture_dec" in zone_princ.gettags(voisind) and not "ecriture_sci" in zone_princ.gettags(voisind):
            voising = zone_princ.find_withtag(f'voisin_g_{voisind}')[0]
            if (zone_princ.gettags(voisind))[2] == (zone_princ.gettags(voising))[2] and not "ecriture_dec" in zone_princ.gettags(voising) and not "ecriture_sci" in zone_princ.gettags(voising) and not "ecriture_pourc" in zone_princ.gettags(voising):
                liste_fusion.insert(0,voising)
            voisind = voising
    return liste_fusion

#Addition de fractions de même dénominateur
def fusion(objetbouge):
    numerateur=0
    denominateur=int(zone_princ.gettags(objetbouge)[2])
    liste=liste_a_fusionner(objetbouge)
    if len(liste)>1:
        for i in liste:
            numerateur=numerateur+int(zone_princ.gettags(i)[1])
        x0 = zone_princ.bbox(liste[0])[0] + bordure / 2
        y0 = zone_princ.bbox(liste[0])[1] + bordure / 2
        cree(numerateur,denominateur,x0,y0,"auto")
        if 'gauche' in zone_princ.gettags(liste[0]):
            voising = zone_princ.find_withtag(f'voisin_g_{liste[0]}')[0]
            listetags = [x for x in zone_princ.gettags(voising) if x.startswith('groupe_')]
            for j in range(len(listetags)):
                zone_princ.addtag_withtag(listetags[j], f"groupe_{fractions[-1]}")
            zone_princ.addtag_withtag('gauche', fractions[-1])
            zone_princ.addtag_withtag('droite', voising)
            zone_princ.addtag_withtag(f'voisin_g_{fractions[-1]}', voising)
            zone_princ.addtag_withtag(f'voisin_d_{voising}', fractions[-1])
        if 'droite' in zone_princ.gettags(liste[-1]):
            voisind = zone_princ.find_withtag(f'voisin_d_{liste[-1]}')[0]
            listetags = [x for x in zone_princ.gettags(fractions[-1]) if x.startswith('groupe_')]
            for j in range(len(listetags)):
                zone_princ.addtag_withtag(listetags[j], f"groupe_{voisind}")
            zone_princ.addtag_withtag('gauche', voisind)
            zone_princ.addtag_withtag('droite', fractions[-1])
            zone_princ.addtag_withtag(f'voisin_g_{voisind}', fractions[-1])
            zone_princ.addtag_withtag(f'voisin_d_{fractions[-1]}', voisind)
        for i in liste_a_fusionner(objetbouge):
            fractions.remove(i)
            zone_princ.delete(i)
            zone_princ.delete(f'accessoires_{i}')
        if revenir.get():
            outil.set("deplacer")

def multiplication_fractions(objetbouge,objetamultiplier):
    tag_ancien_numerateur = zone_princ.gettags(objetbouge)[1]
    tag_ancien_denominateur = zone_princ.gettags(objetbouge)[2]

    numerateur=int(zone_princ.gettags(objetbouge)[1])*int(zone_princ.gettags(objetamultiplier)[1])
    denominateur=int(zone_princ.gettags(objetbouge)[2])*int(zone_princ.gettags(objetamultiplier)[2])
    x0 = zone_princ.bbox(objetbouge)[0] + bordure / 2
    y0 = zone_princ.bbox(objetbouge)[1] + bordure / 2
    (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur,denominateur, x0,y0)


    # Mise à jour des tags de la fraction
    # On supprime les tags correspondant aux anciens numérateur / dénominateur
    zone_princ.dtag(objetamultiplier, tag_ancien_numerateur)
    zone_princ.dtag(objetamultiplier, tag_ancien_denominateur)
    # On stocke temporairement les tags restants dans une liste.
    liste_tags = list(zone_princ.gettags(objetamultiplier))
    # On y ajoute les tags correspondant aux nouveaux numérateur / dénominateur
    liste_tags.insert(1, denominateur)
    liste_tags.insert(1, numerateur)
    # On remplace les tags de la fraction par ceux de la liste.
    zone_princ.itemconfigure(objetamultiplier, tags=liste_tags)
    fractions.remove(objetbouge)
    zone_princ.delete(f'groupe_{objetbouge}')
    redim_fractions(calc_nombre())
    # Changement du texte affiché
    if "ecriture_frac" in zone_princ.gettags(objetamultiplier):
        zone_princ.itemconfig(f'texte_{objetamultiplier}',text=f'{numerateur}\n{denominateur}')
    if "ecriture_dec" in zone_princ.gettags(objetamultiplier):
        ecriture(objetamultiplier,"decimale")
    if "ecriture_sci" in zone_princ.gettags(objetamultiplier):
        ecriture(objetamultiplier,"scientifique")
    if "ecriture_pourc" in zone_princ.gettags(objetamultiplier):
        ecriture(objetamultiplier,"pourcentage")
    adapte_trait(objetamultiplier)

#On clique
def clic(event):
    global DETECTION_CLIC_SUR_OBJET,objetbouge,diffx,diffy,X_new,Y_new
    # position du pointeur de la souris
    X = X_new = event.x
    Y = Y_new =event.y
    trouve = 0
    liste_bouge=[*zone_princ.find_withtag('fraction'),*marqueurs]
    if ligne_existe:
        liste_bouge.insert(0,fond_ligne)
        liste_bouge.append(marqueur)
    for i in (liste_bouge):
        # coordonnées du rectangle qui encadre l'objet
        [x1, y1, x2, y2] = zone_princ.bbox(i)
        if x1 < X < x2 and y1 < Y < y2 :
            objetbouge=i
            trouve=1
    if trouve==1:
        listetags=zone_princ.gettags(objetbouge)
        if outil.get()=="deplacer":
            DETECTION_CLIC_SUR_OBJET = 1
            # calcul de la position relative du pointeur au moment du clic
            diffx = X - x1
            diffy = Y - y1
            if objetbouge in marqueurs:
                #zone_princ.tag_raise(objetbouge)
                zone_princ.tag_lower(f"graduation1", corbeille)
            else:
                zone_princ.tag_lower(f"groupe_{objetbouge}",corbeille)
            if objetbouge in fractions:
                liste = [x for x in zone_princ.gettags(objetbouge) if x.startswith('groupe_') and not x.endswith(f'{objetbouge}')]
                for i in range(len(liste)):
                    zone_princ.dtag(f"groupe_{objetbouge}",liste[i])

                if 'gauche' in zone_princ.gettags(objetbouge):
                    voising = zone_princ.find_withtag(f'voisin_g_{objetbouge}')[0]
                    zone_princ.dtag(objetbouge, f'voisin_d_{voising}')
                    zone_princ.dtag(f'voisin_g_{objetbouge}', 'droite')
                    zone_princ.dtag(f'voisin_g_{objetbouge}', f'voisin_g_{objetbouge}')
                    zone_princ.dtag(objetbouge,'gauche')

        elif objetbouge in fractions:
            if copie.get():
                objetatraiter=duplicate(objetbouge,event,"auto")
            else:
                objetatraiter=objetbouge
            if outil.get() == "frac_unitaire":
                frac_unitaire(objetatraiter, "frac_unitaire",1)
            elif outil.get() == "frac_denominateur":
                frac_unitaire(objetatraiter, "frac_denominateur",2)
            elif outil.get()=="ajouter":
                fusion(objetatraiter)
            elif outil.get()=="decimale":
                if "ecriture_dec" in listetags:
                    ecriture(objetatraiter,"fractionnaire")
                else:
                    ecriture(objetatraiter, "decimale")
            elif outil.get()=="scientifique":
                if "ecriture_sci" in listetags:
                    ecriture(objetatraiter,"fractionnaire")
                else:
                    ecriture(objetatraiter, "scientifique")
            elif outil.get()=="pourcentage":
                if "ecriture_pourc" in listetags:
                    ecriture(objetatraiter,"fractionnaire")
                else:
                    ecriture(objetatraiter, "pourcentage")
            elif outil.get() == "multiplier":
                multiplier(objetatraiter)
#On déplace
def drag(event):
    global X_new,Y_new,proche,objetamultiplier,multiplication
    if DETECTION_CLIC_SUR_OBJET == 1:
        multiplication=False
        proche=0
        X_old=X_new
        Y_old=Y_new
        X_new = event.x
        Y_new = event.y
        if ligne_existe:
            if objetbouge==marqueur:
                cree_marqueur(event)
        # mise à jour de la position de l'objet et de tout son groupe
        if ligne_existe and objetbouge==fond_ligne:
            zone_princ.move(f"graduation", X_new - X_old, Y_new - Y_old)
            zone_princ.move(f"groupe_ligne", X_new - X_old, Y_new - Y_old)
        else:
            zone_princ.move(f"groupe_{objetbouge}",X_new-X_old,Y_new-Y_old)
        if objetbouge in zone_princ.find_overlapping(bboxcorbeille[0],bboxcorbeille[1],bboxcorbeille[2],bboxcorbeille[3]):
            for i in zone_princ.find_withtag(f"groupe_{objetbouge}"):
                if i in fractions:
                    zone_princ.itemconfigure(i,fill="red")
        elif objetbouge in fractions:
            for i in zone_princ.find_withtag(f"groupe_{objetbouge}"):
                if i in fractions:
                    if transparence.get() or 'multi' in zone_princ.gettags(objetbouge):
                        zone_princ.itemconfigure(i, fill='')
                    else:
                        zone_princ.itemconfigure(i, fill=couleur_deplacer)

            if 'multi' in zone_princ.gettags(objetbouge):
                trouve=0
                for i in fractions:
                    #if i in zone_princ.find_overlapping(*zone_princ.coords(objetbouge))and i!=objetbouge:
                    if i in zone_princ.find_overlapping(event.x,event.y,event.x,event.y) and i != objetbouge:
                        trouve=1
                        objetamultiplier=i
                        multiplication=True
                    if trouve==1:
                        numerateur=int(zone_princ.gettags(objetbouge)[1])*int(zone_princ.gettags(objetamultiplier)[1])
                        denominateur=int(zone_princ.gettags(objetbouge)[2])*int(zone_princ.gettags(objetamultiplier)[2])
                        x0, y0, x1, y1 = zone_princ.coords(objetbouge)
                        (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur, denominateur, x0, y0)
                        while largeur<2*bordure:
                            denominateur=denominateur-1
                            (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur, denominateur, x0, y0)
                        zone_princ.coords(objetbouge, coords_fractions)
                        zone_princ.coords(f"bordure_{objetbouge}", coords_bordure_fine)
                        zone_princ.coords(f"texte_{objetbouge}", coords_texte)
                        texte = f"texte_{objetbouge}"
                        milieu_texte = ((zone_princ.bbox(texte)[0] + zone_princ.bbox(texte)[2]) / 2,(zone_princ.bbox(texte)[1] + zone_princ.bbox(texte)[3]) / 2)
                        zone_princ.coords(f"trait_{objetbouge}", zone_princ.bbox(texte)[0], milieu_texte[1], zone_princ.bbox(texte)[2], milieu_texte[1])
                        zone_princ.coords(f"x_{objetbouge}",zone_princ.bbox(objetbouge)[0]+3*bordure,zone_princ.bbox(objetbouge)[1]+3*bordure)
                    else:
                        numerateur = int(zone_princ.gettags(objetbouge)[1])
                        denominateur = int(zone_princ.gettags(objetbouge)[2])
                        x0, y0, x1, y1 = zone_princ.coords(objetbouge)
                        (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur, denominateur, x0, y0)
                        while largeur < 2 * bordure:
                            denominateur = denominateur - 1
                            (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur, denominateur, x0, y0)
                        zone_princ.coords(objetbouge, coords_fractions)
                        zone_princ.coords(f"bordure_{objetbouge}", coords_bordure_fine)
                        zone_princ.coords(f"texte_{objetbouge}", coords_texte)
                        texte = f"texte_{objetbouge}"
                        milieu_texte = ((zone_princ.bbox(texte)[0] + zone_princ.bbox(texte)[2]) / 2, (zone_princ.bbox(texte)[1] + zone_princ.bbox(texte)[3]) / 2)
                        zone_princ.coords(f"trait_{objetbouge}", zone_princ.bbox(texte)[0], milieu_texte[1], zone_princ.bbox(texte)[2], milieu_texte[1])
                        zone_princ.coords(f"x_{objetbouge}", zone_princ.bbox(objetbouge)[0] + 3 * bordure, zone_princ.bbox(objetbouge)[1] + 3 * bordure)



#On relâche
def end(event):
    global DETECTION_CLIC_SUR_OBJET
    proche=0
    if DETECTION_CLIC_SUR_OBJET==1:
        if objetbouge in zone_princ.find_overlapping(bboxcorbeille[0], bboxcorbeille[1], bboxcorbeille[2], bboxcorbeille[3]):
            liste = (zone_princ.find_withtag(f"groupe_{objetbouge}"))
            for i in liste:
                if i in fractions:
                    fractions.remove(i)
                if i in marqueurs:
                    marqueurs.remove(i)
            zone_princ.delete(f"groupe_{objetbouge}")
        elif multiplication==True:
            multiplication_fractions(objetbouge,objetamultiplier)
        elif objetbouge in marqueurs and ligne_existe and magnetisme_sucettes:
            liste=zone_princ.find_withtag('ligne_grad')
            cordx=(zone_princ.bbox(objetbouge)[0]+zone_princ.bbox(objetbouge)[2])/2
            for i in liste:
                distance=abs(zone_princ.coords(i)[0]-cordx)
                if i==liste[0]:
                    gradmagn=i
                    petit = distance
                if distance<petit:
                    gradmagn=i
                    petit=distance
            zone_princ.moveto(objetbouge,zone_princ.coords(gradmagn)[0]-30,zone_princ.coords(gradmagn)[3]-60)
            ratio=((zone_princ.coords(gradmagn)[0]-zone_princ.coords(ligne)[0])-1)/larg_ligne
            zone_princ.addtag_withtag(ratio,objetbouge)
        elif objetbouge in fractions:
            for i in reversed(zone_princ.find_withtag('fraction')):
                    if zone_princ.coords(objetbouge)[0]<bordure:
                        for l in range(bordure-int(zone_princ.coords(objetbouge)[0])):
                            zone_princ.move(f'groupe_{objetbouge}',1,0)
                            zone_princ.update()
                            time.sleep(0.001)
                    if zone_princ.coords(objetbouge)[2]+bordure>larg_canvas:
                        for l in range(int(bordure + zone_princ.coords(objetbouge)[2]-larg_canvas)):
                            zone_princ.move(f'groupe_{objetbouge}',-1,0)
                            zone_princ.update()
                            time.sleep(0.001)
                    if zone_princ.coords(objetbouge)[1]<bordure:
                        for l in range(bordure-int(zone_princ.coords(objetbouge)[1])):
                            zone_princ.move(f'groupe_{objetbouge}',0,1)
                            zone_princ.update()
                            time.sleep(0.001)
                    if zone_princ.coords(objetbouge)[3]+bordure>haut_canvas:
                        for l in range(bordure+int(zone_princ.coords(objetbouge)[3]-haut_canvas)):
                            zone_princ.move(f'groupe_{objetbouge}',0,-1)
                            zone_princ.update()
                            time.sleep(0.001)
                    if estproche(objetbouge,i)=="gauche" and proche==0:
                        proche=1
                        dx=zone_princ.coords(i)[2]-zone_princ.coords(objetbouge)[0]+bordure
                        dy=zone_princ.coords(i)[1]-zone_princ.coords(objetbouge)[1]
                        zone_princ.move(f'groupe_{objetbouge}',dx,dy)
                        liste=[x for x in zone_princ.gettags(i) if x.startswith('groupe_')]
                        for j in range(len(liste)):
                            zone_princ.addtag_withtag(liste[j],f"groupe_{objetbouge}")
                        zone_princ.addtag_withtag('gauche',objetbouge)
                        zone_princ.addtag_withtag('droite', i)
                        zone_princ.addtag_withtag(f'voisin_g_{objetbouge}',i)
                        zone_princ.addtag_withtag(f'voisin_d_{i}', objetbouge)
                    elif estproche(objetbouge,i)=="droite" and proche==0:
                        proche = 1
                        dx = zone_princ.coords(i)[0] - zone_princ.coords(objetbouge)[2] - bordure
                        dy = zone_princ.coords(i)[1] - zone_princ.coords(objetbouge)[1]
                        zone_princ.move(f'groupe_{objetbouge}',dx,dy)
                        zone_princ.addtag_withtag(f'groupe_{objetbouge}',f'groupe_{i}' )
                        zone_princ.addtag_withtag('droite', objetbouge)
                        zone_princ.addtag_withtag('gauche', i)
                        zone_princ.addtag_withtag(f'voisin_d_{objetbouge}', i)
                        zone_princ.addtag_withtag(f'voisin_g_{i}', objetbouge)
                    elif estproche(objetbouge,i)=="bas":
                        proche = 1
                        dx = zone_princ.coords(i)[0] - zone_princ.coords(objetbouge)[0]
                        dy = zone_princ.coords(i)[1] - zone_princ.coords(objetbouge)[3] - bordure
                        zone_princ.move(f'groupe_{objetbouge}', dx, dy)
                    elif estproche(objetbouge,i)=="haut":
                        proche = 1
                        dx = zone_princ.coords(i)[0] - zone_princ.coords(objetbouge)[0]
                        dy = zone_princ.coords(i)[3] - zone_princ.coords(objetbouge)[1] + bordure
                        zone_princ.move(f'groupe_{objetbouge}', dx, dy)
            if proche==0:
                liste_groupe_actif = [x for x in zone_princ.find_withtag(f'groupe_{objetbouge}') if x in zone_princ.find_withtag('fraction')]
                for i in liste_groupe_actif:
                    for j in fractions:
                        if estproche(i,j)=="droite":
                            dx = zone_princ.coords(i)[2] - zone_princ.coords(j)[0] + bordure
                            dy = zone_princ.coords(i)[1] - zone_princ.coords(j)[1]
                            zone_princ.move(f'groupe_{j}', dx, dy)
                            liste = [x for x in zone_princ.gettags(i) if x.startswith('groupe_')]
                            for k in range(len(liste)):
                                zone_princ.addtag_withtag(liste[k], f"groupe_{j}")
                            zone_princ.addtag_withtag('gauche', j)
                            zone_princ.addtag_withtag('droite', i)
                            zone_princ.addtag_withtag(f'voisin_g_{j}', i)
                            zone_princ.addtag_withtag(f'voisin_d_{i}', j)
            coords=(zone_princ.bbox(objetbouge))
            if ligne_existe:
                if estproche(objetbouge,ligne)=="bas":
                    dx = zone_princ.coords(ligne)[0] - zone_princ.coords(objetbouge)[0] + bordure
                    dy = zone_princ.coords(ligne)[3] - zone_princ.coords(objetbouge)[3] - bordure//2
                    zone_princ.move(f'groupe_{objetbouge}', dx, dy)
                    zone_princ.addtag_withtag('groupe_ligne',f'groupe_{objetbouge}')
                    zone_princ.addtag_withtag('groupe_fond_ligne', f'groupe_{objetbouge}')
                    zone_princ.addtag_withtag('fraction_igne_1',objetbouge)

        DETECTION_CLIC_SUR_OBJET=0


def efface_message():
    global etiquette
    etiquette.place_forget()

def message(texte):
    global etiquette
    etiquette.configure(text=texte)
    etiquette.place(x=larg_canvas/2,y=haut_canvas/2,anchor=CENTER)
    zone_princ.after(2000,efface_message)


def decomposition(entier):
    if entier==1:
        return '1'
    else:
        liste = []
        for i in range(2,entier+1):
            while entier % i == 0:
                liste.append(str(i))
                entier = entier / i
        s=" x "
        return s.join(liste)


# Créé par cyril, le 22/04/2023 en Python 3.7
def ecriture_decimale(numerateur, denominateur):
    nombre = numerateur / denominateur
    exposant = 0
    if nombre < 1:
        while nombre < 1:
            nombre *= 10
            exposant -= 1
    else:
        while nombre >= 10:
            nombre /= 10
            exposant += 1

    valeur_attendue = nombre * 10 ** exposant
    valeur_resultat = round(numerateur / denominateur,3)
    valeur_tolerance = 10 ** (exposant-20) # Seuil de tolérance à 10^-20

    if -4 < exposant < 3:
        if abs(valeur_resultat - valeur_attendue) <= valeur_tolerance:
            return "{:.{prec}g}".format(valeur_resultat, prec=3).replace(".",",")
        else:
            return "≈ {:.{prec}g}".format(valeur_resultat, prec=3).replace(".",",")
    else:
        if abs(valeur_resultat - valeur_attendue) <= valeur_tolerance:
            return "{:.{prec}g}×10^{}".format(nombre, exposant, prec=3).replace(".",",")
        else:
            return "≈ {:.{prec}g}×10^{}".format(nombre, exposant, prec=3).replace(".",",")
def ecriture_pourcentage(numerateur, denominateur):
    nombre=(numerateur/denominateur)*100
    if nombre.is_integer():
        return (f'{int(nombre)} %')
    else:
        dec=2
        texte=format(nombre,f'.{2}f')
        if float(texte)==nombre:
            return (f'{texte} %').replace('.',',')
        else:
            while float(texte)!=nombre and dec<3:
                dec=dec+1
                texte = format(nombre, f'.{dec}f')
            return (f'≈ {texte} %').replace('.', ',')



# Créé par cyril, le 22/04/2023 en Python 3.7
def ecriture_scientifique(numerateur, denominateur):
    nombre = numerateur / denominateur
    exposant = 0
    if nombre < 1:
        while nombre < 1:
            nombre *= 10
            exposant -= 1
    else:
        while nombre >= 10:
            nombre /= 10
            exposant += 1

    nombre_arrondi = round(nombre, 2)
    valeur_attendue = nombre_arrondi * 10 ** exposant
    valeur_resultat = numerateur / denominateur
    valeur_tolerance = 10 ** (exposant-10) # Seuil de tolérance à 10^-10

    if exposant < 0:
        exp_str = '⁻' + ''.join(['⁰¹²³⁴⁵⁶⁷⁸⁹'[int(digit)] for digit in str(-exposant)])
    else:
        exp_str = ''.join(['⁰¹²³⁴⁵⁶⁷⁸⁹'[int(digit)] for digit in str(exposant)])

    if abs(valeur_resultat - valeur_attendue) <= valeur_tolerance:
        return "{:.{prec}g}×10 {}".format(nombre, exp_str, prec=3).replace(".",",")

    else:
        return "≈ {:.{prec}g}×10 {}".format(nombre, exp_str, prec=3).replace(".",",")


def ecriture(objetbouge,mode):
    numerateur=int(zone_princ.gettags(objetbouge)[1])
    denominateur=int(zone_princ.gettags(objetbouge)[2])
    if transparence.get():
        couleur_dyn = ''
    else:
        couleur_dyn = couleur_rectangle
    if chiffres.get():
        texte_dyn = couleur_dyn
    else:
        texte_dyn = '#000'
    listetags=[x for x in zone_princ.gettags(objetbouge) if x.startswith("ecriture_")]
    if mode=="decimale":
        if "ecriture_frac" in listetags or "ecriture_fact" in listetags:
            zone_princ.delete(f'trait_{objetbouge}')
        zone_princ.itemconfigure(f'texte_{objetbouge}', text=ecriture_decimale(numerateur, denominateur))
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_dec", objetbouge)
    elif mode=="scientifique":
        if "ecriture_frac" in listetags or "ecriture_fact" in listetags:
            zone_princ.delete(f'trait_{objetbouge}')
        zone_princ.itemconfigure(f'texte_{objetbouge}', text=ecriture_scientifique(numerateur, denominateur))
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_sci", objetbouge)
    elif mode=="pourcentage":
        if "ecriture_frac" in listetags or "ecriture_fact" in listetags:
            zone_princ.delete(f'trait_{objetbouge}')
        zone_princ.itemconfigure(f'texte_{objetbouge}', text=ecriture_pourcentage(numerateur, denominateur))
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_pourc", objetbouge)
    elif mode=="facteurs":
        if "ecriture_frac" not in listetags:
            ecriture(objetbouge,"fractionnaire")
            listetags = [x for x in zone_princ.gettags(objetbouge) if x.startswith("ecriture_")]
        zone_princ.itemconfigure(f'texte_{objetbouge}', text=f'{decomposition(numerateur)}\n{decomposition(denominateur)}')
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_fact", objetbouge)
        adapte_trait(objetbouge)
    elif mode=="fractionnaire":
        zone_princ.itemconfigure(f'texte_{objetbouge}', text=f"{numerateur}\n{denominateur}")
        texte = zone_princ.find_withtag(f'texte_{objetbouge}')[0]
        milieu_texte = ((zone_princ.bbox(texte)[0] + zone_princ.bbox(texte)[2]) / 2,(zone_princ.bbox(texte)[1] + zone_princ.bbox(texte)[3]) / 2)
        zone_princ.create_line(zone_princ.bbox(texte)[0], milieu_texte[1], zone_princ.bbox(texte)[2], milieu_texte[1], width=2, fill=texte_dyn, tags=(f"groupe_{objetbouge}", "texte_fraction", f"accessoires_{objetbouge}", f"trait_{objetbouge}","objet"))
        zone_princ.tag_lower(f"trait_{objetbouge}",corbeille)
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_frac", objetbouge)
        adapte_trait(objetbouge)
    elif mode=="masquer":
        if "ecriture_frac" in listetags or "ecriture_fact" in listetags:
            zone_princ.delete(f'trait_{objetbouge}')
        zone_princ.itemconfigure(f'texte_{objetbouge}', text='')
        for i in listetags:
            zone_princ.dtag(objetbouge,i)
        zone_princ.addtag_withtag("ecriture_mask", objetbouge)

    if revenir.get():
        outil.set("deplacer")


def multiplier(objet):
    x=zone_princ.bbox(objet)[0]+3*bordure
    y=zone_princ.bbox(objet)[1]+3*bordure
    zone_princ.create_text(x,y,text="X",fill='red',tags=(f"groupe_{objet}",f"accessoires_{objet}","objet",f"x_{objet}"))
    liste = [x for x in zone_princ.gettags(objet) if x.startswith('groupe_') and not x.endswith(f'{objet}')]
    for i in range(len(liste)):
        zone_princ.dtag(f"groupe_{objet}", liste[i])
    liste = [x for x in zone_princ.find_withtag(f'groupe_{objet}') if x in fractions and x!=objet]
    for i in range(len(liste)):
        zone_princ.dtag(f'groupe_{liste[i]}',f"groupe_{objet}")
    if 'gauche' in zone_princ.gettags(objet):
        voising = zone_princ.find_withtag(f'voisin_g_{objet}')[0]
        zone_princ.dtag(objet, f'voisin_d_{voising}')
        zone_princ.dtag(f'voisin_g_{objet}', 'droite')
        zone_princ.dtag(f'voisin_g_{objet}', f'voisin_g_{objet}')
        zone_princ.dtag(objet, 'gauche')
    if 'droite' in zone_princ.gettags(objet):
        voisind = zone_princ.find_withtag(f'voisin_d_{objet}')[0]
        zone_princ.dtag(objet, f'voisin_g_{voisind}')
        zone_princ.dtag(f'voisin_d_{objet}', 'gauche')
        zone_princ.dtag(f'voisin_d_{objet}', f'voisin_d_{objet}')
        zone_princ.dtag(objet, 'droite')
    zone_princ.itemconfigure(objet,fill='')
    zone_princ.addtag_withtag('multi',objet)
    zone_princ.itemconfigure(f'texte_{objet}',fill='red')
    zone_princ.itemconfigure(f'trait_{objet}', fill='red')
    message(f'Superposez cette fraction et une autre pour les multiplier\nentre elles.')
    if revenir.get():
        outil.set("deplacer")

def multiplier_par(objet,multiplicateur):
    numerateur = zone_princ.gettags(objet)[1]
    nouveau_numerateur = multiplicateur*int(numerateur)
    denominateur = int(zone_princ.gettags(objet)[2])
    # Mise à jour des tags de la fraction
    # On supprime les tags correspondant à l'ancien numérateur
    zone_princ.dtag(objet, numerateur)
    zone_princ.dtag(objet, denominateur)
    # On stocke temporairement les tags restants dans une liste.
    liste_tags = list(zone_princ.gettags(objet))
    # On y ajoute les tags correspondant au nouveau numérateur.
    liste_tags.insert(1, denominateur)
    liste_tags.insert(1, nouveau_numerateur)
    # On remplace les tags de la fraction par ceux de la liste.
    zone_princ.itemconfigure(objet, tags=liste_tags)
    redim_fractions(calc_nombre())
    # Changement du texte affiché
    if "ecriture_frac" in zone_princ.gettags(objet):
        zone_princ.itemconfig(f'texte_{objet}',text=f'{nouveau_numerateur}\n{denominateur}')
    if "ecriture_fact" in liste_tags:
        zone_princ.itemconfig(f'texte_{objet}', text=f'{decomposition(nouveau_numerateur)}\n{decomposition(denominateur)}')
    if "ecriture_dec" in zone_princ.gettags(objet):
        ecriture(objet,"decimale")
    if "ecriture_sci" in zone_princ.gettags(objet):
        ecriture(objet,"scientifique")
    if "ecriture_pourc" in zone_princ.gettags(objet):
        ecriture(objet,"pourcentage")
    adapte_trait(objet)

def cree_menu_contextuel():
    global menu_contextuel, menu_multiplier, menu_diviser
    menu_contextuel=Menu(zone_princ,tearoff=0)
    menu_contextuel.add_command(label="Dupliquer",command=lambda:duplicate(objet_clicdroit,donnees_souris,"manuel"))
    menu_contextuel.add_separator()
    menu_contextuel.add_command(label="Diviser en fractions unitaires",command=lambda:frac_unitaire(objet_clicdroit,"frac_unitaire",1))
    menu_diviser = Menu(menu_contextuel, tearoff=0)
    menu_contextuel.add_cascade(label="Diviser par ...", menu=menu_diviser)
    menu_diviser.add_command(label=2,command=lambda:frac_unitaire(objet_clicdroit,"frac_denominateur",2))
    menu_diviser.add_command(label=3, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 3))
    menu_diviser.add_command(label=4, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 4))
    menu_diviser.add_command(label=5, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 5))
    menu_diviser.add_command(label=6, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 6))
    menu_diviser.add_command(label=7, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 7))
    menu_diviser.add_command(label=8, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 8))
    menu_diviser.add_command(label=9, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 9))
    menu_diviser.add_command(label=10, command=lambda: frac_unitaire(objet_clicdroit, "frac_denominateur", 10))
    menu_contextuel.add_separator()
    menu_contextuel.add_command(label="Additioner des fractions de même dénominateur",command=lambda:fusion(objet_clicdroit))
    menu_contextuel.add_separator()
    menu_contextuel.add_command(label="Afficher l'écriture décimale",command=lambda:ecriture(objet_clicdroit,"decimale"))
    menu_contextuel.add_command(label="Afficher l'écriture scientifique",command=lambda:ecriture(objet_clicdroit,"scientifique"))
    menu_contextuel.add_command(label="Afficher l'écriture en pourcentage",command=lambda:ecriture(objet_clicdroit,"pourcentage"))
    menu_contextuel.add_command(label="Afficher l'écriture fractionnaire",command=lambda:ecriture(objet_clicdroit,"fractionnaire"))
    menu_contextuel.add_command(label="Décomposer en facteurs premiers",command=lambda:ecriture(objet_clicdroit,"facteurs"))
    menu_contextuel.add_command(label="Masquer l'écriture",command=lambda:ecriture(objet_clicdroit,"masquer"))
    menu_contextuel.add_separator()
    menu_contextuel.add_command(label="Multiplier par une autre fraction",command=lambda:multiplier(objet_clicdroit))
    menu_multiplier=Menu(menu_contextuel,tearoff=0)
    menu_contextuel.add_cascade(label="Multiplier par un entier...",menu=menu_multiplier)
    menu_multiplier.add_command(label=2,command=lambda:multiplier_par(objet_clicdroit,2))
    menu_multiplier.add_command(label=3,command=lambda:multiplier_par(objet_clicdroit,3))
    menu_multiplier.add_command(label=4, command=lambda: multiplier_par(objet_clicdroit, 4))
    menu_multiplier.add_command(label=5, command=lambda: multiplier_par(objet_clicdroit, 5))
    menu_multiplier.add_command(label=6, command=lambda: multiplier_par(objet_clicdroit, 6))
    menu_multiplier.add_command(label=7, command=lambda: multiplier_par(objet_clicdroit, 7))
    menu_multiplier.add_command(label=8, command=lambda: multiplier_par(objet_clicdroit, 8))
    menu_multiplier.add_command(label=9, command=lambda: multiplier_par(objet_clicdroit, 9))
    menu_multiplier.add_command(label=10, command=lambda: multiplier_par(objet_clicdroit, 10))

cree_menu_contextuel()


def aff_menu_contextuel(event):
    global objet_clicdroit,donnees_souris
    X = event.x
    Y = event.y
    donnees_souris=event
    trouve=0
    for i in fractions:
        # coordonnées du rectangle qui encadre l'objet
        [x1, y1, x2, y2] = zone_princ.bbox(i)
        if x1 < X < x2 and y1 < Y < y2:
            objet_clicdroit=i
            trouve=1
    if trouve==1:
        menu_contextuel.tk_popup(X+zone_princ.winfo_rootx(),Y+zone_princ.winfo_rooty())
        listetags=zone_princ.gettags(objet_clicdroit)
        for i in (0,2,3,5,7,8,9,10,11,12,14):
            menu_contextuel.entryconfigure(i, state=NORMAL)
        if listetags[1]=="1":
            menu_contextuel.entryconfigure(2, state=DISABLED)
        if len(liste_a_fusionner(objet_clicdroit))<2:
            menu_contextuel.entryconfigure(5, state=DISABLED)
        if "ecriture_dec" in listetags:
            menu_contextuel.entryconfigure(7, state=DISABLED)
        if "ecriture_sci" in listetags:
            menu_contextuel.entryconfigure(8, state=DISABLED)
        if "ecriture_pourc" in listetags:
            menu_contextuel.entryconfigure(9, state=DISABLED)
        if "ecriture_frac" in listetags:
            menu_contextuel.entryconfigure(10, state=DISABLED)
        if "ecriture_fact" in listetags:
            menu_contextuel.entryconfigure(11, state=DISABLED)
        if "ecriture_mask" in listetags:
            menu_contextuel.entryconfigure(12, state=DISABLED)

def duplicate(objet,event,mode):
    objet_a_dupliquer=objet
    listeobjets = [objet_a_dupliquer]
    listenouveauxobjets = []
    if 'droite' in zone_princ.gettags(objet_a_dupliquer):
        objet = objet_a_dupliquer
        while 'droite' in zone_princ.gettags(objet):
            nouvelobjet=zone_princ.find_withtag(f"voisin_d_{objet}")[0]
            listeobjets.append(nouvelobjet)
            objet=nouvelobjet
        tour=0

    for i in listeobjets:
        cree(int(zone_princ.gettags(i)[1]), int(zone_princ.gettags(i)[2]), zone_princ.bbox(i)[0] + 20,zone_princ.bbox(i)[1] + 20, "auto")
        if "ecriture_dec" in zone_princ.gettags(i):
            ecriture(fractions[-1],"decimale")
        if "ecriture_sci" in zone_princ.gettags(i):
            ecriture(fractions[-1],"scientifique")
        if "ecriture_pourc" in zone_princ.gettags(i):
            ecriture(fractions[-1],"pourcentage")
        listenouveauxobjets.append(fractions[-1])
        if len(listeobjets)>1:
            if tour>0:
                zone_princ.addtag_withtag('gauche',listenouveauxobjets[-1])
                zone_princ.addtag_withtag('droite',listenouveauxobjets[-2])
                zone_princ.addtag_withtag(f'voisin_d_{listenouveauxobjets[-2]}',listenouveauxobjets[-1])
                zone_princ.addtag_withtag(f'voisin_g_{listenouveauxobjets[-1]}', listenouveauxobjets[-2])
                for j in range (tour):
                    zone_princ.addtag_withtag(f'groupe_{listenouveauxobjets[j]}',f'groupe_{listenouveauxobjets[-1]}')
            tour=tour+1
    deplacement_souris(event)
    return listenouveauxobjets[0]
    if mode=="manuel" and revenir.get():
        outil.set("deplacer")


def trois_chiffres(nombre):
    test = nombre
    exp = 0
    while not 1 <= test < 10:
        if test >= 10:
            test = test / 10
            exp = exp + 1
        else:
            test = test * 10
            exp = exp - 1
    n0 = int(nombre * 10.0 ** (2 - exp))
    n1 = n0 // 100
    n2 = (n0 - n1 * 100) // 10
    n3 = (n0 - n1 * 100) % 10
    return n0,n1,n2,n3,exp

def deplacement_souris(event):
    objetacolorier=None
    for j in zone_princ.find_withtag("fraction"):
        if j in zone_princ.find_overlapping(event.x,event.y,event.x,event.y):
            objetacolorier=j
    if objetacolorier:
        if outil.get()=="deplacer":
            for i in fractions:
                if i in zone_princ.find_withtag(f'groupe_{objetacolorier}') and not 'multi' in zone_princ.gettags(i):
                    zone_princ.itemconfigure(i, fill=couleur_deplacer)
                else:
                    if transparence.get() or 'multi' in zone_princ.gettags(i):
                        zone_princ.itemconfigure(i, fill='')
                    else:
                        zone_princ.itemconfigure(i, fill=couleur_rectangle)
        elif outil.get() == "ajouter":
            for i in fractions:
                liste=liste_a_fusionner(objetacolorier)
                if i in liste and len(liste)>1:
                    zone_princ.itemconfigure(i, fill=couleur_ajouter)
                else:
                    if transparence.get():
                        zone_princ.itemconfigure(i, fill='')
                    else:
                        zone_princ.itemconfigure(i, fill=couleur_rectangle)
        elif outil.get()=="ecriture":
            for i in fractions:
                if i == objetacolorier:
                    zone_princ.itemconfigure(i, fill=couleur_deplacer)
                else:
                    if transparence.get():
                        zone_princ.itemconfigure(i, fill='')
                    else:
                        zone_princ.itemconfigure(i, fill=couleur_rectangle)
        else:
            for i in fractions:
                if i == objetacolorier and not 'multi' in zone_princ.gettags(i):
                    zone_princ.itemconfigure(i, fill=couleur_decouper)
                else:
                    if transparence.get() or 'multi' in zone_princ.gettags(i):
                        zone_princ.itemconfigure(i, fill='')
                    else:
                        zone_princ.itemconfigure(i, fill=couleur_rectangle)
    else:
        for i in fractions:
            if transparence.get() or 'multi' in zone_princ.gettags(i):
                zone_princ.itemconfigure(i, fill='')
            else:
                zone_princ.itemconfigure(i, fill=couleur_rectangle)
def calc_nombre():
    return nombre_droite.get().replace(',', '.')

def ligne_graduee(mode):
    global ligne, ligne_existe, larg_unite,fond_ligne,marqueur
    nombre = calc_nombre()
    if mode=="creer":
        bouton_droite.configure(state=DISABLED)
        bouton_suppr_droite.configure(state=NORMAL)
        taille_fractions_3.configure(state=DISABLED)
        taille_fractions_custom.configure(state=DISABLED)

        if larg_rel.get()=="perso":
            larg_rel.set("1")
        if float(nombre)>10:
            larg_rel.set("ligne")
            taille_fractions_1.configure(state=DISABLED)
            taille_fractions_3.configure(state=DISABLED)
        else:
            taille_fractions_1.configure(state=NORMAL)
    if nombre!=0:
        redim_fractions(nombre)
    if type_droite.get()=="decimale":
        nombre_division.configure(state=DISABLED)
        options_grad_2.configure(state=NORMAL)
        options_etiquettes_2.configure(state=NORMAL)
        options_etiquettes_3.configure(state=NORMAL)
    else:
        nombre_division.configure(state=NORMAL)
        options_grad_2.configure(state=DISABLED)
        options_etiquettes_2.configure(state=DISABLED)
        options_etiquettes_3.configure(state=DISABLED)

    if (mode=="maj" and ligne_existe) or mode=="creer":
        if ligne_existe:
            positionx=zone_princ.coords(ligne)[0]+1
            positiony=zone_princ.coords(ligne)[1]
            suppr_ligne_graduee("maj")
        else:
            positionx = centre_canvasx - larg_ligne / 2
            positiony = 200

        if type_droite.get() == "decimale":
                if nombre!='' and not float(nombre)<=0:
                    ligne_existe = True
                    nombre=float(nombre)
                    n0,n1,n2,n3,exp=trois_chiffres(nombre)

                    larg_grad = larg_ligne / n0
                    if n3 == 0 and n2 == 0:
                        last = 2
                    else:
                        last = 1
                    fond_ligne = zone_princ.create_rectangle(positionx - 30, positiony-150, positionx + larg_ligne + 30, positiony+50, fill="#dffefc", tags='graduation')
                    zone_princ.tag_raise(fond_ligne,fond)
                    marqueur=zone_princ.create_image(positionx, positiony-100,image=img_pin[couleur_pin],tags='graduation')
                    ligne = zone_princ.create_line(positionx - 1, positiony, positionx + larg_ligne + last, positiony, width=3, tags='graduation')
                    option_magnetisme_sucettes = zone_princ.create_image(positionx + 150, positiony - 120,
                                               image=img_magnetisme, tags='graduation')
                    zero = positionx
                    fin = larg_canvas - 50
                    x = zero
                    p=1-exp

                    for k in range((n0 // 100) + 1):
                        if grad_1.get():
                            graduation1 = zone_princ.create_line(x, positiony - 30, x, positiony, width=3, tags=('graduation','graduation1','ligne_grad'))
                        if k < (n1):
                            for j in range(10):
                                if grad_2.get():
                                    graduation2 = zone_princ.create_line(x, positiony - 20, x, positiony, tags=('graduation','graduation2','ligne_grad'))
                                if larg_grad >= 2.5 or j == 5 or j==0:
                                    n=k * 10**exp + j * 10**(exp-1)
                                    test=float(n).is_integer()
                                    if test:
                                        texte=int(n)
                                    else:
                                        texte=format(n,f'.{p}f')
                                        texte=texte.replace('.',',')
                                        if texte[-1] == '0':
                                            texte = texte[:-1]
                                    if (etiquettes_2.get() and not j==0) or (j == 0 and etiquettes_1.get()):
                                        if j==0:
                                            police='arial 14 bold'
                                        else:
                                            police="arial 10"
                                        etiquette2 = zone_princ.create_text(x, positiony + 20,font=police, text=texte,tags='graduation')
                                for i in range(10):
                                    if larg_grad >= 2 and grad_3.get():
                                        graduation3 = zone_princ.create_line(x, positiony - 10, x, positiony, fill="blue", tags=('graduation','graduation3','ligne_grad'))
                                    x = x + larg_grad
                    for j in range(((n0 - ((n0 // 100)) * 100) // 10) + 1):
                        if grad_2.get():
                            graduation2 = zone_princ.create_line(x, positiony - 20, x, positiony, tags=('graduation','graduation2','ligne_grad'))
                        if larg_grad >= 2.5 or j == 5 or j==0:
                            n = k * 10 ** exp + j * 10 ** (exp-1)
                            test = float(n).is_integer()
                            if test:
                                texte = int(n)
                            else:
                                texte = format(n,f'.{p}f')
                                texte = texte.replace('.', ',')
                                if texte[-1]=='0':
                                    texte=texte[:-1]
                            if (etiquettes_2.get() and not j==0) or (j == 0 and etiquettes_1.get()):
                                if j == 0:
                                    police = 'arial 14 bold'
                                else:
                                    police = "arial 10"
                                etiquette2 = zone_princ.create_text(x, positiony + 20, text=texte,font=police, tags='graduation')
                        if j < n2:
                            for i in range(10):
                                if larg_grad >= 2 and grad_3.get():
                                    graduation3 = zone_princ.create_line(x, positiony - 10, x, positiony, fill="blue", tags=('graduation','graduation3','ligne_grad'))
                                x = x + larg_grad
                    for i in range(n3 + 1):
                        if larg_grad >= 2 and grad_3.get():
                            graduation3 = zone_princ.create_line(x, positiony - 10, x, positiony, fill="blue",tags=('graduation','graduation3','ligne_grad'))
                        x = x + larg_grad
                        if i == n3 and not n3 == 0 and etiquette_fin.get()==1:
                            x = x - larg_grad
                            n = nombre
                            test = float(n).is_integer()
                            if test:
                                texte = int(n)
                            else:
                                texte = format(n, f'.{p+1}f')
                                texte = texte.replace('.', ',')
                            etiquette3 = zone_princ.create_text(x, positiony - 20, text=texte, tags='graduation')
                    if grad_1.get():
                        zone_princ.tag_lower('graduation2','graduation1')
                    if grad_2.get():
                        zone_princ.tag_lower('graduation3','graduation2')

        else:
            nombre_division.configure(state=NORMAL)
            options_grad_2.configure(state=DISABLED)
            ligne_existe = True
            nombre = int(nombre)
            decoupage = int(nombre_division.get())
            last = 2
            fond_ligne = zone_princ.create_rectangle(positionx - 30, positiony - 150,
                                                     positionx + larg_ligne + 30, positiony + 50,
                                                     fill="#dffefc", tags='graduation')
            zone_princ.tag_raise(fond_ligne, fond)
            ligne = zone_princ.create_line(positionx - 1, positiony,
                                           positionx + larg_ligne + last, positiony, width=3,
                                           tags='graduation')
            marqueur = zone_princ.create_image(positionx, positiony - 100,
                                               image=img_pin[couleur_pin], tags='graduation')
            option_magnetisme_sucettes = zone_princ.create_image(positionx + 150, positiony - 120,
                                               image=img_megnetisme, tags='graduation')
            zero = positionx
            fin = larg_canvas - 50
            x = zero
            larg_entier = larg_ligne / nombre
            for k in range(int(nombre) + 1):
                if grad_1.get():
                    graduation1 = zone_princ.create_line(x, positiony - 30, x, positiony, width=3, tags=('graduation','ligne_grad'))
                if etiquettes_1.get():
                    zone_princ.create_text(x,positiony+20,text=k,tags='graduation')
                x = x + larg_entier
            x = zero
            for k in range(decoupage * int(nombre)):
                if grad_2.get():
                    graduation2 = zone_princ.create_line(x, positiony - 20, x, positiony, width=1, tags=('graduation','ligne_grad'))
                    x = x + larg_entier / decoupage

def suppr_ligne_graduee(mode):
    global ligne, ligne_existe, couleur_pin
    if mode=="suppr":
        bouton_droite.configure(state=NORMAL)
        bouton_suppr_droite.configure(state=DISABLED)
        taille_fractions_3.configure(state=NORMAL)
        taille_fractions_custom.configure(state=NORMAL)
        larg_rel.set("perso")
        zone_princ.delete('marqueur')
        marqueurs.clear()
        redim_fractions(1)
        couleur_pin=0
    if ligne_existe:

        zone_princ.delete('graduation')
        ligne_existe = False

def move_ligne_graduee(dx,dy):
    zone_princ.move("graduation",dx,dy)


def check_entry(self):
    nombre = nombre_droite.get().replace(',', '.')
    try:
        float(nombre)
    except ValueError:
        nombre_droite.delete(0, END)
        nombre = nombre_droite.get()
    if not nombre=='':
        if float(nombre)>10:
            larg_rel.set("ligne")
            taille_fractions_1.configure(state=DISABLED)
            options_droite_3.configure(state=DISABLED)
            type_droite.set("decimale")
        else:
            options_droite_3.configure(state=NORMAL)
            taille_fractions_1.configure(state=NORMAL)
            if not ligne_existe:
                taille_fractions_3.configure(state=NORMAL)
        if float(nombre)!=0:
            ligne_graduee("maj")
#Spécial pour Windows
def molette_fraction_windows(event):
    if event.delta == 120:
        sens=0
    else:
        sens=1
    action_molette_fraction(sens,event.x,event.y)

def molette(sens):
    if sens==0 and larg_unite_custom.get()<100:
        larg_unite_custom.set(larg_unite_custom.get()+1)
    elif sens==1 and larg_unite_custom.get()>3:
        larg_unite_custom.set(larg_unite_custom.get() - 1)
    redim_fractions(1)

def molette_fraction_linux(event):
    if event.num == 4:
        sens = 0
    else:
        sens = 1
    action_molette_fraction(sens,event.x,event.y)

def molette_windows(event):
    if event.delta == 120:
        sens = 0
    else:
        sens = 1
    molette(sens)

def molette_linux(event):
    if event.num == 4:
        sens = 0
    else:
        sens = 1
    molette(sens)


def action_molette_fraction(sens,x,y):
    global DETECTION_MOLETTE_SUR_OBJET, objetbouge, objetx, objety, ok
    trouve = 0
    for i in fractions:
        # coordonnées du rectangle qui encadre l'objet
        [x1, y1, x2, y2] = zone_princ.bbox(i)
        if x1 < x < x2 and y1 < y < y2:
            DETECTION_MOLETTE_SUR_OBJET = 1
            objetbouge = i
            trouve = 1
            objetx = x1
            objety = y1
    if trouve == 1:
        # liste des fractions concernées

        # Si on veut que tout la molette agisse sur tout le groupe.
        # liste = zone_princ.find_withtag(f"groupe_{objetbouge}")

        # Si on veut que la molette n'agisse que sur la fraction survolée
        liste = [objetbouge]

        #On trie la liste des objets pour ne garder que les fractions sous forme de fractions et éliminer les accessoires (trait de fractions, texte ...)
        for i in [x for x in liste if x in fractions and ("ecriture_frac" in zone_princ.gettags(x) or "ecriture_fact" in zone_princ.gettags(x))]:
            # récupération du numérateur et du dénominateur
            numerateur=nouveau_numerateur=int(zone_princ.gettags(i)[1])
            denominateur=nouveau_denominateur=int(zone_princ.gettags(i)[2])
            if sens==0:
                # Calcul de la fraction égale la plus proche "vers le haut"
                #Le PGCD est j+1 (car on commence la boucle à 0)
                for j in range (numerateur):
                    if denominateur%(j+1)==0 and numerateur%(j+1)==0:
                        nouveau_denominateur = int(denominateur * (j+2) / (j+1) )
                        nouveau_numerateur = int(numerateur * (j+2) / (j+1) )
            else:
                # Calcul de la fraction égale la plus proche "vers le bas"
                # Le PGCD est j+1 (car on commence la boucle à 0)
                for j in range (numerateur):
                    if denominateur%(j+1)==0 and numerateur%(j+1)==0 and j>0:
                        nouveau_denominateur = int(denominateur * j / (j+1) )
                        nouveau_numerateur = int(numerateur * j / (j+1) )

            #Mise à jour des tags de la fraction
            #On supprime les tags correspondant aux anciens numérateur / dénominateur
            zone_princ.dtag(i,numerateur)
            zone_princ.dtag(i,denominateur)
            #On stocke temporairement les tags restants dans une liste.
            liste_tags=list(zone_princ.gettags(i))
            #On y ajoute les tags correspondant aux nouveaux numérateur / dénominateur
            liste_tags.insert(1,nouveau_denominateur)
            liste_tags.insert(1,nouveau_numerateur)
            #On remplace les tags de la fraction par ceux de la liste.
            zone_princ.itemconfigure(i,tags=liste_tags)
            # Changement du texte affiché
            if "ecriture_fact" in liste_tags:
                zone_princ.itemconfig(f'texte_{i}', text=f'{decomposition(numerateur)}\n{decomposition(denominateur)}')
            else:
                zone_princ.itemconfig(f'texte_{i}', text=f'{nouveau_numerateur}\n{nouveau_denominateur}')
            adapte_trait(i)

def check_fraction(variable):
    if variable==num and not numerateur_custom.get().isdigit():
        numerateur_custom.insert(0,1)
    if variable==den and not denominateur_custom.get().isdigit():
        denominateur_custom.insert(0, 1)
    if numerateur_custom.get().isdigit() and denominateur_custom.get().isdigit():
        bouton_custom.configure(state=NORMAL)

def check_entier(entree):
    if not entree.get().isdigit() or int(entree.get())==0:
        entree.delete(0,END)
    if not numerateur_custom.get().isdigit() or not denominateur_custom.get().isdigit():
        bouton_custom.configure(state=DISABLED)
    else:
        bouton_custom.configure(state=NORMAL)
#Zone gauche
def facteur(n):
    factor = 1
    while n >= 1:
        n /= 10
        factor *= 10
    return factor
def redim_fractions(nombre):
    global larg_unite
    suppr=0
    nombre=float(nombre)
    if larg_rel.get() == "1":
        larg_unite = larg_ligne // nombre
        larg_unite_custom.set(10*math.sqrt(larg_unite/larg_ligne))
    elif larg_rel.get() == "ligne":
        larg_unite = larg_ligne
        larg_unite_custom.set(10)
    elif larg_rel.get() == "perso":
        larg_unite=larg_ligne*((larg_unite_custom.get()/10)**2)
    for i in zone_princ.find_withtag('fraction'):
        numerateur = int(zone_princ.gettags(i)[1])
        denominateur = int(zone_princ.gettags(i)[2])
        x0 = zone_princ.coords(i)[0]
        y0 = zone_princ.coords(i)[1]
        (largeur, coords_fractions, milieu_fraction, coords_texte, coords_bordure_fine) = dimensions(numerateur,denominateur, x0,y0)
        zone_princ.coords(i, coords_fractions)
        zone_princ.coords(f"bordure_{i}", coords_bordure_fine)
        zone_princ.coords(f"texte_{i}", coords_texte)
        texte = f"texte_{i}"
        milieu_texte = ((zone_princ.bbox(texte)[0] + zone_princ.bbox(texte)[2]) / 2,(zone_princ.bbox(texte)[1] + zone_princ.bbox(texte)[3]) / 2)
        zone_princ.coords(f"trait_{i}", milieu_texte[0] - 15, milieu_texte[1], milieu_texte[0] + 15, milieu_texte[1])
        if 'droite' in zone_princ.gettags(i):
            voisin = zone_princ.find_withtag(f'voisin_d_{i}')[0]
            dx = zone_princ.coords(i)[2] - zone_princ.coords(voisin)[0] + bordure
            dy = zone_princ.coords(i)[1] - zone_princ.coords(voisin)[1]
            zone_princ.move(f'groupe_{voisin}', dx, dy)
        adapte_texte(i)
        if not 2 * bordure < largeur < larg_canvas:
            fractions.remove(i)
            zone_princ.delete(f'groupe_{i}')
            suppr=1
            message ("Des fractions trop petites ou trop grandes\npour être affichées ont été supprimées.")
    diviseur=facteur(larg_unite/larg_canvas)
    longueur=larg_unite/diviseur
    zone_princ.coords(ligne_reference,startx, starty, startx+longueur, starty)
    zone_princ.coords(texte_ligne_reference,startx+longueur/2,starty-10)
    if diviseur<=1:
        texte="une unité"
    elif diviseur==10:
        texte="un dixième"
    elif diviseur==100:
        texte="un centième"
    zone_princ.itemconfigure(texte_ligne_reference,text=texte)



def double_clic(event):
    # position du pointeur de la souris
    X = event.x
    Y = event.y
    trouve = 0
    for i in (zone_princ.find_withtag('fraction')):
        # coordonnées du rectangle qui encadre l'objet
        [x1, y1, x2, y2] = zone_princ.bbox(i)
        if x1 < X < x2 and y1 < Y < y2:
            objetbouge = i
            trouve = 1
    if trouve == 1:
        duplicate(objetbouge,event,"manuel")


def switch_pleinecran():
    global pleinecran
    if fullscreen.get():
        fenetre.attributes("-fullscreen", False)
        fullscreen.set(False)
        pleinecran.configure(image=img_pleinecran)
        quitter.grid_forget()
        minimiser.grid_forget()
        pleinecran.grid(row=0, column=7, rowspan=2, sticky=E)
    else:
        fenetre.attributes("-fullscreen", True)
        fullscreen.set(True)
        pleinecran.configure(image=img_sortiepleinecran)
        quitter.grid(row=0, column=7, sticky=E)
        minimiser.grid(row=0, column=6, sticky=E)
        pleinecran.grid(row=1, column=7, sticky=E)
    maj_canvas("maj")

def remplissage_fractions():
    if transparence.get():
        zone_princ.itemconfigure("fraction",fill='')
    else:
        zone_princ.itemconfigure("fraction", fill=couleur_rectangle)
    if couleurs.get():
        for i in fractions:
            zone_princ.itemconfigure(i, outline=couleurhex(i))
    else:
        zone_princ.itemconfigure("fraction", outline=couleur_bordure_rectangle)
    if chiffres.get():
        zone_princ.itemconfigure("texte_fraction",fill='')
    else:
        zone_princ.itemconfigure("texte_fraction", fill='#000')

def fermeture_generale():
    fenetre.destroy()

def annuler():
    boite.place_forget()


boite = Frame(fenetre,padx=20,pady=20,borderwidth=10, relief=RIDGE, background=couleur, highlightthickness=0)
confirmation = Label(boite, text="Quitter Fracatux ?", font=gros, background=couleur,pady=10)
confirmation_ok = Button(boite, text="oui", command=fermeture_generale, font=gros, pady=10, background=couleur_bouton)
confirmation_annuler = Button(boite, text="non", command=annuler, font=gros, pady=10, background=couleur_bouton)
logoquit=Label(boite,image=img_logo, pady=10)

def sauvegarde():
    # Enregistrement des variables dans le fichier
    sauv_variables = []
    fichierSauvegarde = open(f"{my_datadir}/parametres.txt", "wb")
    pickle.dump(sauv_variables, fichierSauvegarde)
    fichierSauvegarde.close()
    boite.place(x=fenetre.winfo_width()/2,y=fenetre.winfo_height()/2, anchor=CENTER)
    confirmation.grid(row=0,column=0,columnspan=2)
    confirmation_ok.grid(row=1,column=0)
    confirmation_annuler.grid(row=1,column=1)

def reset():
    zone_princ.delete("objet")
    fractions.clear()
    marqueurs.clear()
    suppr_ligne_graduee('suppr')
liste_boutons=[]
numerateur_general=1
denominateurs=(1,2,3,4,5,6,7,8,9,10,12,20,25,50,100,1000)
def change_boutons(n):
    global numerateur_general
    tour=0
    numerateur_general=numerateur_general+n
    for i in liste_boutons:
        i.config(text=f"{numerateur_general}\n{denominateurs[tour]}", command=partial(cree,numerateur_general,denominateurs[tour],alea_x(larg_unite*numerateur_general/denominateurs[tour]),centre_canvasy+random.randint(0,int(haut_canvas/2-100)),"cree"))
        tour=tour+1
    if numerateur_general==1:
        diminue_num.configure(state=DISABLED)
    else:
        diminue_num.configure(state=NORMAL)

diminue_num=Button(zone_gauche,width=2,font="Arial 10 bold",height=1,pady=1,text='-',command=lambda:change_boutons(-1))
augmente_num=Button(zone_gauche,width=2,font="Arial 10 bold",height=1,pady=1,text='+',command=lambda:change_boutons(1))
diminue_num.grid(row=1,column=0,columnspan=2,sticky="nesw")
augmente_num.grid(row=1,column=2,columnspan=2,sticky="nesw")
diminue_num.configure(state=DISABLED)

def const_bouton(i):
    liste_boutons.append(Button(zone_gauche,width=2, font="Arial 10 bold",height=2,pady=1,text=f"{numerateur_general}\n{i}",underline=0, command=partial(cree,numerateur_general,i,alea_x(larg_unite/i),centre_canvasy+random.randint(0,int(haut_canvas/2-100)),"cree")))
    return liste_boutons[-1]
ligne=2
tour=1
for i in denominateurs:
    #pair
    if tour%2==0:
        colonne=2
    #impair
    else:
        colonne=0
        ligne=ligne+1
    const_bouton(i).grid(row=ligne, column=colonne, columnspan=2, sticky="nesw")
    tour=tour+1
#Fenêtre à propos
def apropos():
    if not aproposouverte.get():
        aproposouverte.set(True)
        fen_apropos = Toplevel(fenetre)
        fen_apropos.title('À propos Fracatux')
        fen_apropos.configure(background=couleur, pady=50)
        if fullscreen.get():
            fen_apropos.attributes('-fullscreen',1)
            fen_apropos.columnconfigure(1, weight=1)
        global lock
        lock = 1

        def fermeture(event=None):
            global lock
            lock = 0
            fenetre.bind_all('<Escape>', lambda event: fenetre.destroy())
            fen_apropos.destroy()

        def libere(event=None):
            aproposouverte.set(False)

        logo = Label(fen_apropos, background=couleur, image=img_logo)
        logo.grid(row=0, column=0, sticky='nw')
        fen_apropos.bind_all('<Escape>', lambda event: fermeture())
        quitter = Button(fen_apropos, background=couleur, highlightthickness=0, image=img_quitter, relief="flat",
                         command=fermeture)
        quitter.grid(row=0, column=2, sticky='ne')
        titre_aide = Label(fen_apropos, background=couleur, text="À propos de Fracatux ...", font='Arial 20 bold', pady=20)
        titre_aide.grid(row=0, column=1, sticky='ew')
        barre = Scrollbar(fen_apropos, width=15)
        texte_apropos = Text(fen_apropos, height=30, width=100, background='#fff')
        texte_apropos.grid(row=1, column=1)
        barre.grid(row=1, column=2,sticky='ns')
        barre.config(command=texte_apropos.yview)
        texte_apropos.config(yscrollcommand=barre.set, wrap=WORD,tabs=('2c', '4.5c', 'right', '9c', 'center', '13c', 'numeric'), padx=20, pady=4)
        quote = """
    Fracatux est un logiciel libre qui permet de représenter les fractions sous fomes de barres et d'effectuer avec des opérations.
    
    Il ne s'agit pas d'un exerciseur autonome pour l'élève, mais d'un outil polyvalent de maniupulation d'objets pour l'enseignant(e). Les différents modes et options permettent d'adapter le comportement du logiciel selon le scénario de séance souhaité.
    
    Il est développé  par Arnaud Champollion et partagé sous licence libre GNU/GPL.
    
    Version 1.5.2
    
    Le code source est hébergé sur la forge des Communs Numériques : https://forge.apps.education.fr/
    
    Une forge est un outil facilitant l'édition et le suivi de projets collaboratifs. Il est possible depuis la page du projet de télécharger les versions éxécutables de Tuxblocs, mais également :
    - de consulter et télécharger le code source (la "recette" du logiciel).
    - de participer à son amélioration
    
    Il n'est pas nécessaire de savoir coder pour participer. Le développement d'un logiciel nécessite bien d'autres choses : relectures, traductions, documentation, tests, distribution, graphismes...
    
    Sur https://forge.apps.education.fr/ vous pouvez rédiger des "issues", ou "tickets" pour décrire des bugs rencontrés, ou bien encore des idées de nouvelles fonctionnalités.
    """
        texte_apropos.insert(END, quote)
        texte_apropos.config(state=DISABLED)
        fen_apropos.bind_all('<Destroy>',libere)
        fen_apropos.mainloop()



# Fenêtre d'aide
def aide():
    if not aideouverte.get():
        aideouverte.set(True)
        fen_aide = Toplevel(fenetre)
        fen_aide.title('Aide de Fracatux')
        fen_aide.configure(background=couleur,pady=50)
        if fullscreen.get():
            fen_aide.attributes('-fullscreen',1)
            fen_aide.columnconfigure(1, weight=1)
        global lock
        lock = 1
        def fermeture(event=None):
            global lock
            lock = 0
            fenetre.bind_all('<Escape>', lambda event: fenetre.destroy())
            fen_aide.destroy()
            aideouverte.set(False)

        def libere(event=None):
            aideouverte.set(False)

        logo = Label(fen_aide, background=couleur, image=img_logo)
        logo.grid(row=0, column=0, sticky='nw')
        fen_aide.bind_all('<Escape>', lambda event: fermeture())
        quitter = Button(fen_aide, background=couleur, highlightthickness=0, image=img_quitter, relief="flat",command=fermeture)
        quitter.grid(row=0, column=2, sticky='ne')
        titre_aide = Label(fen_aide, background=couleur, text="Manuel", font='Arial 20 bold',pady=20)
        titre_aide.grid(row=0, column=1, sticky='ew')
        barre = Scrollbar(fen_aide,width=15)
        texte_manuel = Text(fen_aide, height=30, width=100, background='#fff')
        texte_manuel.grid(row=1, column=1)
        barre.grid(row=1, column=2, sticky='ns')
        barre.config(command=texte_manuel.yview)
        texte_manuel.config(yscrollcommand=barre.set, wrap=WORD,
                            tabs=('2c', '4.5c', 'right', '9c', 'center', '13c', 'numeric'), padx=20, pady=4)
        quote = """Pour afficher rapidement cette aide, utilisez la touche F1 de votre clavier.
    
    Pour déplacer plusieurs fractions ensemble, il faut d'abord les grouper. Pour cela, il faut les positionner côte à côte en s'aidant du magnétisme.
    
    Lorsque des fractions sont groupées, on peut déplacer un groupe en déplaçant son membre le plus à gauche.
    
    Pour multiplier / diviser le numérateur et le dénominateur par un même facteur, utiliser la molette de la souris.
    
    Pour dupliquer une fraction ou un groupe de fractions, utiliser le bouton droit de la souris.
    """
        texte_manuel.insert(END, quote)
        texte_manuel.config(state=DISABLED)
        fen_aide.bind_all('<Escape>',partial(fermeture))
        fen_aide.bind_all('<Destroy>', partial(libere))
        fen_aide.mainloop()

marqueurs=[]
def cree_marqueur(event):
    global objetbouge, couleur_pin
    x=zone_princ.coords(marqueur)[0]
    y=zone_princ.coords(marqueur)[1]
    marqueurs.append(zone_princ.create_image(x,y,image=img_pin[couleur_pin],tags=('marqueur','objet','groupe_ligne')))
    zone_princ.addtag_withtag(f'groupe_{marqueurs[-1]}',marqueurs[-1])
    objetbouge=marqueurs[-1]
    if couleur_pin<7:
        couleur_pin=couleur_pin+1
    else:
        couleur_pin=0
    zone_princ.itemconfig(marqueur,image=img_pin[couleur_pin])

#Zone de gauche
custom=LabelFrame(zone_gauche,text="choix")
custom.grid(row=ligne+1,column=0,columnspan=4,pady=5,sticky=EW)
numerateur_custom=ttk.Spinbox(custom, from_=1, to=100,width=3,textvariable=num,justify=CENTER,font='arial 12',command=lambda:check_fraction(num))
trait_fraction=ttk.Separator(custom,orient=HORIZONTAL)
denominateur_custom=ttk.Spinbox(custom, from_=1, to=100,width=3,textvariable=den,justify=CENTER,font='arial 12',command=lambda:check_fraction(den))


numerateur_custom.grid(row=0,column=0,pady=5,padx=0,sticky="nsew")
trait_fraction.grid(row=1,column=0,padx=0,sticky="nsew")
denominateur_custom.grid(row=2,column=0,padx=0,pady=5,sticky="nsew")
bouton_custom=Button(custom,justify=CENTER,text="OK",command=lambda:cree(int(numerateur_custom.get()),int(denominateur_custom.get()),0,0,"cree"))
bouton_custom.grid(row=0,column=1,rowspan=3,padx=3,pady=5,sticky="nsew")

#Bouton aide / à propos
bouton_apropos=Button(zone_gauche, background=couleur_bouton,image=img_info, command=apropos)
bouton_apropos.grid(row=ligne+3, column=0,pady=4, columnspan=2)
bouton_aide=Button(zone_gauche, background=couleur_bouton,image=img_aide, command=aide)
bouton_aide.grid(row=ligne+3, column=2,pady=4, columnspan=2)

#Zones du haut
afficher_droite=LabelFrame(zone_haut,text="Droite graduée")
valeurs=LabelFrame(zone_haut,text="Valeurs")
type_de_droite=LabelFrame(zone_haut,text="Type de droite")
graduations=LabelFrame(zone_haut,text="Graduations")
etiquettes=LabelFrame(zone_haut,text="Étiquettes")
afficher_droite.grid(row=0,column=0,rowspan=2,padx=3,sticky=NS)
valeurs.grid(row=0,column=2,padx=3,rowspan=2,sticky=NS)
type_de_droite.grid(row=0,column=1,rowspan=2,padx=3,sticky=NS)
graduations.grid(row=0,column=3,rowspan=2,padx=3,sticky=NS)
etiquettes.grid(row=0,column=4,rowspan=2,padx=3,sticky=NS)

#Zones du bas
taille_fractions=LabelFrame(zone_bas,text="Largeur d'affichage des fractions")
taille_fractions.grid(row=0,column=0,padx=3,sticky=N)
apparence_fractions=LabelFrame(zone_bas,text="Apparence des fractions")
apparence_fractions.grid(row=0,column=1,padx=3,sticky=N)
outils=LabelFrame(zone_bas,text="Outils")
outils.grid(row=0,column=2,padx=3,pady=0,sticky=N)


#Entrées
div.set(12)
nombre_droite=ttk.Entry(valeurs,width=4,font='arial 12',justify=CENTER)
nombre_droite.insert(0,1)
nombre_droite.grid(row=0,column=1,pady=5,padx=5,sticky=W)
nombre_division=ttk.Spinbox(valeurs,width=4,from_=1,to=60,textvariable=div,font='arial 12',justify=CENTER,command=lambda:ligne_graduee("maj"))
nombre_division.grid(row=1,column=1,pady=5,padx=5)
nombre_division.configure(state=DISABLED)

#Boutons

texte_longueur=Label(valeurs,text="Longueur")
texte_longueur.grid(row=0,column=0,padx=5)
texte_division=Label(valeurs,text="Divisions")
texte_division.grid(row=1,column=0,padx=5)

bouton_droite=Button(afficher_droite,text="Créer",command=lambda:ligne_graduee("creer"))
bouton_droite.grid(row=0,column=0,sticky=NSEW)
bouton_suppr_droite=Button(afficher_droite,text="Supprimer",command=lambda:suppr_ligne_graduee("suppr"))
bouton_suppr_droite.configure(state=DISABLED)
bouton_suppr_droite.grid(row=1,column=0,sticky=NSEW)
options_droite_1=ttk.Radiobutton(type_de_droite,variable=type_droite,value="decimale",text="Décimale",command=lambda :ligne_graduee("maj"))
options_droite_1.grid(row=0,column=0,sticky="w",padx=5)
options_droite_3=ttk.Radiobutton(type_de_droite,variable=type_droite,value="fraction",text="Fractions d'unités (10 max.)",command=lambda :ligne_graduee("maj"))
options_droite_3.grid(row=2,column=0,sticky="w",padx=5)
options_grad_0=ttk.Checkbutton(graduations,variable=grad_1,onvalue=True,text="Afficher les graduations de niveau 1",command=lambda :ligne_graduee("maj"))
options_grad_1=ttk.Checkbutton(graduations,variable=grad_2,onvalue=True,text="Afficher les graduations de niveau 2",command=lambda :ligne_graduee("maj"))
options_grad_2=ttk.Checkbutton(graduations,variable=grad_3,onvalue=True,text="Afficher les graduations de niveau 3",command=lambda :ligne_graduee("maj"))
options_grad_0.grid(row=0,column=0,sticky="w",padx=5)
options_grad_1.grid(row=1,column=0,sticky="w",padx=5)
options_grad_2.grid(row=2,column=0,sticky="w",padx=5)
options_etiquettes_1=ttk.Checkbutton(etiquettes,variable=etiquettes_1,onvalue=True,text="Afficher les étiquettes de niveau 1",command=lambda :ligne_graduee("maj"))
options_etiquettes_2=ttk.Checkbutton(etiquettes,variable=etiquettes_2,onvalue=True,text="Afficher les étiquettes de niveau 2",command=lambda :ligne_graduee("maj"))
options_etiquettes_3=ttk.Checkbutton(etiquettes,variable=etiquette_fin,onvalue=True,text="Afficher l'étiquette finale",command=lambda :ligne_graduee("maj"))
options_etiquettes_1.grid(row=0,column=6,sticky="w",padx=5)
options_etiquettes_2.grid(row=1,column=6,sticky="w",padx=5)
options_etiquettes_3.grid(row=2,column=6,sticky="w",padx=5)

taille_fractions_1=ttk.Radiobutton(taille_fractions,variable=larg_rel,value="1",text="relative à l'unité (jusqu'à 10 unités)",command=lambda:redim_fractions(calc_nombre()))
taille_fractions_2=ttk.Radiobutton(taille_fractions,variable=larg_rel,value="ligne",text="relative à la ligne graduée",command=lambda:redim_fractions(calc_nombre()))
taille_fractions_3=ttk.Radiobutton(taille_fractions,variable=larg_rel,value="perso",text="personnalisée",command=lambda:redim_fractions(1))
taille_fractions_1.grid(row=0,column=0,columnspan=2,sticky="w",padx=5)
taille_fractions_2.grid(row=1,column=0,columnspan=2,sticky="w",padx=5)
taille_fractions_3.grid(row=2,column=0,sticky="w",padx=5)


apparence_fractions_1=ttk.Checkbutton(apparence_fractions,variable=transparence,text="Fond transparent",command=remplissage_fractions)
apparence_fractions_1.grid(row=0,column=0,columnspan=1,sticky="w",padx=5)
apparence_fractions_2=ttk.Checkbutton(apparence_fractions,variable=couleurs,text="Couleurs",command=remplissage_fractions)
apparence_fractions_2.grid(row=2,column=0,columnspan=1,sticky="w",padx=5)
apparence_fractions_3=ttk.Checkbutton(apparence_fractions,variable=chiffres,text="Masquer les chiffres",command=remplissage_fractions)
apparence_fractions_3.grid(row=3,column=0,columnspan=1,sticky="w",padx=5)

outils_1=ttk.Radiobutton(outils,variable=outil,value="deplacer",image=img_main)
outils_1.grid(row=0,column=0,rowspan=2,sticky="nswe")
outils_2=ttk.Radiobutton(outils,variable=outil,value="frac_unitaire",image=img_decoupe_unitaire)
outils_2.grid(row=0,column=1,rowspan=2,sticky="w")
outils_3=ttk.Radiobutton(outils,variable=outil,value="frac_denominateur",image=img_decoupe_denominateur)
outils_3.grid(row=0,column=2,rowspan=2,sticky="w")
outils_4=ttk.Radiobutton(outils,variable=outil,value="ajouter",image=img_fusion)
outils_4.grid(row=0,column=3,rowspan=2,sticky="w")
outils_5=ttk.Radiobutton(outils,variable=outil,value="decimale",image=img_decimale)
outils_5.grid(row=0,column=4,rowspan=2,sticky="w")
outils_8=ttk.Radiobutton(outils,variable=outil,value="scientifique",image=img_scientifique)
outils_8.grid(row=0,column=5,rowspan=2,sticky="w")
outils_6=ttk.Radiobutton(outils,variable=outil,value="pourcentage",image=img_pourcentage)
outils_6.grid(row=0,column=6,rowspan=2,sticky="w")
outils_7=ttk.Radiobutton(outils,variable=outil,value="multiplier",image=img_multiplier)
outils_7.grid(row=0,column=7,rowspan=2,sticky="w")
outils_corbeille=Button(zone_gauche,image=img_corbeille,command=reset)
outils_corbeille.grid(row=ligne+2,column=0,columnspan=4,sticky="nsew",padx=5)
outils_option_1=ttk.Checkbutton(outils,variable=revenir,text='Revenir au mode "déplacer" après chaque action')
outils_option_1.grid(row=2,column=0,columnspan=4,sticky=W)
outils_option_2=ttk.Checkbutton(outils,variable=copie,text='Dupliquer avant chaque action')
outils_option_2.grid(row=2,columnspan=3,column=4,sticky=W)
ToolTip(outils_1, msg="Déplacer les fractions", delay=0.5)
ToolTip(outils_2, msg="Diviser en fractions unitaires", delay=0.5)
ToolTip(outils_3, msg="Diviser par deux", delay=0.5)
ToolTip(outils_4, msg="Additionner des fractions de même dénominateur", delay=0.5)
ToolTip(outils_5, msg="Afficher l'écriture décimale", delay=0.5)
ToolTip(outils_6, msg="Afficher l'écriture en pourcentage", delay=0.5)
ToolTip(outils_7, msg="Multiplier la fraction par ...", delay=0.5)
ToolTip(outils_8, msg="Afficher l'écriture scientifique", delay=0.5)
ToolTip(outils_corbeille, msg="Supprimer toutes les fractions", delay=0.5)


quitter=Button(zone_haut,image=img_quitter, highlightthickness=0, highlightbackground='#fff',relief="flat",command=partial(sauvegarde))
minimiser=Button(zone_haut,image=img_reduire, highlightthickness=0, relief="flat",command=fenetre.iconify)
pleinecran=Button(zone_haut,image=img_pleinecran, highlightthickness=0, highlightbackground='#fff',relief="flat",command=switch_pleinecran)
pleinecran.grid(row=0,column=7,rowspan=2,sticky=E)







#Deco
zone_logo=Canvas(zone_gauche,highlightthickness=0,borderwidth=0,width=96,height=101)
zone_logo.grid(row=0,column=0,columnspan=4, sticky='sew')
fenetre.update()
logo=zone_logo.create_image(50.5,zone_logo.winfo_height(),anchor='s',image=img_logo)


zone_princ.update()
larg_canvas = zone_princ.winfo_width()
haut_canvas = zone_princ.winfo_height()
centre_canvasx = larg_canvas / 2
centre_canvasy = haut_canvas / 2
corbeille = zone_princ.create_image(centre_canvasx, haut_canvas - 38, image=img_minicorbeille)
bboxcorbeille = (zone_princ.bbox(corbeille))
texte="texte"
etiquette=Label(zone_princ,text=texte,font="Arial 16 bold",height=3, pady=10, padx=10, borderwidth=5, relief=GROOVE, background=couleur)


#Appuis claviers

fenetre.bind('<F1>',lambda event:aide())
fenetre.bind_all('<Escape>',lambda event:sauvegarde())
fenetre.bind_all('<F11>',lambda event:switch_pleinecran())
fenetre.protocol("WM_DELETE_WINDOW",partial(sauvegarde))

fenetre.bind_all('<Control-Z>',annulation)


nombre_droite.bind('<Return>',lambda event:ligne_graduee("maj"))
nombre_droite.bind('<KP_Enter>',lambda event:ligne_graduee("maj"))
nombre_droite.bind('<KeyRelease>',check_entry)
numerateur_custom.bind('<KeyRelease>',lambda event:check_entier(numerateur_custom))
denominateur_custom.bind('<KeyRelease>',lambda event:check_entier(denominateur_custom))
nombre_division.bind('<KeyRelease>',lambda event:check_entier(nombre_division))

numerateur_custom.bind('<Return>',lambda event:cree(int(numerateur_custom.get()),int(denominateur_custom.get()),random.randint(bordure,larg_canvas-int(larg_unite*int(numerateur_custom.get())/int(denominateur_custom.get()))-bordure),centre_canvasy+random.randint(0,haut_canvas/2-100),"cree"))
numerateur_custom.bind('<KP_Enter>',lambda event:cree(int(numerateur_custom.get()),int(denominateur_custom.get()),random.randint(bordure,larg_canvas-int(larg_unite*int(numerateur_custom.get())/int(denominateur_custom.get()))-bordure),centre_canvasy+random.randint(0,haut_canvas/2-100),"cree"))
denominateur_custom.bind('<Return>',lambda event:cree(int(numerateur_custom.get()),int(denominateur_custom.get()),random.randint(bordure,larg_canvas-int(larg_unite*int(numerateur_custom.get())/int(denominateur_custom.get()))-bordure),centre_canvasy+random.randint(0,haut_canvas/2-100),"cree"))
denominateur_custom.bind('<KP_Enter>',lambda event:cree(int(numerateur_custom.get()),int(denominateur_custom.get()),random.randint(bordure,larg_canvas-int(larg_unite*int(numerateur_custom.get())/int(denominateur_custom.get()))-bordure),centre_canvasy+random.randint(0,haut_canvas/2-100),"cree"))






#Événements souris
zone_princ.bind('<Button-1>',clic) # évévement clic gauche (press)
zone_princ.bind('<B1-Motion>',drag) # événement bouton gauche enfoncé (hold down)
zone_princ.bind('<ButtonRelease-1>',end) # événement bouton gauche relâché (hold down)
zone_princ.bind('<Button-3>',aff_menu_contextuel) # évévement clic gauche (press)
zone_princ.bind('<Button-4>',molette_fraction_linux)
zone_princ.bind('<Button-5>',molette_fraction_linux)
zone_princ.bind('<MouseWheel>',molette_fraction_windows)
zone_princ.bind('<Motion>',deplacement_souris)
zone_princ.bind('<Double-Button-1>',double_clic)






#Événements fenêtre
fenetre.bind('<Configure>',lambda event:maj_canvas("maj"))

if sys.platform == "linux":
    fenetre.attributes("-zoomed",1)
else:
    fenetre.state('zoomed')
taille_fractions_custom=ttk.Scale(taille_fractions,variable=larg_unite_custom,from_=3,to=100,length=250,orient='horizontal',command=lambda event:redim_fractions(0))
taille_fractions_custom.grid(row=3,column=0,sticky="w",padx=5)

taille_fractions_custom.bind('<Button-4>',molette_linux)
taille_fractions_custom.bind('<Button-5>',molette_linux)
taille_fractions_custom.bind('<MouseWheel>',molette_windows)

#Boucle principale
fenetre.mainloop()
