from tkinter import *
from tkinter.ttk import *
import tkinter.font as font
from tkinter.filedialog import *
from math import *
import PIL.Image as Image
import PIL.ImageTk as ImageTk
import PIL.ImageGrab as ImageGrab
from PIL import ImageTk, Image
from sys import argv
import os
import sys
import speech_recognition as sr
import pyttsx3
from win32 import win32api
from pyautogui import *
import gtts
from playsound import playsound

# GOTO
GotoTextBox = 0  # here , we have A vala option for text
GotoFont = 0  # here, we have , font style ,
GotoMenuFile = 0  # here we have Menu bars, File handling , aboutus
GotoTextEditor = 0  # here we have font styles , Italic, bold etc and design vala font , infact it is 3rd row
GotoItems = 0  # it contain , all the general items , pencil , rubber etc
GotoBrushes = 0  # it contain brushes
GotoColorBox = 0  # color box
GotoOutline = 0  # outline and fill option
GotoShapes = 0  # shapes
GotoMoreColors = 0

"""  Created By Ayush Bisht
    Date of completion :  10 june 2020

    """

def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

# Main window ............
win = Tk()
win.title("INDIpaint")
win.geometry("1000x600")
# ...............................

# Global variables ...............................................

outLinevar = 'black'
fillvar = ''
X, Y, z, sx, sy, cs, choosebox, zsize = 0, 0, 0, 0, 0, 1, 1, 0
dsp = [20, 30, 50, 60]
all_width = [1, 30, 30]
se = [0, 0, 0, 0]
dColor, Color1, Color2 = "#000000", "#000000", "#ffffff"
text = Text()
dataFromNotePad = ""
x0, y0, w, h = 0, 0, 0, 0
textIndex = -1
TextInPaint = ""
option = "paint"
CursorSet = "arrow"
# ......................................................................

# https://pythonexamples.org/python-tkinter-button-change-font/#:~:text=You%20can%20also%20change%20font,font%20size%20of%20tkinter%20button.

mfont = font.Font(size="15", family='Courier', weight='bold')

win['padx'] = 30
win["bg"] = "black"
win.columnconfigure(0, weight=200)
win.rowconfigure(0, weight=1)
win.rowconfigure(1, weight=0)
win.rowconfigure(2, weight=450)

optionLabel = LabelFrame(win, width='500', height='200', bg="white")
optionLabel.grid(row=0, sticky='nsew', padx=12, pady=2)

textLabel = LabelFrame(win, width='500', height=20, bg="white")
textLabel.grid(row=1, column=0, sticky='nsew', padx=10, pady=2)

contentLabel = Canvas(win, width="500", height="150", highlightthickness=1, highlightbackground="black",
                      background="white", cursor=CursorSet)
contentLabel.grid(row=2, column=0, sticky='news')

optionLabel.rowconfigure(0, weight=10)
optionLabel.columnconfigure(0, weight=30)
optionLabel.columnconfigure(1, weight=30)
optionLabel.columnconfigure(2, weight=30)
optionLabel.columnconfigure(3, weight=0)
optionLabel.columnconfigure(4, weight=0)
optionLabel.columnconfigure(5, weight=0)
optionLabel.columnconfigure(6, weight=20)
optionLabel.columnconfigure(7, weight=30)

items = LabelFrame(optionLabel, text='Tools', labelanchor='s', takefocus=True, fg="grey")
items.grid(row=0, column=0, sticky='nwes', pady=3, padx=1)
Brushes = LabelFrame(optionLabel, text='Brushes', labelanchor='s', takefocus=True, fg="grey")
Brushes.grid(row=0, column=1, sticky='nwes', padx=1, pady=3)
shapes = LabelFrame(optionLabel, text='Shapes', labelanchor='s', takefocus=True, fg="grey")
shapes.grid(row=0, column=2, sticky='nwes', padx=1, pady=3)
out_fill = LabelFrame(optionLabel, relief="flat")
out_fill.grid(row=0, column=3, sticky="nwes", padx=1, pady=3)
size = LabelFrame(optionLabel, text='Size', labelanchor='s', takefocus=True, fg="grey")
size.grid(row=0, column=4, sticky='nwes', padx=1, pady=3)
colorSelect = LabelFrame(optionLabel, takefocus=True, relief="flat", height=2)
colorSelect.grid(row=0, column=5, sticky='nwes', padx=1, pady=3)
colorbox = LabelFrame(optionLabel, text='colorbox', labelanchor='s', takefocus=True, fg="grey")
colorbox.grid(row=0, column=6, sticky='nwes', padx=1, pady=3)
editColor = LabelFrame(optionLabel, text="edit colors", labelanchor='s', takefocus=True, fg="grey")
editColor.grid(row=0, column=7, sticky='nwes', padx=1, pady=3)

GotoTextBox = 1

# Text Box ..................................................................................................................................

""" endCO is used to get  the last coordinate of the rectangle on which we are suppose to insert our text , it basically uses TEXT( )  widget to take the input which is passed off to create_text( )
so as to add text to canvas widget.

"""

def endCO(event):
    global se, x0, y0, w
    global t, text, dataFromNotePad, textInCanvas

    class Struct(object):
        pass

    data = Struct()
    data.win = win
    if se[0] < event.x:
        x0 = se[0]
    else:
        x0 = event.x
    if se[1] < event.y:
        y0 = se[1]
    else:
        y0 = event.y

    w, h = abs(event.x - se[0]), abs(event.y - se[1])
    text = Text(contentLabel, width=int(w / 11), height=int(h / 21))
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)
    t = contentLabel.create_window(x0, y0, window=text, anchor='nw')
    contentLabel.delete(textInCanvasIndexer)

"""
initialCO  is used to get the initial coordinate of that rectangle with whose reference we are suppose to add text in our canvas widget

"""
def initialCO(event):
    global se, t, textInCanvas, textInCanvasIndexer, textIndex
    if textIndex<1000:
        textIndex += 1
    textInCanvasIndexer = textInCanvas[textIndex]
    se[0], se[1] = event.x, event.y
    contentLabel.delete(t)

""" Here , that rectangle is created .
"""
def textShape(event):
    global se, k
    contentLabel.delete(k)
    k = contentLabel.create_rectangle(se[0], se[1], event.x, event.y, fill="white", outline="white")

""" here, it clarify wheather you complete you text or not, when completes TextInPaint become "" , and  text is added to  canvas widget

  """
def selector(s):
    global t, text, dataFromNotePad, textInCanvas, se, x0, y0, k, w, h, Color1, fontType, textInCanvasIndexer
    global TextInPaint
    TextInPaint = s
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    if TextInPaint == "text":
        contentLabel.bind("<ButtonRelease-1>", endCO)
        contentLabel.bind("<Button-1>", initialCO)
        contentLabel.bind("<B1-Motion>", textShape)
    else:
        dataFromNotePad = text.get(1.0, END)
        textInCanvasIndexer = contentLabel.create_text(x0, y0, text=dataFromNotePad, font=fontText, width=w,
                                                       anchor='nw', fill=Color1)
        contentLabel.delete(t)
        contentLabel.delete(k)

""" here , event is bind to mouse , so that when you press mouse right button then text is added to you canvas widget

"""
def TextChange(event):
    global TextInPaint, polyy1, polyx1, choosebox
    if z==4:
        selector("")
        TextInPaint = ""
        polyx1, polyy1 = 0, 0
        choosebox = 1

k = contentLabel.create_rectangle(0, 0, 0, 0)
textInCanvas = [contentLabel.create_text(0, 0)] * 1000
textInCanvasIndexer = textInCanvas[0]
t = contentLabel.create_window(0, 0)

# .................................................................................................................................................................

GotoFont = 1

# Font Size  and Style  ........................................................................

SizeVar = IntVar()
SizeVar.set(15)
fontFamilyVar = StringVar()
fontFamilyVar.set("Arial")

""" It set the font size for our text editor feature
"""

def getSizeofFont():
    SizeVar.set(textButtonS.get())
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)
    Notepad.configure(font=fontText, foreground=Color1)

""" It set the font family for our text editor feature

"""
def fontFamilyFun():
    global fontFamilyVar
    fontSt = vb.get()
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    fontFamilyVar.set(lis[fontSt])
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)
    Notepad.configure(font=fontText, foreground=Color1)
    fontFamily["font"] = (fontFamilyVar.get, 10)

# ............................................................................................

GotoMenuFile = 1
#  Menu Bar  and File Handling .............................................................................

Notepad = Text()
notepadWin = contentLabel.create_window(0, 0)
notePadData = StringVar()
FileSave = None
ScreenShotSave = None
imgt = [None] * 100
imageIndex = 0

""" paintfile :  This one is the main component of this program,  as it did all the stuffs like opeing new file , saving , printing etc
"""
def paintfile(s):
    global ScreenShotSave, imgCanvas, imgt, imageIndex,ir, ic, it, iet, irt, ih1, ih2
    xind = win.winfo_rootx() + contentLabel.winfo_x()
    yind = win.winfo_rooty() + contentLabel.winfo_y()
    xx = xind + contentLabel.winfo_width()
    yy = yind + contentLabel.winfo_height()
    if s == "save":
        if ScreenShotSave == None:
            ScreenShotSave = asksaveasfilename(initialfile='Untitled.png',
                                               defaultextension=".png",
                                               filetypes=[("All Files", "*.*"),
                                                          ("png", "*.png"), ("jpg", "*.jpg"), ("gif", "*.gif")])
            if ScreenShotSave == "":
                ScreenShotSave = None

        ImageGrab.grab(bbox=(xind, yind, xx, yy)).save(ScreenShotSave)

    elif s == "save_as":
        ScreenShotSave = asksaveasfilename(initialfile='Untitled.png',
                                           defaultextension=".png",
                                           filetypes=[("All Files", "*.*"),
                                                      ("png", "*.png"), ("jpg", "*.jpg"), ("gif", "*.gif")])

        ImageGrab.grab(bbox=(xind, yind, xx, yy)).save(ScreenShotSave)
    elif s == "new":
        ir, ic, it, iet, irt, ih1, ih2 = -1, -1, -1, -1, -1, -1, -1
        contentLabel.delete(ALL)
    elif s == "open":
        openImageFile = askopenfilename(defaultextension=".png",
                                        filetypes=[("All Files", "*.*"),
                                                   ("png", "*.png"), ("jpg", "*.jpg"), ("gif", "*.gif")])

        # PIL(python imaging library) is used to work 30 more image formats
        #  http://effbot.org/tkinterbook/photoimage.htm
        resource_path(openImageFile)
        imgResize = Image.open(openImageFile)
        imgResize = imgResize.resize((xx - xind, yy - yind), Image.ANTIALIAS)
        imgt[imageIndex] = ImageTk.PhotoImage(imgResize)
        contentLabel.create_image(0, 0, image=imgt[imageIndex], anchor=NW)
        imageIndex += 1
    elif s == "print":
        if ScreenShotSave != None:
            os.startfile(ScreenShotSave, "print")
    elif s == "exit":
        # t = askokcancel("Quit", "Do you really wish to quit?")

        win.destroy()
        # win.destroy()

def Choice(s):
    global notePadData, notepadWin, Notepad, FileSave, option

    class Struct(object):
        pass

    option = "text"
    Data = Struct()
    Data.win = win
    if s == "text":

        Notepad = Text(contentLabel, width=500, height=500)
        fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                             slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
        Notepad.configure(font=fontText, foreground=Color1)
        notepadWin = contentLabel.create_window(0, 0, window=Notepad, anchor='nw')

    elif s == "save":
        print(Notepad.index("insert"))
        if FileSave == None:
            FileSave = asksaveasfilename(initialfile='Untitled.txt',
                                         defaultextension=".txt",
                                         filetypes=[("All Files", "*.*"),
                                                    ("Text Documents", "*.txt")])
            if FileSave == "":
                FileSave = None
            else:
                file = open(FileSave, 'w')
                file.write(Notepad.get(1.0, END))
                file.close()
        else:
            file = open(FileSave, 'w')
            file.write(Notepad.get(1.0, END))
            file.close()
    elif s == "save_as":
        FileSave = asksaveasfilename(initialfile='Untitled.txt',
                                     defaultextension=".txt",
                                     filetypes=[("All Files", "*.*"),
                                                ("Text Documents", "*.txt")])
        if FileSave == "":
            FileSave = None
        else:
            file = open(FileSave, 'w')
            file.write(Notepad.get(1.0, END))
            file.close()
    elif s == "new":
        Notepad.delete(1.0, END)
    elif s == "print":
        if FileSave != None:
            os.startfile(FileSave, "print")
    elif s == "exit":
        option = "paint"
        contentLabel.delete(notepadWin)

