diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/editor.py b/editor.py index 41fdd47..46b21be 100644 --- a/editor.py +++ b/editor.py @@ -71,34 +71,45 @@ save_bt.grid(column=0, row=0, sticky=(tk.W)) open_bt = ttk.Button(toolbar, text="Ouvrir") open_bt.grid(column=1, row=0, sticky=(tk.W)) +old_text = "" def diff(old, new): + if old == new: + return None index = 0 - line = 1 - char = 0 for i in range(min(len(old), len(new))): if old[i] != new[i]: return { "type": "replace", - "start": str(line)+"."+str(char), - "end": 0, + "start": "1.0+"+str(i)+"c", + "end": "1.0+"+str(i+abs(len(old) - len(new))-1)+"c", "text": new[i:i+abs(len(old)-len(new))] } - char += 1 - if old[i] == "\n": - line += 1 - char = 0 - return { - "type": "insert", - "start": "end", - "text": new[i:i+abs(len(old)-len(new))] - } + if len(old) > len(new): + return { + "type": "replace", + "start": "end-"+str(len(old)-len(new))+"c", + "end": "end", + "text": "" + } + else: + return { + "type": "insert", + "start": "end", + "text": new[len(old):] + } def on_area_input(event): + global old_text #print(area.get("1.0", "end")) print(event) #sock.send({"type":"insert", "start":"1.0", "text":area.get("1.0", "end")}, send_addr) - sock.send({"type":"replace", "start":"1.0", "end":"end", "text":area.get("1.0", "end")}, send_addr) + #sock.send({"type":"replace", "start":"1.0", "end":"end", "text":area.get("1.0", "end")}, send_addr) + d = diff(old_text, area.get("1.0","end")) + if d == None: + return + sock.send(d, send_addr) + old_text = area.get("1.0","end") #if event.keycode == 25: # area.mark_set("insert", "1.0") @@ -106,18 +117,23 @@ def on_area_input(event): area.bind("", on_area_input) area.bind("", on_area_input) +area.tag_configure("plop", background="#ffaaaa") + def on_request(r): - global waiting_for_text + global waiting_for_text, old_text print(r) c, a = r if c["type"] == "set": if waiting_for_text: area.replace("1.0", "end", c["text"]) waiting_for_text = False + old_text = area.get("1.0","end") elif c["type"] == "insert": - area.insert(c["start"], c["text"]) + area.insert(c["start"], c["text"], "plop") + old_text = area.get("1.0","end") elif c["type"] == "replace": - area.replace(c["start"], c["end"], c["text"]) + area.replace(c["start"], c["end"], c["text"], "plop") + old_text = area.get("1.0","end") elif c["type"] == "get": sock.send({"type":"set", "text":area.get("1.0", "end")}, send_addr) elif c["type"] == "create_line": diff --git a/tutorial.html b/tutorial.html index ff4b48e..8d7ba41 100644 --- a/tutorial.html +++ b/tutorial.html @@ -335,55 +335,66 @@ la même manière que ci-dessus.

print(area.get("1.0", "end")) # obtenir tout le texte
 print(area.get("2.0", "8.0")) # le texte de la ligne 2 à la ligne 8
 area.replace("1.0", "end", "le nouveau texte") # remplacer du texte
-area.insert("1.0", "le nouveau texte") # insérer du texte
+area.insert("1.0", "le nouveau texte") # insérer du texte +area.insert("1.0 +42 chars", "le nouveau texte") +area.insert("end -3 lines", "le nouveau texte") +

Pour mettre en forme certaines parties du texte, on peut utiliser des +tags :

+
area.tag_configure("fond_rouge", background="#ffaaaa")
+area.tag_configure("insistance", foreground="#008800", underline=True)
+
+area.insert("1.0", "ce texte sera sur fond rouge", "fond_rouge")
+text.tag_add("insistance", "1.3", "1.8")
+

Liste de tous +les styles possibles.

Barre de défilement

Certains widgets (Text) peuvent défiler avec la molette, mais pour afficher la barre de défilement il faut un widget supplémentaire.

-
scroll = ttk.Scrollbar(root, orient=tk.VERTICAL, command=mon_widget_qui_défile.yview)
-scroll.grid(column=1, row=0, sticky=(tk.N, tk.S, tk.E, tk.W))
-mon_widget_qui_défile.configure(yscrollcommand=scroll.set)
+
scroll = ttk.Scrollbar(root, orient=tk.VERTICAL, command=mon_widget_qui_défile.yview)
+scroll.grid(column=1, row=0, sticky=(tk.N, tk.S, tk.E, tk.W))
+mon_widget_qui_défile.configure(yscrollcommand=scroll.set)

Cadre

Un cadre qui peut avoir une bordure et contenir d’autres widgets.

-
frame = ttk.Frame(root, borderwidth=5, relief="ridge", width=200, height=100)
+
frame = ttk.Frame(root, borderwidth=5, relief="ridge", width=200, height=100)

Les options ne sont pas obligatoires.