def about_us():
    print("about us")
    about = Tk()
    about.title("ABOUT US")
    about.geometry("500x500")
    aboutText = Text(about, width=90, height=90, )

    aboutText.insert("end",
                     "\t\t\t About - Us \n\n\n Hello friends this is Ayush Bisht and I am a rising software engineer.Lets discuss few things about this application -- IndiPaint ,whch was"
                     " developed and designed under the guidance of expert seniors of BTKIT Dwarahat. This application  is an open source software , user can modified its code "
                     " according to their needs and desire. My main aim is  to implement our Knowledge and creates something new which could help ohters. Indipaint is an INDIAN software"
                     " and freely available to all. This project helps the students to learn Python Programming more precisely. This project gonna be a fun for the beginer who are neophyte in this"
                     " domain , they can easily learn all the major concept of GUI programmming and can create their own projects or their own self made software..."
                     "\n thank you all\n Project Manager \n Ayush Bisht \n............... Happy Coding ")

    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    aboutText.configure(font=fontText, foreground=Color1)
    aboutText.pack()
    about.mainloop()

menuBar = Menu(win)

file = Menu(menuBar, tearoff=0)
menuBar.add_cascade(label='File', menu=file)
file.add_command(label='New', command=lambda: paintfile("new"))
file.add_command(label='Open', command=lambda: paintfile("open"))
file.add_command(label='Save', command=lambda: paintfile("save"))
file.add_command(label='Save as', command=lambda: paintfile("save_as"))
file.add_command(label='Print', command=lambda: paintfile("print"))
file.add_command(label='About Us', command=lambda: about_us())
file.add_command(label='Exit', command=lambda: paintfile("exit"))

home = Menu(menuBar, tearoff=0)
menuBar.add_cascade(label='Home', menu=home)
home.add_command(label="NOTEPAD", command=lambda: Choice('text'))
home.add_command(label='New', command=lambda: Choice('new'))
home.add_command(label='Save', command=lambda: Choice('save'))
home.add_command(label='Save as', command=lambda: Choice('save_as'))
home.add_command(label='Print', command=lambda: Choice('print'))
home.add_command(label='PAINT', command=lambda: Choice('exit'))

# ...........................................................................................

GotoTextEditor = 1
# Text Editor ..........................................................................................................

ItalicVar = StringVar()
BoldVar = StringVar()
UnderVar = BooleanVar()
OverVar = BooleanVar()
ItalicVar.set("roman")
BoldVar.set("normal")
UnderVar.set(False)
OverVar.set(False)

def getTextStyle():
    if var1.get():
        ItalicVar.set("italic")
    else:
        ItalicVar.set("roman")
    if var2.get():
        BoldVar.set("bold")
    else:
        BoldVar.set("normal")

    if var3.get():
        UnderVar.set(True)
    else:
        UnderVar.set(False)

    if var4.get():
        OverVar.set(True)
    else:
        OverVar.set(False)
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)
    Notepad.configure(font=fontText, foreground=Color1)

textLabel.rowconfigure(0, weight=0)
textLabel.columnconfigure(0, weight=15)
textLabel.columnconfigure(1, weight=17)
textLabel.columnconfigure(2, weight=10)
textLabel.columnconfigure(3, weight=10)

fontFamilyFrame = LabelFrame(textLabel, height=1, foreground="white", background="black")
fontFamilyFrame.grid(row=0, column=0, sticky="news", padx=0)
fontFamily = Menubutton(fontFamilyFrame, textvariable=fontFamilyVar, anchor='n', font=(fontFamilyVar.get(), 10),
                        foreground="white", background="black")
fontFamily.menu5 = Menu(fontFamily, foreground="white", background="black")
fontFamily["menu"] = fontFamily.menu5
lis = list()
for fonter in font.families():
    lis.append(fonter)
vb = IntVar()
vb.set(990)
for i in range(0, len(lis)):
    fontFamily.menu5.add_radiobutton(label=lis[i], command=fontFamilyFun, variable=vb, value=i, background="black",
                                     foreground="white")

fontFamily.pack(expand=True, fill=BOTH)

var1, var2, var3, var4 = IntVar(), IntVar(), IntVar(), IntVar()
textStyle = LabelFrame(textLabel, width=10)
textStyle.grid(row=0, column=1, sticky="nws", padx=10)
textButtonI = Checkbutton(textStyle, text="I",
                          font=font.Font(family="stika heading", size=10, slant="italic", weight="bold"), relief="flat",
                          width=5, variable=var1, command=getTextStyle, indicatoron=0, foreground="white",
                          background="black", selectcolor=Color1)
textButtonI.pack(expand=True, fill=BOTH, side=LEFT, padx=10)

textButtonB = Checkbutton(textStyle, text="B", font=font.Font(family="stika heading", size=10, weight="bold"),
                          relief="flat", width=5, variable=var2, command=getTextStyle, indicatoron=0,
                          foreground="white", background="black", selectcolor=Color1)
textButtonB.pack(expand=True, side=LEFT, fill=BOTH, padx=10)

textButtonU = Checkbutton(textStyle, text="U",
                          font=font.Font(family="stika heading", size=10, weight="bold", underline=True), relief="flat",
                          width=5, variable=var3, command=getTextStyle, indicatoron=0, foreground="white",
                          background="black", selectcolor=Color1)
textButtonU.pack(expand=True, fill=BOTH, side=LEFT, padx=10)
textButtonO = Checkbutton(textStyle, text="abc",
                          font=font.Font(family="stika heading", size=10, weight="bold", overstrike=True),
                          relief="flat", width=5, variable=var4, command=getTextStyle, indicatoron=0,
                          foreground="white", background="black", selectcolor=Color1)
textButtonO.pack(expand=True, fill=BOTH, side=LEFT, padx=10)

textButtonS = Spinbox(textStyle, width=5, from_=1, to=100, command=getSizeofFont, foreground="white",
                      background="black", font=font.Font(family="stika heading", size=11, weight="bold"))
textButtonS.pack(expand=True, fill=BOTH, side=LEFT, padx=10)

designsImageList = ["Drectangle.png", "Dcircle.png", "Dtria.png", "Dtriangle.png", "Dheart.png", "Dstar.png"]

DesignList = [None] * 6
DesignImageList = [None] * 6
for i in range(0, 6):
    resource_path(".img\\"+designsImageList[i])
    DesignList[i] = Image.open(".img\\"+designsImageList[i])
    DesignList[i] = DesignList[i].resize((60, 60), Image.ANTIALIAS)
    DesignImageList[i] = ImageTk.PhotoImage(DesignList[i])

design = LabelFrame(textLabel, width=50, foreground="white", background="black")
design.grid(row=0, column=3, sticky='news')

design_menu = Menubutton(design, text="Designs", anchor='n', foreground="white", background="black")
design_menu.menu = Menu(design_menu, foreground="white", background="black")
design_menu["menu"] = design_menu.menu
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d1'), image=DesignImageList[0], background="black")
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d2'), image=DesignImageList[1], background="black")
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d3'), image=DesignImageList[2], background="black")
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d4'), image=DesignImageList[3], background="black")
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d5'), image=DesignImageList[4], background="black")
design_menu.menu.add_radiobutton(command=lambda: shapesChoose('d6'), image=DesignImageList[5], background="black")
design_menu.pack(expand=True, fill=BOTH)

# ....................................................................................................................

GotoItems = 1

# Items for Paint ...............................................

def paint(event):
    x2 = 0
    y2 = 0
    global X, Y, z, dColor, Color2, Color1, all_width, polyx1, polyy1, zindex, CursorSet
    polyx1, polyy1 = 0, 0
    if event.state == 1032:
        dColor = Color2
    else:
        dColor = Color1
    if X == 0 and Y == 0:
        x1, y1 = (event.x), (event.y)
        x2, y2 = (event.x + 1), (event.y + 1)
    else:
        x1, y1 = X, Y
        x2, y2 = (event.x), (event.y)
    X = x2
    Y = y2
    if z == 0:
        if all_width[z] <= 4:
            contentLabel.create_line(x1, y1, x2, y2, fill=dColor)
        else:
            contentLabel.create_rectangle(x1, y1, x2, y2, fill=dColor, width=all_width[zsize], outline=dColor)
    elif z == 1:
        contentLabel.create_oval(x1, y1, x2 - 0.5, y2 + 1, fill=dColor, outline=dColor, width=3)
    elif z == 2:
        contentLabel.create_rectangle(x1, y1, x2 - 1, y2 + 1, fill="white", outline="white", width=all_width[zsize])

def reset(event):
    global X, Y
    X = 0
    Y = 0

def items_f(p):
    global choosebox, polyx1, polyy1
    global z, TextInPaint
    if p == 4:
        TextInPaint = "text"
        selector("text")
        z=p
    else:
        TextInPaint = ""
        polyx1, polyy1 = 0, 0
        choosebox = 1
        z = p
        contentLabel.bind("<ButtonRelease-1>", reset)
        contentLabel.bind("<B1-Motion>", paint)
        contentLabel.bind("<ButtonRelease-3>", reset)
        contentLabel.bind("<B3-Motion>", paint)

items.rowconfigure(0, weight=1)
items.rowconfigure(1, weight=1)
items.columnconfigure(0, weight=1)
items.columnconfigure(1, weight=1)
items.columnconfigure(2, weight=1)

resource_path(".img\\pencil.png")
pencilIMG = Image.open(".img\\pencil.png")
pencilIMG = pencilIMG.resize((20, 20), Image.ANTIALIAS)
PencilImg = ImageTk.PhotoImage(pencilIMG)

resource_path(".img\\pen.png")
penIMG = Image.open(".img\\pen.png")
penIMG = penIMG.resize((20, 20), Image.ANTIALIAS)
PenImg = ImageTk.PhotoImage(penIMG)

resource_path(".img\\abc.png")
textIMG = Image.open(".img\\abc.png")
textIMG = textIMG.resize((20, 20), Image.ANTIALIAS)
TextImg = ImageTk.PhotoImage(textIMG)

resource_path(".img\\eraser.png")
eraserIMG = Image.open(".img\\eraser.png")
eraserIMG = eraserIMG.resize((20, 20), Image.ANTIALIAS)
EraserImg = ImageTk.PhotoImage(eraserIMG)

resource_path(".img\\fill.png")
fillIMG = Image.open(".img\\fill.png")
fillIMG = fillIMG.resize((20, 20), Image.ANTIALIAS)
FillImg = ImageTk.PhotoImage(fillIMG)

resource_path(".img\\search.png")
zoomIMG = Image.open(".img\\search.png")
zoomIMG = zoomIMG.resize((20, 20), Image.ANTIALIAS)
ZoomImg = ImageTk.PhotoImage(zoomIMG)

pencil = Button(items, command=lambda: items_f(0), width=35, image=PencilImg, compound=CENTER, relief="flat")
pencil.grid(row=0, column=0, )
pen = Button(items, command=lambda: items_f(1), width=35, image=PenImg, compound=CENTER, relief="flat")
pen.grid(row=0, column=1)
eraser = Button(items, command=lambda: items_f(2), width=35, image=EraserImg, compound=CENTER, relief="flat")
eraser.grid(row=1, column=0)
colorpicker = Button(items, command=lambda: items_f(3), width=35, image=FillImg, compound=CENTER, relief="flat")
colorpicker.grid(row=1, column=1)
TEXT = Button(items, command=lambda: items_f(4), width=35, image=TextImg, compound=CENTER, relief="flat")
TEXT.grid(row=0, column=2)
zoom = Button(items, command=lambda: items_f(5), width=35, image=ZoomImg, compound=CENTER, relief="flat")
zoom.grid(row=1, column=2)

GotoBrushes = 1
#  Brushes ..........................................................................................

brushType = 0

def paintBrush(event):
    global brushType, polyx1, polyy1, X, Y, fillvar,tcolor
    x, y = event.x, event.y
    polyx1, polyy1 = 0, 0
    tcolor = "black"
    if fillvar == '' and outLinevar == '':
        tcolor = "black"
    else:
        tcolor = fillvar

    if event.state == 1032:
        dColor = Color2
    else:
        dColor = Color1
    if X == 0 and Y == 0:
        x1, y1 = (event.x), (event.y)
        x2, y2 = (event.x + 1), (event.y + 1)
    else:
        x1, y1 = X, Y
        x2, y2 = (event.x), (event.y)
    X = x2
    Y = y2
    if brushType == 0:

        contentLabel.create_oval(x1, y1, x2 - 1, y2 + 1, fill=dColor, outline=dColor, width=all_width[zsize] + 10)
    elif brushType == 1:
        contentLabel.create_text(x, y, text=".", fill=dColor)
        contentLabel.create_text(x + 10, y + 10, text=".", fill=dColor)
        contentLabel.create_text(x + 10, y, text=".", fill=dColor)
        contentLabel.create_text(x, y + 10, text=".", fill=dColor)
        contentLabel.create_text(x - 10, y - 10, text=".", fill=dColor)
        contentLabel.create_text(x, y - 10, text=".", fill=dColor)
        contentLabel.create_text(x - 10, y, text=".", fill=dColor)
        contentLabel.create_text(x + 10, y - 10, text=".", fill=dColor)
        contentLabel.create_text(x - 10, y + 10, text=".", fill=dColor)
        contentLabel.create_text(x - 13, y, text=".", fill=dColor)
        contentLabel.create_text(x + 13, y - 14, text=".", fill=dColor)
        contentLabel.create_text(x - 16, y + 14, text=".", fill=dColor)
        contentLabel.create_text(x - 6, y, text=".", fill=dColor)
        contentLabel.create_text(x + 12, y - 10, text=".", fill=dColor)
        contentLabel.create_text(x - 4, y + 1, text=".", fill=dColor)
        contentLabel.create_text(x - 7, y + 5, text=".", fill=dColor)
        contentLabel.create_text(x + 1, y - 14, text=".", fill=dColor)
        contentLabel.create_text(x - 6, y + 14, text=".", fill=dColor)
        contentLabel.after(40)
    elif brushType == 2:
        contentLabel.create_rectangle(x1, y1, x2 - 1, y2 + 1, fill=dColor, outline=dColor, width=all_width[zsize] + 20)
    elif brushType == 3:
        contentLabel.create_rectangle(x1, y1, x2 - 1, y2 + 1, fill=Color1, outline=Color1, width=all_width[zsize])
        contentLabel.create_rectangle(x1, y1 + 2, x2 - 1, y2 + 3, fill=Color2, outline=Color2, width=all_width[zsize])
        contentLabel.create_rectangle(x1, y1 + 4, x2 - 1, y2 + 5, fill=Color1, outline=Color1, width=all_width[zsize])
        contentLabel.create_rectangle(x1, y1 + 6, x2 - 1, y2 + 7, fill=Color2, outline=Color2, width=all_width[zsize])
        contentLabel.create_rectangle(x1, y1 + 8, x2 - 1, y2 + 9, fill=Color1, outline=Color1, width=all_width[zsize])
        contentLabel.create_rectangle(x1, y1 + 10, x2 - 1, y2 + 11, fill=Color2, outline=Color2, width=all_width[zsize])

def brush_f(s):
    global brushType, TextInPaint
    TextInPaint = ""
    brushType = s
    contentLabel.bind("<ButtonRelease-1>", reset)
    contentLabel.bind("<B1-Motion>", paintBrush)
    contentLabel.bind("<ButtonRelease-3>", reset)
    contentLabel.bind("<B3-Motion>", paintBrush)

def size_f(c):
    global all_width, zsize
    all_width[zsize] = c

resource_path(".img\\brush.png")
MainIMG = Image.open(".img\\brush.png")
MainIMG = MainIMG.resize((50, 50), Image.ANTIALIAS)
MainImg = ImageTk.PhotoImage(MainIMG)

resource_path(".img\\brush1.png")
brush1IMG = Image.open(".img\\brush1.png")
brush1IMG = brush1IMG.resize((20, 20), Image.ANTIALIAS)
Brush1Img = ImageTk.PhotoImage(brush1IMG)

resource_path(".img\\brush2.png")
brush2IMG = Image.open(".img\\brush2.png")
brush2IMG = brush2IMG.resize((20, 20), Image.ANTIALIAS)
Brush2Img = ImageTk.PhotoImage(brush2IMG)

resource_path(".img\\brush3.png")
brush3IMG = Image.open(".img\\brush3.png")
brush3IMG = brush3IMG.resize((20, 20), Image.ANTIALIAS)
Brush3Img = ImageTk.PhotoImage(brush3IMG)

resource_path(".img\\brush4.png")
brush4IMG = Image.open(".img\\brush4.png")
brush4IMG = brush4IMG.resize((20, 20), Image.ANTIALIAS)
Brush4Img = ImageTk.PhotoImage(brush4IMG)

brush_menu = Menubutton(Brushes, anchor='n', image=MainImg, compound=CENTER)
brush_menu.menu = Menu(brush_menu)
brush_menu["menu"] = brush_menu.menu

brush_menu.menu.add_radiobutton(command=lambda: brush_f(0), background="white", image=Brush1Img, compound=LEFT,
                                label="Small")
brush_menu.menu.add_radiobutton(command=lambda: brush_f(2), background="white", image=Brush2Img, compound=LEFT,
                                label="Large")
brush_menu.menu.add_radiobutton(command=lambda: brush_f(1), background="white", image=Brush3Img, compound=LEFT,
                                label="Sprayer")
brush_menu.menu.add_radiobutton(command=lambda: brush_f(3), background="white", image=Brush4Img, compound=LEFT,
                                label="Roller")
brush_menu.pack()

resource_path(".img\\size.png")
sizeIMG = Image.open(".img\\size.png")
sizeIMG = sizeIMG.resize((45, 65), Image.ANTIALIAS)
SizeIMG = ImageTk.PhotoImage(sizeIMG)

size_menu = Menubutton(size, anchor='n', image=SizeIMG, compound=CENTER)
size_menu.menu = Menu(size_menu, foreground="white", background="black")
size_menu["menu"] = size_menu.menu
size_menu.menu.add_radiobutton(label="SIZE 1",
                               command=lambda: size_f(3), background="black", foreground="white",
                               font=font.Font(family="Sitka Heading", size=9))
size_menu.menu.add_radiobutton(label="SIZE 2",
                               command=lambda: size_f(15), background="black", foreground="white",
                               font=font.Font(family="Sitka Heading", size=9))
size_menu.menu.add_radiobutton(label="SIZE 3",
                               command=lambda: size_f(30), background="black", foreground="white",
                               font=font.Font(family="Sitka Heading", size=9))
size_menu.menu.add_radiobutton(label="SIZE 4",
                               command=lambda: size_f(40), font=font.Font(family="Sitka Heading", size=9),
                               background="black", foreground="white")
size_menu.pack()

# ..................................................................................................................................

GotoColorBox = 1

# Color BOX ..............................................................................

def setColor(colour):
    global Color1, Color2, cs, outLinevar, fillvar
    if cs == 1:
        Color1 = colour
        fillvar = Color1
    else:
        Color2 = colour
        outLinevar = Color2
    color1 = LabelFrame(colorSelect, text="Color 1", labelanchor='s', relief='flat')
    color1.grid(row=0, column=0, sticky='news', padx=2, pady=2)
    color1b = Button(color1, relief='flat', background=Color1, command=lambda: colorS(1))
    color1b.pack(fill=BOTH, expand=True)
    color2 = LabelFrame(colorSelect, text="Color 2", labelanchor='s', relief='flat')
    color2.grid(row=0, column=1, sticky='news', padx=2, pady=2)
    color2b = Button(color2, relief='flat', background=Color2, command=lambda: colorS(2))
    color2b.pack(fill=BOTH, expand=True)
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)
    if Color1 != "#FFFFFF":
        textButtonI["selectcolor"] = Color1
        textButtonU["selectcolor"] = Color1
        textButtonB["selectcolor"] = Color1
        textButtonO["selectcolor"] = Color1

def colorS(t):
    global cs
    cs = t
    color1 = LabelFrame(colorSelect, text="Color 1", labelanchor='s', relief='flat')
    color1.grid(row=0, column=0, sticky='news', padx=2, pady=2)
    color1b = Button(color1, relief='flat', background=Color1, command=lambda: colorS(1))
    color1b.pack(fill=BOTH, expand=True)
    color2 = LabelFrame(colorSelect, text="Color 2", labelanchor='s', relief='flat')
    color2.grid(row=0, column=1, sticky='news', padx=2, pady=2)
    color2b = Button(color2, relief='flat', background=Color2, command=lambda: colorS(2))
    color2b.pack(fill=BOTH, expand=True)
    fontText = font.Font(family=fontFamilyVar.get(), size=SizeVar.get(), weight=BoldVar.get(),
                         slant=ItalicVar.get(), underline=UnderVar.get(), overstrike=OverVar.get())
    text.configure(font=fontText, foreground=Color1)

colorbox.rowconfigure(0)
colorbox.rowconfigure(1)
colorbox.columnconfigure(0)
colorbox.columnconfigure(1)
colorbox.columnconfigure(2)
colorbox.columnconfigure(3)
colorbox.columnconfigure(4)
colorbox.columnconfigure(5)
colorbox.columnconfigure(6)

c1 = Button(colorbox, width=2, command=lambda: setColor("#FF3333"), background="#FF3333", relief="flat")
c1.grid(row=0, column=0, padx=4, pady=5)
c2 = Button(colorbox, width=2, command=lambda: setColor("#FF6B33"), background="#FF6B33", relief="flat")
c2.grid(row=0, column=1, padx=4, pady=5)
c3 = Button(colorbox, width=2, command=lambda: setColor("#FFFFFF"), background="#FFFFFF", relief="flat")
c3.grid(row=0, column=2, padx=4, pady=5)
c4 = Button(colorbox, width=2, command=lambda: setColor("#FFB833"), background="#FFB833", relief="flat")
c4.grid(row=0, column=3, padx=4, pady=5)
c5 = Button(colorbox, width=2, command=lambda: setColor("#FFE933"), background="#FFE933", relief="flat")
c5.grid(row=0, column=4, padx=4, pady=5)
c6 = Button(colorbox, width=2, command=lambda: setColor("#A8FF33"), background="#A8FF33", relief="flat")
c6.grid(row=0, column=5, padx=4, pady=5)
c7 = Button(colorbox, width=2, command=lambda: setColor("#49FF33"), background="#49FF33", relief="flat")
c7.grid(row=0, column=6, padx=4, pady=5)
c8 = Button(colorbox, width=2, command=lambda: setColor("#33FF6B"), background="#33FF6B", relief="flat")
c8.grid(row=1, column=0, padx=4, pady=1)
c9 = Button(colorbox, width=2, command=lambda: setColor("#07531C"), background="#07531C", relief="flat")
c9.grid(row=1, column=1, padx=4, pady=1)
c10 = Button(colorbox, width=2, command=lambda: setColor("#13E2DF"), background="#13E2DF", relief="flat")
c10.grid(row=1, column=2, padx=4, pady=1)
c11 = Button(colorbox, width=2, command=lambda: setColor("#13B0E2"), background="#13B0E2", relief="flat")
c11.grid(row=1, column=3, padx=4, pady=1)
c12 = Button(colorbox, width=2, command=lambda: setColor("#1339E2"), background="#1339E2", relief="flat")
c12.grid(row=1, column=4, padx=4, pady=1)
c13 = Button(colorbox, width=2, command=lambda: setColor("#B613E2"), background="#B613E2", relief="flat")
c13.grid(row=1, column=5, padx=4, pady=1)
c14 = Button(colorbox, width=2, command=lambda: setColor("#E21374"), background="#E21374", relief="flat")
c14.grid(row=1, column=6, padx=4, pady=1)

colorSelect.rowconfigure(0, weight=0)
colorSelect.columnconfigure(0, weight=40)
colorSelect.columnconfigure(1, weight=40)
color1 = Labelframe(colorSelect, text="Color 1", labelanchor='s', height=2)
color1.grid(row=0, column=0, sticky='news', padx=2, pady=2)
color1b = Button(color1, relief='flat', background=Color1, command=lambda: colorS(1), width=2, height=2)
color1b.pack(fill=BOTH)
color2 = Labelframe(colorSelect, text="Color 2", labelanchor='s', height=2)
color2.grid(row=0, column=1, sticky='news', padx=2, pady=2)
color2b = Button(color2, relief='flat', background=Color2, command=lambda: colorS(2), width=2, height=2)
color2b.pack(fill=BOTH)
# ...............................................................................

GotoOutline = 1

# outline and fill color ..........................................

def out(s):
    global Color2, outLinevar
    if s == "OSC":
        outLinevar = Color2
    elif s == "NO":
        outLinevar = ''

def Fill(s):
    global fillvar, Color1
    if s == "FSC":
        fillvar = Color1
    elif s == "NF":
        fillvar = ''

resource_path(".img\\outline.png")
outlineIMG = Image.open(".img\\outline.png")
outlineIMG = outlineIMG.resize((15, 15), Image.ANTIALIAS)
Outline1Img = ImageTk.PhotoImage(outlineIMG)