Le cadre contient ses propres lignes et colonnes. Pour placer des widgets dedans, il suffit de remplacer root par frame en les créant.

Barre de menus

La barre de menus en haut de la fenêtre.

-
root.option_add('*tearOff', False)
-menubar = tk.Menu(root)
-root['menu'] = menubar
-
-menu_file = tk.Menu(menubar)
-menu_edit = tk.Menu(menubar)
-
-menubar.add_cascade(menu=menu_file, label='Fichier')
-menubar.add_cascade(menu=menu_edit, label='Édition')
-
-menu_file.add_command(label='Ouvrir', command=on_open)
+
root.option_add('*tearOff', False)
+menubar = tk.Menu(root)
+root['menu'] = menubar
+
+menu_file = tk.Menu(menubar)
+menu_edit = tk.Menu(menubar)
+
+menubar.add_cascade(menu=menu_file, label='Fichier')
+menubar.add_cascade(menu=menu_edit, label='Édition')
+
+menu_file.add_command(label='Ouvrir', command=on_open)

Canevas

Le canevas est une zone de dessin.

-
canvas = tk.Canvas(root, background='white')
+
canvas = tk.Canvas(root, background='white')

On peut y dessiner des formes :

-
canvas.create_line(x1, y1, x2, y2)
-canvas.create_line(x1, y1, x2, y2, fill="red", width=3, dash=6)
-canvas.create_rectangle(x1, y1, x2, y2, fill="red", outline="blue")
-canvas.create_oval(x1, y1, x2, y2, fill="red", outline="blue")
+
canvas.create_line(x1, y1, x2, y2)
+canvas.create_line(x1, y1, x2, y2, fill="red", width=3, dash=6)
+canvas.create_rectangle(x1, y1, x2, y2, fill="red", outline="blue")
+canvas.create_oval(x1, y1, x2, y2, fill="red", outline="blue")

Événements

Quand il se passe quelque chose sur un widget, un événement est généré. On peut écouter les événements de certains types, c’est-à-dire lancer une fonction quand l’action se produit.

Par exemple, on affiche des informations quand une touche du clavier est relâchée dans la zone de texte :

-
text = tk.Text(root)
-
-def onrelease(event):
-    print("On a frappé le clavier !")
-    print(event)
-
-area.bind("<KeyRelease>", onrelease)
+
text = tk.Text(root)
+
+def onrelease(event):
+    print("On a frappé le clavier !")
+    print(event)
+
+area.bind("<KeyRelease>", onrelease)

On peut aussi utiliser les infos contenues dans l’événement, par exemple event.keycode.

Liste des événements

@@ -429,23 +440,23 @@ droit enfoncé

Fichiers

Demander où enregistrer un fichier, quel fichier ouvrir, choisir un dossier.

-
from tkinter import filedialog
-
-filetypes = [
-    ("Texte", "*.txt"),
-    ("Image PNG", "*.png"),
-    ("Autre", "*.*")
-]
-chemin = tk.filedialog.asksaveasfilename(filetypes=filetypes)
-print(chemin)
+
from tkinter import filedialog
+
+filetypes = [
+    ("Texte", "*.txt"),
+    ("Image PNG", "*.png"),
+    ("Autre", "*.*")
+]
+chemin = tk.filedialog.asksaveasfilename(filetypes=filetypes)
+print(chemin)

On peut remplacer asksaveasfilename par askopenfilename ou askdirectory.

Couleur

Demander de choisir une couleur.

-
from tkinter import colorchooser
-
-color = colorchooser.askcolor(initialcolor='black')
-print(color)
+
from tkinter import colorchooser
+
+color = colorchooser.askcolor(initialcolor='black')
+print(color)

On peut aussi indiquer la couleur initiale avec sa notation hexadécimale "#000000".

diff --git a/tutorial.md b/tutorial.md index e640efb..ea1b65d 100644 --- a/tutorial.md +++ b/tutorial.md @@ -132,8 +132,22 @@ print(area.get("1.0", "end")) # obtenir tout le texte print(area.get("2.0", "8.0")) # le texte de la ligne 2 à la ligne 8 area.replace("1.0", "end", "le nouveau texte") # remplacer du texte area.insert("1.0", "le nouveau texte") # insérer du texte +area.insert("1.0 +42 chars", "le nouveau texte") +area.insert("end -3 lines", "le nouveau texte") ``` +Pour mettre en forme certaines parties du texte, on peut utiliser des tags : + +```python +area.tag_configure("fond_rouge", background="#ffaaaa") +area.tag_configure("insistance", foreground="#008800", underline=True) + +area.insert("1.0", "ce texte sera sur fond rouge", "fond_rouge") +text.tag_add("insistance", "1.3", "1.8") +``` + +[Liste de tous les styles possibles.](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M43) + ### Barre de défilement Certains widgets (`Text`) peuvent défiler avec la molette, mais pour afficher la barre de défilement il faut un widget supplémentaire. diff --git a/tutorial.pdf b/tutorial.pdf index 0d1e952..5e59ec1 100644 Binary files a/tutorial.pdf and b/tutorial.pdf differ