resource_path(".img\\fill.png")
fillColorIMG = Image.open(".img\\fill.png")
fillColorIMG = fillColorIMG.resize((15, 15), Image.ANTIALIAS)
FillColor1IMG = ImageTk.PhotoImage(fillColorIMG)

outFrame = LabelFrame(out_fill, relief="flat")
outFrame.pack(pady=1, side=TOP)
fillFrame = LabelFrame(out_fill, relief="flat")
fillFrame.pack(pady=1, side=TOP)
outButton = Menubutton(outFrame, text="outline", anchor='n', image=Outline1Img, compound=LEFT, relief="flat")
outButton.menu2 = Menu(outButton, foreground="white", background="black")
outButton["menu"] = outButton.menu2
outButton.menu2.add_radiobutton(label="No Outline", command=lambda: out("NO"),
                                font=font.Font(family="Sitka Heading", size=9), background="black", foreground="white")
outButton.menu2.add_radiobutton(label="Solid Color", command=lambda: out("OSC"),
                                font=font.Font(family="Sitka Heading", size=9), background="black", foreground="white")
outButton.pack(side=TOP)

fillButton = Menubutton(fillFrame, text="fill color", image=FillColor1IMG, compound=LEFT, relief="flat")
fillButton.menu3 = Menu(fillButton, foreground="white", background="black")
fillButton["menu"] = fillButton.menu3
fillButton.menu3.add_radiobutton(label="No fill", command=lambda: Fill("NF"),
                                 font=font.Font(family="Sitka Heading", size=9), background="black", foreground="white")
fillButton.menu3.add_radiobutton(label="Solid Color", command=lambda: Fill("FSC"),
                                 font=font.Font(family="Sitka Heading", size=9), background="black", foreground="white")
fillButton.pack(side=TOP)

# .................................................................................

GotoShapes = 1

# shapes    RECTANGLE , TRAINGLE , CIRCLE , OVAL , STAR ETC ............................................................

ir, ic, it, iet, irt, ih1, ih2 = -1, -1, -1, -1, -1, -1, -1
px, py, polyi = 0, 0, -1
X, Y = 0, 0
sti = -1
polyx1, polyy1 = 0, 0
shapeType = "rectangle"

def coordinate(event):
    global sx, sy, polyx1, polyy1
    sx, sy = event.x, event.y
    if polyx1 == 0 and polyy1 == 0:
        polyx1, polyy1 = event.x, event.y

def paintShapes(event):
    global X, sx, sy, r1s, c1s, shapeType, Y, outLinevar, fillvar, t1s, et1s, et1, rt1s, h1s, h2s, star1
    global px, py, poly1, polyx1, polyy1

    px, py = 0, 0
    if shapeType == "rectangle":
        polyx1, polyy1 = 0, 0
        contentLabel.delete(r1s)
        r1s = contentLabel.create_rectangle(sx, sy, event.x, event.y, outline=outLinevar, fill=fillvar)
    elif shapeType == "circle":
        polyx1, polyy1 = 0, 0
        contentLabel.delete(c1s)
        c1s = contentLabel.create_oval(sx, sy, event.x, event.y, outline=outLinevar, fill=fillvar)
    elif shapeType == 'triangle':
        polyx1, polyy1 = 0, 0
        contentLabel.delete(t1s)
        t1s = contentLabel.create_polygon(sx, sy, event.x + 100, event.y, event.x - 100, event.y, outline=outLinevar,
                                          fill=fillvar)
    elif shapeType == 'Etriangle':
        polyx1, polyy1 = 0, 0
        contentLabel.delete(et1s)
        et1s = contentLabel.create_polygon(sx, sy, event.x, event.y, 2 * sx - event.x, event.y, outline=outLinevar,
                                           fill=fillvar)
    elif shapeType == "Rtriangle":
        polyx1, polyy1 = 0, 0
        contentLabel.delete(rt1s)
        rt1s = contentLabel.create_polygon(sx, sy, event.x, event.y, sx, event.y, outline=outLinevar, fill=fillvar)
    elif shapeType == "heart":
        polyx1, polyy1 = 0, 0
        if fillvar != '':
            contentLabel.delete(h1s)
            contentLabel.delete(h2s)
            h1s = contentLabel.create_polygon(sx, sy, sx - (event.x - sx) / 3, sy - (event.y - sy) / 10,
                                              sx - (event.x - sx) / 2, sy + (event.y - sy) / 4, sx + (event.x - sx) / 9,
                                              event.y, smooth=True, fill=fillvar, outline=outLinevar)
            h2s = contentLabel.create_polygon(sx, sy, sx + (event.x - sx) / 3, sy - (event.y - sy) / 10,
                                              sx + (event.x - sx) / 2, sy + (event.y - sy) / 4, sx - (event.x - sx) / 9,
                                              event.y, smooth=True, fill=fillvar, outline=outLinevar)
        else:
            contentLabel.delete(h1s)
            contentLabel.delete(h2s)
            h1s = contentLabel.create_line(sx, sy, sx - (event.x - sx) / 4, sy - (event.y - sy) / 4,
                                           sx - (event.x - sx) / 2, sy + (event.y - sy) / 4, sx, event.y, smooth=True,
                                           fill=outLinevar)
            h2s = contentLabel.create_line(sx, sy, sx + (event.x - sx) / 4, sy - (event.y - sy) / 4,
                                           sx + (event.x - sx) / 2, sy + (event.y - sy) / 4, sx, event.y, smooth=True,
                                           fill=outLinevar)
    elif shapeType == "star":
        polyx1, polyy1 = 0, 0
        contentLabel.delete(star1)
        star1 = contentLabel.create_polygon(sx, sy, sx + (event.x - sx) / 3, sy + (event.y - sy) / 3, event.x,
                                            sy + (event.y - sy) / 2,
                                            sx + (event.x - sx) / 3, sy + 2 * (event.y - sy) / 3, sx, event.y,
                                            sx - (event.x - sx) / 3,
                                            sy + 2 * (event.y - sy) / 3, 2 * sx - event.x, sy + (event.y - sy) / 2,
                                            sx - (event.x - sx) / 3, sy + (event.y - sy) / 3, sx, sy, fill=fillvar,
                                            outline=outLinevar)
    elif shapeType == "poly":
        if fillvar == '':
            pfillvar = "black"
        else:
            pfillvar = fillvar
        contentLabel.delete(poly1)
        poly1 = contentLabel.create_line(polyx1, polyy1, event.x, event.y, fill=pfillvar)
    elif shapeType == "d1":
        contentLabel.create_rectangle(sx, sy, event.x, event.y, outline=outLinevar, fill=fillvar)
    elif shapeType == "d2":
        contentLabel.create_oval(sx, sy, event.x, event.y, outline=outLinevar, fill=fillvar)
    elif shapeType == "d3":
        contentLabel.create_polygon(sx, sy, event.x + 100, event.y, event.x - 100, event.y, outline=outLinevar,
                                    fill=fillvar)
    elif shapeType == "d4":
        contentLabel.create_polygon(sx, sy, event.x, event.y, 2 * sx - event.x, event.y, outline=outLinevar,
                                    fill=fillvar)
    elif shapeType == "d5":
        contentLabel.create_polygon(sx, sy, sx - (event.x - sx) / 3, sy - (event.y - sy) / 10,
                                    sx - (event.x - sx) / 2, sy + (event.y - sy) / 4, sx + (event.x - sx) / 9,
                                    event.y, smooth=True, fill=fillvar, outline=outLinevar)
        contentLabel.create_polygon(sx, sy, sx + (event.x - sx) / 3, sy - (event.y - sy) / 10,
                                    sx + (event.x - sx) / 2, sy + (event.y - sy) / 4, sx - (event.x - sx) / 9,
                                    event.y, smooth=True, fill=fillvar, outline=outLinevar)
    elif shapeType == "d6":
        contentLabel.create_polygon(sx, sy, sx + (event.x - sx) / 3, sy + (event.y - sy) / 3, event.x,
                                    sy + (event.y - sy) / 2,
                                    sx + (event.x - sx) / 3, sy + 2 * (event.y - sy) / 3, sx, event.y,
                                    sx - (event.x - sx) / 3,
                                    sy + 2 * (event.y - sy) / 3, 2 * sx - event.x, sy + (event.y - sy) / 2,
                                    sx - (event.x - sx) / 3, sy + (event.y - sy) / 3, sx, sy, fill=fillvar,
                                    outline=outLinevar)

def resetShapes(event):
    global r1, r1s, ir, ic, shapeType, c1s, c1, t1, t1s, it, iet, et1s, et1, rt1s, irt, rt1
    global h1, h2, h1s, h2s, ih1, ih2, Stars, star1, sti, poly, poly1, polyi, polyx1, polyy1

    if shapeType == "rectangle":
        if ir < 1000:
            ir = ir + 1
            r1s = r1[ir]
    elif shapeType == "circle":
        if ic < 1000:
            ic = ic + 1
            c1s = c1[ic]
    elif shapeType == "triangle":
        if it < 1000:
            it = it + 1
            t1s = t1[it]
    elif shapeType == "Etriangle":
        if iet < 1000:
            iet = iet + 1
            et1s = et1[iet]
    elif shapeType == "Rtriangle":
        if irt < 1000:
            irt = irt + 1
            rt1s = rt1[irt]
    elif shapeType == "heart":
        if ih1 < 1000:
            ih1 += 1
            ih2 += 1
            h1s = h1[ih1]
            h2s = h2[ih2]
    elif shapeType == "star":
        if sti < 1000:
            sti = sti + 1
            star1 = Stars[sti]
    elif shapeType == "poly":
        polyx1, polyy1 = event.x, event.y
        if polyi < 1000:
            polyi += 1
            poly1 = poly[polyi]

def shapesChoose(string):
    global choosebox, shapeType
    choosebox = 2
    shapeType = string
    contentLabel.bind("<ButtonRelease-1>", resetShapes)
    contentLabel.bind("<Button-1>", coordinate)
    contentLabel.bind("<B1-Motion>", paintShapes)

# Rectangle
r1 = [contentLabel.create_rectangle(0, 0, 0, 0)] * 1000
r1s = r1[0]
# circle
c1 = [contentLabel.create_oval(0, 0, 0, 0)] * 1000
c1s = c1[0]

# Triangle
t1 = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
t1s = t1[0]

# Equilateral Triangle
et1 = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
et1s = et1[0]

# Right Angled Triangle
rt1 = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
rt1s = rt1[0]

# Heart
h1 = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
h1s = h1[0]
h2 = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
h2s = h2[0]

# Star
Stars = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
star1 = Stars[0]

# Polygon
poly = [contentLabel.create_polygon(0, 0, 0, 0, 0, 0)] * 1000
poly1 = poly[0]

shapes.rowconfigure(0)
shapes.rowconfigure(1)
shapes.columnconfigure(0)
shapes.columnconfigure(1)
shapes.columnconfigure(2)
shapes.columnconfigure(3)

ShapesImageList = ["rectangle.png", "circle.png", "triangle.jpg", "Etriangle.png", "Rtriangle.png", "heart.png",
                   "star.png", "poly.png"]

shapeList = [None] * 8
shapeImageList = [None] * 8
for i in range(0, 8):
    resource_path(".img\\"+ShapesImageList[i])
    shapeList[i] = Image.open(".img\\"+ShapesImageList[i])
    shapeList[i] = shapeList[i].resize((20, 20), Image.ANTIALIAS)
    ShapesImageList[i] = ImageTk.PhotoImage(shapeList[i])

s1 = Button(shapes, command=lambda: shapesChoose("rectangle"), relief="flat", image=ShapesImageList[0], compound=CENTER,
            width=20)
s1.grid(row=0, column=0, padx=2, pady=5)
s2 = Button(shapes, command=lambda: shapesChoose("circle"), relief="flat", image=ShapesImageList[1], compound=CENTER,
            width=20)
s2.grid(row=0, column=1, padx=2, pady=5)
s3 = Button(shapes, command=lambda: shapesChoose("triangle"), relief="flat", image=ShapesImageList[2], compound=CENTER,
            width=20)
s3.grid(row=0, column=2, padx=2, pady=5)
s4 = Button(shapes, command=lambda: shapesChoose("Etriangle"), relief="flat", image=ShapesImageList[3], compound=CENTER,
            width=20)
s4.grid(row=0, column=3, padx=2, pady=5)
s5 = Button(shapes, command=lambda: shapesChoose("Rtriangle"), relief="flat", image=ShapesImageList[4], compound=CENTER,
            width=20)
s5.grid(row=1, column=0, padx=2, pady=5)
s6 = Button(shapes, command=lambda: shapesChoose("heart"), relief="flat", image=ShapesImageList[5], compound=CENTER,
            width=20)
s6.grid(row=1, column=1, padx=2, pady=5)
s7 = Button(shapes, command=lambda: shapesChoose("star"), relief="flat", image=ShapesImageList[6], compound=CENTER,
            width=20)
s7.grid(row=1, column=2, padx=2, pady=5)
s8 = Button(shapes, command=lambda: shapesChoose("poly"), relief="flat", image=ShapesImageList[7], compound=CENTER,
            width=20)
s8.grid(row=1, column=3, padx=2, pady=5)

# .........................................................................................................................................

GotoMoreColors = 1
# More Colors ............................ .           .                          ...............................................

colors = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace',
          'linen', 'antique white', 'papaya whip', 'blanched almond', 'bisque', 'peach puff',
          'navajo white', 'lemon chiffon', 'mint cream', 'azure', 'alice blue', 'lavender',
          'lavender blush', 'misty rose', 'dark slate gray', 'dim gray', 'slate gray',
          'light slate gray', 'gray', 'light grey', 'midnight blue', 'navy', 'cornflower blue', 'dark slate blue',
          'slate blue', 'medium slate blue', 'light slate blue', 'medium blue', 'royal blue', 'blue',
          'dodger blue', 'deep sky blue', 'sky blue', 'light sky blue', 'steel blue', 'light steel blue',
          'light blue', 'powder blue', 'pale turquoise', 'dark turquoise', 'medium turquoise', 'turquoise',
          'cyan', 'light cyan', 'cadet blue', 'medium aquamarine', 'aquamarine', 'dark green', 'dark olive green',
          'dark sea green', 'sea green', 'medium sea green', 'light sea green', 'pale green', 'spring green',
          'lawn green', 'medium spring green', 'green yellow', 'lime green', 'yellow green',
          'forest green', 'olive drab', 'dark khaki', 'khaki', 'pale goldenrod', 'light goldenrod yellow',
          'light yellow', 'yellow', 'gold', 'light goldenrod', 'goldenrod', 'dark goldenrod', 'rosy brown',
          'indian red', 'saddle brown', 'sandy brown',
          'dark salmon', 'salmon', 'light salmon', 'orange', 'dark orange',
          'coral', 'light coral', 'tomato', 'orange red', 'red', 'hot pink', 'deep pink', 'pink', 'light pink',
          'pale violet red', 'maroon', 'medium violet red', 'violet red',
          'medium orchid', 'dark orchid', 'dark violet', 'blue violet', 'purple', 'medium purple',
          'thistle', 'snow2', 'snow3',
          'snow4', 'seashell2', 'seashell3', 'seashell4', 'AntiqueWhite1', 'AntiqueWhite2',
          'AntiqueWhite3', 'AntiqueWhite4', 'bisque2', 'bisque3', 'bisque4', 'PeachPuff2',
          'PeachPuff3', 'PeachPuff4', 'NavajoWhite2', 'NavajoWhite3', 'NavajoWhite4',
          'LemonChiffon2', 'LemonChiffon3', 'LemonChiffon4', 'cornsilk2', 'cornsilk3',
          'cornsilk4', 'ivory2', 'ivory3', 'ivory4', 'honeydew2', 'honeydew3', 'honeydew4',
          'LavenderBlush2', 'LavenderBlush3', 'LavenderBlush4', 'MistyRose2', 'MistyRose3',
          'MistyRose4', 'azure2', 'azure3', 'azure4', 'SlateBlue1', 'SlateBlue2', 'SlateBlue3',
          'SlateBlue4', 'RoyalBlue1', 'RoyalBlue2', 'RoyalBlue3', 'RoyalBlue4', 'blue2', 'blue4',
          'DodgerBlue2', 'DodgerBlue3', 'DodgerBlue4', 'SteelBlue1', 'SteelBlue2',
          'SteelBlue3', 'SteelBlue4', 'DeepSkyBlue2', 'DeepSkyBlue3', 'DeepSkyBlue4',
          'SkyBlue1', 'SkyBlue2', 'SkyBlue3', 'SkyBlue4', 'LightSkyBlue1', 'LightSkyBlue2',
          'LightSkyBlue3', 'LightSkyBlue4', 'SlateGray1', 'SlateGray2', 'SlateGray3',
          'SlateGray4', 'LightSteelBlue1', 'LightSteelBlue2', 'LightSteelBlue3',
          'LightSteelBlue4', 'LightBlue1', 'LightBlue2', 'LightBlue3', 'LightBlue4',
          'LightCyan2', 'LightCyan3', 'LightCyan4', 'PaleTurquoise1', 'PaleTurquoise2',
          'PaleTurquoise3', 'PaleTurquoise4', 'CadetBlue1', 'CadetBlue2', 'CadetBlue3',
          'CadetBlue4', 'turquoise1', 'turquoise2', 'turquoise3', 'turquoise4', 'cyan2', 'cyan3',
          'cyan4', 'DarkSlateGray1', 'DarkSlateGray2', 'DarkSlateGray3', 'DarkSlateGray4',
          'aquamarine2', 'aquamarine4', 'DarkSeaGreen1', 'DarkSeaGreen2', 'DarkSeaGreen3',
          'DarkSeaGreen4', 'SeaGreen1', 'SeaGreen2', 'SeaGreen3', 'PaleGreen1', 'PaleGreen2',
          'PaleGreen3', 'PaleGreen4', 'SpringGreen2', 'SpringGreen3', 'SpringGreen4',
          'green2', 'green3', 'green4', 'chartreuse2', 'chartreuse3', 'chartreuse4',
          'OliveDrab1', 'OliveDrab2', 'OliveDrab4', 'DarkOliveGreen1', 'DarkOliveGreen2',
          'DarkOliveGreen3', 'DarkOliveGreen4', 'khaki1', 'khaki2', 'khaki3', 'khaki4',
          'LightGoldenrod1', 'LightGoldenrod2', 'LightGoldenrod3', 'LightGoldenrod4',
          'LightYellow2', 'LightYellow3', 'LightYellow4', 'yellow2', 'yellow3', 'yellow4',
          'gold2', 'gold3', 'gold4', 'goldenrod1', 'goldenrod2', 'goldenrod3', 'goldenrod4',
          'DarkGoldenrod1', 'DarkGoldenrod2', 'DarkGoldenrod3', 'DarkGoldenrod4',
          'RosyBrown1', 'RosyBrown2', 'RosyBrown3', 'RosyBrown4', 'IndianRed1', 'IndianRed2',
          'IndianRed3', 'IndianRed4', 'sienna1', 'sienna2', 'sienna3', 'sienna4', 'burlywood1',
          'burlywood2', 'burlywood3', 'burlywood4', 'wheat1', 'wheat2', 'wheat3', 'wheat4', 'tan1',
          'tan2', 'tan4', 'chocolate1', 'chocolate2', 'chocolate3', 'firebrick1', 'firebrick2',
          'firebrick3', 'firebrick4', 'brown1', 'brown2', 'brown3', 'brown4', 'salmon1', 'salmon2',
          'salmon3', 'salmon4', 'LightSalmon2', 'LightSalmon3', 'LightSalmon4', 'orange2',
          'orange3', 'orange4', 'DarkOrange1', 'DarkOrange2', 'DarkOrange3', 'DarkOrange4',
          'coral1', 'coral2', 'coral3', 'coral4', 'tomato2', 'tomato3', 'tomato4', 'OrangeRed2',
          'OrangeRed3', 'OrangeRed4', 'red2', 'red3', 'red4', 'DeepPink2', 'DeepPink3', 'DeepPink4',
          'HotPink1', 'HotPink2', 'HotPink3', 'HotPink4', 'pink1', 'pink2', 'pink3', 'pink4',
          'LightPink1', 'LightPink2', 'LightPink3', 'LightPink4', 'PaleVioletRed1',
          'PaleVioletRed2', 'PaleVioletRed3', 'PaleVioletRed4', 'maroon1', 'maroon2',
          'maroon3', 'maroon4', 'VioletRed1', 'VioletRed2', 'VioletRed3', 'VioletRed4',
          'magenta2', 'magenta3', 'magenta4', 'orchid1', 'orchid2', 'orchid3', 'orchid4', 'plum1',
          'plum2', 'plum3', 'plum4', 'MediumOrchid1', 'MediumOrchid2', 'MediumOrchid3',
          'MediumOrchid4', 'DarkOrchid1', 'DarkOrchid2', 'DarkOrchid3', 'DarkOrchid4',
          'purple1', 'purple2', 'purple3', 'purple4', 'MediumPurple1', 'MediumPurple2',
          'MediumPurple3', 'MediumPurple4', 'thistle1', 'thistle2', 'thistle3', 'thistle4',
          'gray1', 'gray2', 'gray3', 'gray4', 'gray5', 'gray6', 'gray7', 'gray8', 'gray9', 'gray10',
          'gray11', 'gray12', 'gray13', 'gray14', 'gray15', 'gray16', 'gray17', 'gray18', 'gray19',
          'gray20', 'gray21', 'gray22', 'gray23', 'gray24', 'gray25', 'gray26', 'gray27', 'gray28',
          'gray29', 'gray30', 'gray31', 'gray32', 'gray33', 'gray34', 'gray35', 'gray36', 'gray37',
          'gray38', 'gray39', 'gray40', 'gray42', 'gray43', 'gray44', 'gray45', 'gray46', 'gray47',
          'gray48', 'gray49', 'gray50', 'gray51', 'gray52', 'gray53', 'gray54', 'gray55', 'gray56',
          'gray57', 'gray58', 'gray59', 'gray60', 'gray61', 'gray62', 'gray63', 'gray64', 'gray65',
          'gray66', 'gray67', 'gray68', 'gray69', 'gray70', 'gray71', 'gray72', 'gray73', 'gray74',
          'gray75', 'gray76', 'gray77', 'gray78', 'gray79', 'gray80', 'gray81', 'gray82', 'gray83',
          'gray84', 'gray85', 'gray86', 'gray87', 'gray88', 'gray89', 'gray90', 'gray91', 'gray92',
          'gray93', 'gray94', 'gray95', 'gray97', 'gray98', 'gray99']

resource_path(".img\\More.png")
colorMenuIMG = Image.open(".img\\More.png")
colorMenuIMG = colorMenuIMG.resize((60, 60), Image.AFFINE)
ColorMenuIMG = ImageTk.PhotoImage(colorMenuIMG)

color_menu = Menubutton(editColor, anchor='n', image=ColorMenuIMG, compound=CENTER, foreground="white",
                        background="black")
color_menu.menu = Menu(color_menu, background="black")
color_menu["menu"] = color_menu.menu
colorMore = StringVar()
colorMore.set("black")

def MoreColors():
    global Color1, Color2, cs, outLinevar, fillvar
    if cs == 1:
        Color1 = colorMore.get()
        fillvar = Color1
    else:
        Color2 = colorMore.get()
        outLinevar = Color2
    color1 = LabelFrame(colorSelect, text="Color 1", labelanchor='s', relief='flat')
    color1.grid(row=0, column=0, sticky='news', padx=2, pady=2)
    color1b = Button(color1, relief='flat', background=Color1, command=lambda: colorS(1))
    color1b.pack(fill=BOTH, expand=True)
    color2 = LabelFrame(colorSelect, text="Color 2", labelanchor='s', relief='flat')
    color2.grid(row=0, column=1, sticky='news', padx=2, pady=2)
    color2b = Button(color2, relief='flat', background=Color2, command=lambda: colorS(2))
    color2b.pack(fill=BOTH, expand=True)

for i in range(0, len(colors)):
    color_menu.menu.add_radiobutton(label=colors[i], command=MoreColors, variable=colorMore, value=colors[i],
                                    background=colors[i])

color_menu.pack()

# ....................................................................................................................................

# Speech Recognition  . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
#   https://realpython.com/python-speech-recognition/
# https://pypi.org/project/SpeechRecognition/1.3.0/
# Initialize the recognizer

reco1 = sr.Recognizer()
reco1.energy_threshold = 3900
reco1.pause_threshold = 3
reco2 = sr.Recognizer()
reco2.energy_threshold = 3800
reco3 = sr.Recognizer()
reco3.energy_threshold = 3900
xrec, yrec = 0, 0
dicText = {"question mark": '?', "exclamation mark": '!', "full stop": '.', "comma": ',',
           "parentheses braces open": "(", "parentheses braces close": ")", "Apostrophe": "'", "Asterisk": "*",
           "colon": ':', "dash": "-", "semi colon": ';', "slash": '/', "curly braces open ": '{',
           "curly braces close": '}', "square braces open": "[", "square braces close": "]", "percent":
               '%', "equal": '=', "hyphen": '`', "new line": r'\n', "tab": r'\t'}
# Function to convert text to
# speech
MyText = "aww"
recoText = "aww"
checkPunText = "aww"
checkWinText = Text()
lanVar = IntVar()
languageSelect = "en-US"
languageSelectSay = 'en'
lanInd = 0
noiseVar = IntVar()
noiseVar.set(3900)

def extract():
    global instruct_ind, checkWinText
    checkWin = Tk()
    checkWin.title("Speech Recognition")
    checkWin.geometry("400x200")
    if speechVar == 0:
        checkWinText.destroy()
        return
    checkWinText = Text(checkWin, width=60, height=60)
    scrollerReco = Scrollbar(checkWin, orient="vertical", command=checkWinText.yview)
    checkWinText.configure(font=("Kokila", 13), background="black", foreground="#00F3E8",
                           yscrollcommand=scrollerReco.set)
    checkWinText.insert('end',
                        "Python is Everywhere ,thanks for your attention ...\n note : \n 1. Read the whole line till fullstop ,don't speak phrase of words speak the whole sentence \n 2 . At the end of each sentece try to speak the last word loudly "
                        "\n 3. Check your internet connection in case of Slow response.\n 4. Another solution in case of slow response is to increase the \nthreshold energy so as to ignore the unwanted noise during listening , "
                        "\nit can be acheived by increasing the value of value above 4000 in spinbox ,\n and you should have to speak loudly as compared background noise")
    checkWinText.see("end")
    scrollerReco.pack(side="right", fill="y")
    checkWinText.pack()
    checkWinText.mainloop()

def languageFun():
    global languageSelect, languageSelectSay
    if lanVar.get():
        LanguageB["image"] = LanguageHin
        languageSelect = "hi-IN"
        languageSelectSay = 'hi'
    elif lanVar.get() == 0:
        LanguageB["image"] = LanguageEng
        languageSelect = "en-US"
        languageSelectSay = 'en'

def Noiselevel():
    global reco1, reco2, reco3
    reco1.energy_threshold = int(NoiseLevel.get())
    reco2.energy_threshold = int(NoiseLevel.get())
    reco3.energy_threshold = int(NoiseLevel.get())

def SpeakText(command, languageSend):
    # Initialize the engine
    global lanInd
    if languageSend == 'hi':
        lanInd += 1
        getAud = gtts.gTTS(command, lang=languageSelectSay)
        getAud.save("voice{}.mp3".format(lanInd))
        playsound("voice{}.mp3".format(lanInd))
        os.remove("voice{}.mp3".format(lanInd))
    elif languageSend == 'en':
        engine = pyttsx3.init()
        engine.say(command)
        engine.runAndWait()

def checkVoiceCom():
    global MyText, checkWinText, checkPunText, l
    indexReco = 3
    with sr.Microphone() as source2:
        while (indexReco):
            SpeakText(recoText, 'hi')
            checkWinText.insert('end', "\n*. STATEMENT :  {} ".format(recoText))
            checkWinText.see("end")
            checkWinText["foreground"] = "white"
            checkWinText.insert('end',
                                "\nx. INSTRUCTION :  Say \'best\' if statement correct otherwise say \'net\' and in case of punctuation say get")
            checkWinText.see("end")
            SpeakText("Say best if statement is correct and say net if not and in case of punctuation say get", 'en')

            # speechRecoActivate["text"] = "Say Set"
            audio3 = reco2.record(source2, duration=3)
            try:
                checkText = reco2.recognize_google(audio3)
                checkText = checkText.lower()
                print(checkText)

                if checkText == "best" or checkText == 'bast':
                    print(checkText)
                    return 1
                elif checkText == "net" or checkText == 'nat':
                    return 0
                elif checkText == "get" or checkText == 'gat':
                    print("p")
                    punT = 3

                    for keysT in dicText:
                        checkWinText.insert('end', " \n {0}   =  {1} ".format(keysT, dicText[keysT]))
                    checkWinText.insert('end', "select any punctuation within 4 sec ..")
                    checkWinText.see("end")
                    while (punT):
                        with sr.Microphone() as source4:
                            print("say pun")
                            audio4 = reco3.record(source4, duration=4)
                            try:
                                checkPunText = reco3.recognize_google(audio4)
                                checkPunText = checkPunText.lower()
                                pun = dicText.get(checkPunText, None)
                                print(checkPunText)
                                if option == "text" and pun != None:
                                    Notepad.insert("end", pun + " ")
                                    return 0
                            except sr.RequestError as e:
                                checkWinText.insert("end", "\n {} ".format(e))
                                checkWinText.see("end")
                                print("errer {0}".format(e))

                            except sr.UnknownValueError:
                                print("Speak Again ...............")
                                checkWinText.insert("end", "\nSpeak Again ...............")
                                checkWinText.see("end")
                        punT -= 1
                    return 0

            except sr.RequestError as e:
                checkWinText.insert("end", "\n{} ".format(e))
                checkWinText.see("end")
                print("errer {0}".format(e))

            except sr.UnknownValueError:
                print("Speak Again ...............")
                checkWinText.insert("end", "\nSpeak Again ...............")
                checkWinText.see("end")
            indexReco = indexReco - 1

    checkWinText.insert('end', "\nspeak new statement..")
    checkWinText.see('end')
    speechRecoActivate["image"] = SpeechRecoIMG[0]

def getRecoCor(event):
    global xrec, yrec
    xrec = event.x
    yrec = event.y

def callback(reco1, audio2):
    print("callback")
    global recoText, x0, y0

    try:

        MyText = reco1.recognize_google(audio2, language=languageSelect)
        recoText = str(MyText)
        if checkVoiceCom() == 1:
            if option == "text":
                Notepad.insert("end", MyText + " ")
            else:
                if x0 == 0 and y0 == 0:
                    x0, y0 = 20, 20
                contentLabel.create_text(x0, y0 + 5, text=MyText, anchor='nw')
        else:
            SpeakText("Please speak it again", 'en')

    except sr.RequestError as e:
        print("Could not request results; {0}".format(e))
        checkWinText.insert("end", "\n{} ".format(e))
        checkWinText.see("end")

    except sr.UnknownValueError:
        print("Speak Again ...............")
        SpeakText("Speak Again", 'en')
        checkWinText.insert("end", "\n Speak Again ...............")
        checkWinText.see("end")

def SpeechRecognition():
    global instruct_ind, MyText, recoText
    global notePadData, notepadWin, Notepad, FileSave, option
    speechRecoActivate["image"] = SpeechRecoIMG[0]
    if speechVar.get():
        source2 = sr.Microphone()
        print("YES")
        reco1.listen_in_background(source2, callback)
    elif speechVar.get() == 0:
        print(speechVar.get())
        speechRecoActivate["image"] = SpeechRecoIMG[1]

ImgReco = ["listen.png", "record.png", "wait.png"]
speechRecoIMG = [None] * 3
SpeechRecoIMG = [None] * 3
for i in range(0, 3):
    speechRecoIMG[i] = Image.open(".img\\"+ImgReco[i])
    speechRecoIMG[i] = speechRecoIMG[i].resize((20, 20), Image.AFFINE)
    SpeechRecoIMG[i] = ImageTk.PhotoImage(speechRecoIMG[i])

resource_path(".img\\Eng2.jpg")
resource_path(".img\\Hin1.png")

languageEng = Image.open(".img\\Eng2.jpg")
languageEng = languageEng.resize((20, 20), Image.AFFINE)
LanguageEng = ImageTk.PhotoImage(languageEng)
languageHin = Image.open(".img\\Hin1.png")
languageHin = languageHin.resize((20, 20), Image.ADAPTIVE)
LanguageHin = ImageTk.PhotoImage(languageHin)

speechVar = IntVar()
speechReco = LabelFrame(textLabel, width=10)
speechReco.grid(row=0, column=2, sticky="news", padx=20)
speechRecoActivate = Checkbutton(speechReco, text="SPEAK", variable=speechVar, command=SpeechRecognition,
                                 image=SpeechRecoIMG[1], indicatoron=0, foreground="white", background="white",
                                 selectcolor="red", relief='flat')
speechRecoActivate.pack(expand=True, fill=BOTH, side="left", padx=5)
traceB = Button(speechReco, text="Trace", command=extract, foreground="white", background="black", width=5,
                relief='flat')
traceB.pack(fill=BOTH, expand=True, side="left", padx=5)
LanguageB = Checkbutton(speechReco, command=languageFun, foreground="white", background="black", width=10,
                        image=LanguageEng, variable=lanVar, indicatoron=0, relief='flat')
LanguageB.pack(fill=BOTH, expand=True, side="left", padx=5)
NoiseLevel = Spinbox(speechReco, command=Noiselevel, from_=120, to=8000, width=5, foreground="white",
                     background="black", textvariable=noiseVar, relief='flat')
NoiseLevel.pack(fill=BOTH, expand=True, side="left", padx=5)

# .........................................................................................................................................

# https://www.tcl.tk/man/tcl8.6/TkCmd/keysyms.htm

def Savefilehandler(event):
    if option == "paint":
        paintfile("save")
    elif option == "text":
        Choice("save")

def Printfilehandler(event):
    if option == "paint":
        paintfile("print")
    elif option == "text":
        Choice("print")

win.bind("<Control-S>", Savefilehandler)
win.bind("<Control-s>", Savefilehandler)

win.bind("<Control-p>", Printfilehandler)
win.bind("<Control-P>", Printfilehandler)

win.bind("<Button-3>", TextChange)
win.bind("<Escape>", TextChange)

imgCanvas = contentLabel.create_image(0, 0)
win.config(menu=menuBar)

win.mainloop()


import os
import re
import subprocess
from pathlib import Path

import pytest

from scargo.global_values import SCARGO_PKG_PATH

@pytest.fixture()
def create_tmp_directory(tmp_path: Path) -> None:
    os.chdir(tmp_path)

@pytest.fixture(scope="session")
def use_local_scargo() -> None:
    # This is necessary, so we can test latest changes in docker
    # Might be worth to rework with devpi later on
    scargo_repo_root = SCARGO_PKG_PATH.parent
    scargo_docker_env_name = "SCARGO_DOCKER_INSTALL_LOCAL"

    # If tests are run locally, wheel should be always rebuild to avoid using obsolete version
    # In case of running on CI, many workers should use the same version created earlier in workflow
    if "CI" in os.environ:
        if scargo_docker_env_name in os.environ:
            return
        else:
            raise KeyError(f"{scargo_docker_env_name} not found in the env variables")

    result = subprocess.run(
        ["flit", "build"],
        cwd=scargo_repo_root,
        check=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True,
    )
    match = re.search(r"Built\swheel:\s*(dist/scargo.*.whl)", result.stdout)
    assert match
    os.environ[scargo_docker_env_name] = match.group(1)


"""
This implementation of DEPSYM is copied directly from the code notebook in https://github.com/RakshaAg/DEPSYM.

Some code using StanzaLanguage have been modified as it is no longer supported in spacy-stanza v1.x.x.

SpaCy model is changed to use en_core_web_lg instead of en_core_web_sm

@inproceedings{depsym,
  author = {Chatterjee, Niladri and Agarwal, Raksha},
  title        = {DEPSYM: A Lightweight Syntactic Text Simplification Approach using Dependency Trees},
  booktitle    = {Proceedings of the First Workshop on Current Trends in Text Simplification (CTTS 2021), co-located with SEPLN 2021},
  year         = {2021},
  editor       = {Saggion, Horacio and Štajner, Sanja and Ferrés, Daniel and Kim Cheng Sheang},
  pages        = {42-56},
  month        = {09},
}
"""

import spacy
from spacy import displacy
import stanza
import spacy_stanza
from pattern.en import comparative, superlative, conjugate, INFINITIVE, PRESENT, PAST, FUTURE, pluralize
import truecase
import re
import textstat
import pattern

##### MONKEY PATCH OF PATTERN 3.6.0 #####
# Retrieved from https://github.com/clips/pattern/issues/308#issuecomment-1308344763
import os

from pattern.helpers import decode_string
from codecs import BOM_UTF8

from simplertimes.simplify.simplifier import AbstractSimplifier

BOM_UTF8 = BOM_UTF8.decode("utf-8")
decode_utf8 = decode_string

def _read(path, encoding="utf-8", comment=";;;"):
    """ Returns an iterator over the lines in the file at the given path,
        strippping comments and decoding each line to Unicode.
    """
    if path:
        if isinstance(path, str) and os.path.exists(path):
            # From file path.
            f = open(path, "r", encoding="utf-8")
        elif isinstance(path, str):
            # From string.
            f = path.splitlines()
        else:
            # From file or buffer.
            f = path
        for i, line in enumerate(f):
            line = line.strip(BOM_UTF8) if i == 0 and isinstance(line, str) else line
            line = line.strip()
            line = decode_utf8(line, encoding)
            if not line or (comment and line.startswith(comment)):
                continue
            yield line
    return
# The _read method uses old style of raising StopIteration
# Raising stop iteration breaks the code in newer Python versions
pattern.text._read = _read
##### MONKEY PATCH OF PATTERN 3.6.0 #####

def inorder_traversal(token, removed=None):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      if(child != removed):
        s = s + " " + inorder_traversal(child, removed)

  s = s + " " + token.text

  if(len(list(token.rights)) != 0):
    for child in token.rights:
      if(child != removed):
        s = s + " " + inorder_traversal(child, removed)
  return s

def inorder_traversal_2(token, removed):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      if(child not in removed):
        s = s + " " + inorder_traversal_2(child, removed)

  s = s + " " + token.text

  if(len(list(token.rights)) != 0):
    for child in token.rights:
      if(child not in removed):
        s = s + " " + inorder_traversal_2(child, removed)
  return s

def inorder_traversal_3(token, removed):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      if(child not in removed):
        s = s + " " + inorder_traversal_3(child, removed)
  if(token not in removed):
    s = s + " " + token.text

  if(len(list(token.rights)) != 0):
    for child in token.rights:
      if(child not in removed):
        s = s + " " + inorder_traversal_3(child, removed)
  return s

def left_subtree(token):
  if(len(list(token.lefts)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      s = s + " " + inorder_traversal(child)
  s = s + " " + token.text
  return s

def left_subtree_2(token, removed=None):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      if(child != removed):
        s = s + " " + inorder_traversal(child, removed)

  s = s + " " + token.text
  return s

def left_subtree_3(token, removed):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.lefts)) != 0):
    for child in token.lefts:
      if(child not in removed):
        s = s + " " + inorder_traversal_3(child, removed)

  if(token not in removed):
    s = s + " " + token.text
  return s

def right_subtree_3(token, removed):
  if(len(list(token.children)) == 0):
     return token.text
  s = ""
  if(len(list(token.rights)) != 0):
    for child in token.rights:
      if(child not in removed):
        s = s + " " + inorder_traversal_3(child, removed)

  if(token not in removed):
    s = s + " " + token.text
  return s

def get_root(doc):
  root  = None
  for token in doc:
    if(token.dep_ == "ROOT"):
      root = token
      return root

def get_root_stanza(doc):
  root  = None
  for token in doc:
    if(token.dep_ == "root"):
      root = token
      return root

def get_tag(token, tag):
  for child in token.children:
    if(child.dep_ == tag):
      return child

def find_in_subtree(token, tag):
  if(token == None):
     return
  if(token.tag_ == tag):
     return token
  for child in token.subtree:
    if(child.dep_ == tag):
      return child

def find_in_children(token, tag):
  if(token == None):
     return
  if(token.tag_ == tag):
     return token
  for child in token.children:
    if(child.dep_ == tag):
      return child

def pos_in_subtree(token, tag):
  if(token == None):
     return False
  if(token.pos_ == tag):
     return True
  for child in token.subtree:
    if(child.pos_ == tag):
      return True
  return False

def auxiliary_verb(verb, subj):
  if subj.tag_ in ("NN", "NNP"):
    if verb.tag_ in ("VBP", "VBZ", "VB"):
      aux = "is "
    elif verb.tag_ in ("VBD", "VBG", "VBN"):
      aux = "was "
    else:
      aux = "are "
  elif subj.tag_ in ("NNS", "NNPS"):
    if verb.tag_ in ("VBP", "VBZ", "VB"):
      aux = "are "
    elif verb.tag_ in ("VBD", "VBG", "VBN"):
      aux = "were "
    else:
      aux = "are "
  elif subj.tag_ in ("PRP") and subj.text.lower() == "they":
    if verb.tag_ in ("VBP", "VBZ", "VB") :
      aux = "are "
    elif verb.tag_ in ("VBD", "VBG", "VBN"):
      aux = "were "
  elif subj.tag_ in ("PRP"):
    if verb.tag_ in ("VBP", "VBZ", "VB"):
      aux = "is "
    elif verb.tag_ in ("VBD", "VBG", "VBN"):
      aux = "was "
  else:
      aux = "are "
  return aux

def remove_punct(s):
    s_list = list(s.split(" "))
    if(s_list[0] in ['?', '!', ',', ';', '.']):
        s_list[0] = ""
    for i in range(len(s_list)):
        if(len(s_list[i]) > 0 and (s_list[i][0] == "." or s_list[i][0] == ",")):
            s_list[i] = "."
    s = " ".join(c for c in s_list)
    fix_spaces = re.compile(r'\s*([?!.,]+(?:\s+[?!.,]+)*)\s*')
    s = fix_spaces.sub(lambda x: "{} ".format(x.group(1).replace(" ", "")), s)
    s = truecase.get_true_case(s)
    return s

# Share a global level nlp pipeline to avoid repeated instantiation
spacy_nlp = spacy.load("en_core_web_lg")

def appositive_simplification_2(comp_sent):
  # nlp = spacy.load("en_core_web_sm")
  doc = spacy_nlp(comp_sent)

  root = get_root(doc)
  subj = get_tag(root, "nsubj")

  apposcl = None

  apposcl = find_in_subtree(root, "appos")

  if(apposcl == None):
    apposcl = find_in_subtree(root, "amod")
    if(apposcl != None):
      if(apposcl.head.dep_ != "nsubj"):
        print("Appos: No simplification(no subject)")
        return False, comp_sent
    else:
      print("Appos: No simplification")
      return False, comp_sent

  appos_subj = apposcl.head

  appos_phrase = inorder_traversal(apposcl)
  aux_verb = str(auxiliary_verb(root, appos_subj))
  noun_phrase = left_subtree_2(appos_subj, apposcl)
  sentence1 = inorder_traversal(root, apposcl)
  sentence1 = ' '.join(sentence1.split(","))
  sentence1 = ' '.join(sentence1.split()) + "."

  sentence2 = noun_phrase + " " + aux_verb + appos_phrase
  sentence2 = ' '.join(sentence2.split(","))
  sentence2 = ' '.join(sentence2.split()) + "."

  sentence1 = remove_punct(sentence1)
  sentence2 = remove_punct(sentence2)

  print(sentence1)
  print(sentence2)
  return True, sentence1 + " " + sentence2

def rel_order(token):
  if(token.dep_ == "nsubj" or token.dep_ == "nsubjpass"):
    return True
  else:
    return False

def relative_clause_simplify(cmp_snt):
  # nlp = spacy.load("en_core_web_sm")
  doc = spacy_nlp(cmp_snt)
  root = get_root(doc)
  relcl = None
  relcl = find_in_subtree(root, "relcl")
  if(relcl == None):
    relcl = find_in_subtree(root, "rcmod")

  if(relcl == None):
    print("Relcl: No simplification")
    return False, cmp_snt

  subj = relcl.head

  rel_phrase = doc[relcl.left_edge.i : relcl.right_edge.i+1].text
  noun_phrase = left_subtree_2(subj, relcl)
  sentence1 = inorder_traversal(root, relcl)
  sentence1 = ' '.join(sentence1.split(","))
  sentence1 = ' '.join(sentence1.split()) + "."
  sentence2 = noun_phrase + " " + rel_phrase
  sentence2 = ' '.join(sentence2.split(","))
  sentence2 = ' '.join(sentence2.split())
  sentence2 = ' '.join(sentence2.split()) + "."

  sent1_doc = spacy_nlp(sentence1)
  sent1_root = get_root(sent1_doc)
  if(sent1_root.pos_ != "VERB" and sent1_root.pos_ != "AUX"):
    print("Relcl: No simplification")
    return False, cmp_snt

  order = rel_order(subj)

  sentence1 = remove_punct(sentence1)
  sentence2 = remove_punct(sentence2)

  if(not order):
    print(sentence1)
    print(sentence2)
    return True, sentence1 + " " + sentence2
  else:
    print(sentence2)
    print(sentence1)
    return True, sentence2 + " " + sentence1

def conjoint_clause_simplification(cmp_snt,Qnlp):
  cmp_snt = cmp_snt.rstrip(" ,.")
  print('the input is ',cmp_snt)
  doc = Qnlp(cmp_snt)
  root = get_root_stanza(doc)

  clause_type = None

  clause_type = find_in_children(root, "conj")
  if(clause_type == None):
    clause_type = find_in_children(root, "advcl")
  if(clause_type == None):
    clause_type = find_in_children(root, "parataxis")
  if(clause_type == None):
      clause_type = find_in_subtree(root, "conj")
  if(clause_type == None):
    clause_type = find_in_subtree(root, "advcl")
  if(clause_type == None):
    clause_type = find_in_subtree(root, "parataxis")
  if(clause_type == None):
    print("Conjoint: No simplification(no second clause found)")
    return False, cmp_snt

  clause_root = None

  if(clause_type.dep_ == "conj"):
    clause_root = find_in_subtree(root, "cc")
    if(clause_root != None):
      if((not pos_in_subtree(root, "VERB")) or (not (pos_in_subtree(clause_type, "VERB") or pos_in_subtree(clause_type, "AUX")))):
        print("Conjoint: No simplification 2(no verb in second clause)")
        return False, cmp_snt
    else:
      clause_root = find_in_children(clause_type, "advmod")
  elif(clause_type.dep_ == "advcl"):
    print("advcl")
    clause_root = find_in_children(clause_type, "mark")
    if(clause_root == None):
      clause_root = find_in_subtree(root, "mark")
    if(clause_root == None):
      clause_root = find_in_children(clause_type, "advmod")
    if(clause_root != None):
        if(clause_root.text == "to"):
            print("Conjoint: No simplification 3(no conjunction found)")
            return False, cmp_snt
  elif(clause_type.dep_ == "parataxis"):
    print("parataxis")
    clause_root = find_in_children(clause_type, "advmod")
  else:
    print("Conjoint: No simplification 3(no conjunction found)")
    return False, cmp_snt

  if(clause_root == None):
    print("Conjoint: No simplification 4")
    return False, cmp_snt

  clause_subj = None

  clause_subj = find_in_children(clause_type, "nsubj")
  if(clause_subj == None):
    clause_subj = find_in_children(clause_type, "nsubj:pass")
  clause_subj_flag = False
  if(clause_subj == None):
    clause_subj_flag = True
    clause_subj = find_in_children(root, "nsubj")
    if(clause_subj == None):
        clause_subj = find_in_children(root, "nsubj:pass")
    if(clause_subj == None):
        print("Conjoint: No simplification(no clause subject found)")
        return False, cmp_snt
    aux_str = ""
    for child in root.children:
        if(child.dep_ == "aux"):
            aux_str += child.text + " "
  modal = None
  if(clause_root.text.lower() in ['when', 'after', 'since', 'before', 'once']):
    modal = find_in_subtree(root, "aux")

  marker1 = ""
  marker2 = ""
  if(clause_root.text.lower() == "if"):
    marker1 = "Then"
    for child in root.subtree:
      if(child.text.lower() == "then"):
        marker1 = ""

  sentence1 = inorder_traversal_2(root, [clause_type, clause_root])

  sentence2 = ""
  marker2 = add_marker(clause_type, clause_root, modal) + " "
  if(clause_subj_flag):
    sentence2 = clause_subj.text + " " + aux_str + inorder_traversal(clause_type, clause_root)
  else:
    sentence2 = inorder_traversal(clause_type, clause_root)

  reverse = None

  if((root.i > clause_type.i) or (clause_root.text.lower() in ["because", "as"] and clause_root.i > 0)):
    if(clause_root.text.lower() in ['when', 'after', 'since', 'before', 'once'] and clause_root.i == 0):
      reverse = False
    else:
      reverse = True
  else:
    reverse = False

  if(clause_root.text.lower() in ["because", "as"] and clause_root.i > 0):
    sentence1 = marker2 + sentence1
    sentence2 = marker1 + sentence2
  else:
    sentence1 = marker1 + sentence1
    sentence2 = marker2 + sentence2

  s1 = remove_punct(sentence1)
  s2 = remove_punct(sentence2)
  exception_list = ["This happened", "This happens", "This was", "This is"]
  for c in ['when', 'after', 'since', 'before', 'once']:
        exception_list.append("This is " + c)
        exception_list.append("This was " + c)
        exception_list.append("This happens " + c)
        exception_list.append("This happened " + c)
        if(modal != None):
             exception_list.append('This ' + modal.text + ' happen ' + c)
  if(s1 in exception_list or s2 in exception_list):
        return False, cmp_snt

  if(reverse):
    print(sentence2)
    print(sentence1)
    return True, sentence2 + ". " + sentence1 + "."
  else:
    print(sentence1)
    print(sentence2)
    return True, sentence1 + ". " + sentence2 + "."

def add_marker(root, conj,  modal=None):
  conj_text = conj.text.lower()
  if(conj_text in ["and", "moreover"]):
    return "And"
  elif(conj_text == "if"):
    return "Suppose"
  elif(conj_text in ['though', 'although', 'but', 'whereas', 'however']):
    return "But"
  elif(conj_text in ['when', 'after', 'since', 'before', 'once']):
    if(conj.i > 0):
      if root.tag_ == 'VBP' or root.tag_ == 'VBZ' or root.tag_ == 'VB':
        return 'This is ' + conj_text + " "
      else:
        return 'This was ' + conj_text + " "
    else:
      if root.tag_ == 'VBP' or root.tag_ == 'VBZ':
        return 'This happens ' + conj_text + " "
      elif root.tag_ == 'VB' and modal != None:
        return 'This ' + modal.text + ' happen ' + conj_text + " "
      else:
        return 'This happened ' + conj_text + " "
  elif conj_text in ['because', 'so', 'while', "therefore"]:
    return 'So '
  elif conj_text in ["nevertheless", "nonetheless", "yet"]:
    return 'But'
  elif conj_text == "otherwise":
    return 'or'
  elif conj_text == "unless":
    return 'unless'
  else:
     return ""

def change_verb_form(verb, v_aux, auxpass, subj_tag, subj_word):
    word_list = v_aux.split()
    new_verb = ""
    modal_list = ["can", "could", "must", "should", "will", "would", "may", "might", "shall"]
    if ('will' in word_list or 'would' in word_list) and auxpass != "been":
      print("future simple")
      new_verb = v_aux + conjugate(verb, 'pl')
    elif auxpass == 'been':
      if 'will' in word_list or 'would' in word_list:
        print("future perfect")
        new_verb = v_aux + verb
      elif 'has' in word_list or 'have' in word_list:
        print("present perfect")
        if bool(set(word_list) & set(modal_list)):
            new_verb = v_aux + verb
        elif subj_tag in ("NNS", "NNPS") :
            new_verb = "have " + verb
        elif subj_tag in ("NN", "NNP"):
            new_verb = "has " + verb
        elif subj_tag in ("PRP") and subj_word.lower() in ("them", "me", "you"):
            new_verb = "have " + verb
        elif subj_tag in ("PRP") and subj_word.lower() in ("it", "her", "him"):
            new_verb = "has " + verb
        else:
            new_verb = v_aux + verb
      elif 'had' in word_list:
        print("past perfect")
        new_verb = v_aux + verb
    elif auxpass == "being":
      if('was' in word_list or 'were' in word_list):
        print("past continous")
        if subj_tag in ("NNS", "NNPS"):
            new_verb = "were " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("NN", "NNP"):
            new_verb = "was " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("PRP") and subj_word.lower() in ("them", "you"):
            new_verb = "were " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("PRP") and subj_word.lower() in ("me", "it", "her", "him"):
            new_verb = "was " + conjugate(verb, tense='present', aspect='progressive')
        else:
            new_verb = "was " + conjugate(verb, tense='present', aspect='progressive')
      else:
        print("present continous")
        if subj_tag in ("NNS", "NNPS"):
            new_verb = "are " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("NN", "NNP"):
            new_verb = "is " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("PRP") and subj_word.lower() in ("them", "you"):
            new_verb = "are " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("PRP") and subj_word.lower() in ("it", "her", "him"):
            new_verb = "is " + conjugate(verb, tense='present', aspect='progressive')
        elif subj_tag in ("PRP") and subj_word.lower() in ("me"):
            new_verb = "am " + conjugate(verb, tense='present', aspect='progressive')
        else:
            new_verb = "is " + conjugate(verb, tense='present', aspect='progressive')
    elif auxpass in ['was', 'were']:
      print("simple past")
      if subj_tag in ("NNS", "NNPS"):
        new_verb = conjugate(verb, 'ppl') + " "
      elif subj_tag in ("NN", "NNP"):
        new_verb = conjugate(verb, '3sgp') + " "
      elif subj_tag in ("PRP") and subj_word.lower() in ("them", "me", "you"):
        new_verb = conjugate(verb, 'ppl') + " "
      elif subj_tag in ("PRP") and subj_word.lower() in ("it", "her", "him"):
        new_verb = conjugate(verb, '3sgp') + " "
      else:
        new_verb = conjugate(verb, '3sgp') + " "
    else:
      print("simple present")
      if subj_tag in ("NNS", "NNPS"):
        new_verb = conjugate(verb, 'pl') + " "
      elif subj_tag in ("NN", "NNP"):
        new_verb = conjugate(verb, '3sg') + " "
      elif subj_tag in ("PRP") and subj_word.lower() in ("them", "me", "you"):
        new_verb = conjugate(verb, 'pl') + " "
      elif subj_tag in ("PRP") and subj_word.lower() in ("it", "her", "him"):
        new_verb = conjugate(verb, '3sg') + " "
      else:
        new_verb = conjugate(verb, '3sg') + " "

    return new_verb

def change_pronoun_object(word):
  pron_list = {'me':'I', 'you':'you', 'him':'he', 'her':'she', 'it':'it', 'them':'they', 'us':'we'}
  word_list = word.split()
  for i in range(len(word_list)):
    if(word_list[i] in pron_list.keys()):
        word_list[i] = pron_list[word_list[i]]
  return " ".join(str(e) for e in word_list)

def change_pronoun_subject(word):
  pron_list = {'i':'me', 'you':'you', 'he': 'him', 'she':'her', 'it':'it', 'they':'them', 'we':'us'}
  word_list = word.split()
  word_list = word.split()
  for i in range(len(word_list)):
    if(word_list[i].lower() in pron_list.keys()):
        word_list[i] = pron_list[word_list[i].lower()]
  return " ".join(str(e) for e in word_list)

def passive_simplify(cmp_snt):
    # nlp=spacy.load('en_core_web_sm')
    doc = spacy_nlp(cmp_snt)
    simplify_flag = False
    root = get_root(doc)
    auxpass = find_in_children(root, "auxpass")
    if(auxpass == None):
        print("No passive clause found")
        return simplify_flag, cmp_snt
    agent = find_in_children(root, "agent")
    if(agent == None):
        print("No agent found")
        return simplify_flag, cmp_snt
    subj = find_in_children(root, "nsubjpass")
    if(subj == None):
        print("No subject found")
        return simplify_flag, cmp_snt

    simplify_flag = True

    aux = find_in_children(root, "aux")

    aux_tense = auxpass.tag_
    if aux_tense == 'VB' and aux != None:
        aux_tense = aux.tag_
    elif aux_tense == 'VBN' and aux != None:
        if aux.text.lower() not in ("has", "have", "had"):
            aux_tense = 'MD'

    new_obj = inorder_traversal(subj)
    obj = find_in_children(agent, "pobj")
    new_subj = inorder_traversal(obj)
    removed_aux = []
    for child in root.children:
        if(child.dep_ == "aux"):
            removed_aux.append(child)

    left_of_subj = ""
    right_of_subj = ""
    left_of_obj = ""
    right_of_obj = ""

    flag = 0
    for child in root.lefts:
        if(child.dep_ == "nsubjpass"):
            flag = 1
            continue
        if(flag == 0 and child not in [root, subj, auxpass, agent] + removed_aux):
            left_of_subj += inorder_traversal(child) + " "
        elif(flag == 1 and child not in [root, subj, auxpass, agent] + removed_aux):
            right_of_subj += inorder_traversal(child) + " "

    flag = 0
    for child in root.rights:
        if(child.dep_ == "agent"):
            continue
        if(((child.dep_ == "prt" or child.dep_ == "prep") and (len(list(child.children)) == 0)) and child not in [root, subj, auxpass, agent] + removed_aux):
            left_of_obj += inorder_traversal(child) + " "
        elif(child not in [root, subj, auxpass, agent] + removed_aux):
            right_of_obj += inorder_traversal(child) + " "

    v_aux = ""
    if(aux != None):
        v_aux = aux.text
    aux_str = ""
    for child in root.children:
        if(child.dep_ == "aux"):
            aux_str += child.text + " "
    new_verb = change_verb_form(root.text, aux_str, auxpass.text, obj.tag_, obj.text)
    new_subj = change_pronoun_object(new_subj)
    new_obj = change_pronoun_subject(new_obj)
    final_sent = left_of_subj + " " + new_subj + " " + right_of_subj + " " + new_verb + " " + left_of_obj + " " + new_obj + " " + right_of_obj
    final_sent = ' '.join(final_sent.split())
    final_sent = truecase.get_true_case(final_sent)
    final_sent = remove_punct(final_sent)
    print(final_sent)
    return simplify_flag, final_sent

def simplify(snt,Qnlp):
    doc=Qnlp(snt)
    flag = False
    final_snt = ""
    for s in doc.sents:
        flag, simp_snt = appositive_simplification_2(s.text)
        if(flag == True):
            print(simp_snt)
            final_snt += (simplify(simp_snt,Qnlp) + " ")
            continue
        else:
            flag, simp_snt = conjoint_clause_simplification(s.text,Qnlp)
            if(flag == True):
                print(simp_snt)
                final_snt += (simplify(simp_snt,Qnlp) + " ")
                continue
            else:
                flag, simp_snt = relative_clause_simplify(s.text)
                if(flag == True):
                    final_snt += (simplify(simp_snt,Qnlp) + " ")
                    continue
                else:
                    flag, simp_snt = passive_simplify(s.text)
                    if(flag == True):
                        final_snt += (simplify(simp_snt,Qnlp) + " ")
                        continue
                    else:
                        final_snt += (simp_snt + " ")
    return final_snt

# Custom simplifier wrapper around the DEPSYM code
from nltk.tokenize import sent_tokenize
from typing import *
import os, contextlib # For silencing output. From https://stackoverflow.com/a/28321717
from ..utils import detokenize_for_output

class DEPSYMSimplifier(AbstractSimplifier):

    def __init__(self):
        # Will hold onto the Stanza NLP object
        # Reuse across simplifications because this is heavy to create
        self.Qnlp = None

    def simplify_documents(self, documents:Union[List[str], str]) -> Union[List[List[str]], List[List[Tuple[str,str]]]]:
        """Simplifies the documents given

        Args:
            documents : str | [str]
                The document(s) to simplify

        Returns:
            A list containing the simplified documents. `out[0]` gives the simplified documents.
            `out[1]` gives the complex-simple sentence pairs. Accessing complex-simple pairs will
            follow the format: `pairs[doc_idx][pair_idx][orig=0|simp=1]`
        """

        # Ensure list
        if isinstance(documents, str):
            documents = [documents]

        # Split a document to its individual sentences
        orig_sents = []
        for document in documents:
            # Split document into sentences using NLTK
            doc_sents = sent_tokenize(document, language='english')
            orig_sents.append(doc_sents)

        # Initialize stanza if not yet initialized
        if self.Qnlp is None:
            self.Qnlp = spacy_stanza.load_pipeline("en")

        # Create simplified predictions
        simp_docs = []
        simp_sents = []
        # For each document
        for doc_idx, doc_sents in enumerate(orig_sents):
            print(f"Simplifying document {doc_idx+1}")
            simp_doc_sents = []
            # Output silencing from https://stackoverflow.com/a/28321717
            with open(os.devnull, 'w') as devnull:
                with contextlib.redirect_stdout(devnull):
                    # For each sentence in the document
                    for comp_sent in doc_sents:
                        # Simplify the sentences
                        sentence = simplify(comp_sent, self.Qnlp)
                        # Fix formatting
                        sentence = detokenize_for_output(sentence)
                        simp_doc_sents.append(sentence)
            # Collect the simplified sentences per doument
            simp_docs.append(' '.join(simp_doc_sents))
            simp_sents.append(simp_doc_sents)

        # Create complex-simple sentence pairs
        orig_simp_pairs = []
        # For each doc that was processed
        for doc_idx in range(len(documents)):
            # Get all the orig and simplified sentences
            doc_orig_sents = orig_sents[doc_idx]
            doc_simp_sents = simp_sents[doc_idx]
            # Store as pair
            orig_simp_pairs.append([ (doc_orig_sents[sent_idx], doc_simp_sents[sent_idx] )
                                    for sent_idx in range(len(doc_orig_sents)) ])

        return simp_docs, orig_simp_pairs