Skip to content

Commit dfd76d0

Browse files
authored
Update source_file.py
v1.3
1 parent d8352b7 commit dfd76d0

File tree

1 file changed

+82
-58
lines changed

1 file changed

+82
-58
lines changed

source_file.py

Lines changed: 82 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,74 @@
22
from tkinter import ttk
33
from tkinter.messagebox import showinfo
44
from tkinter.filedialog import askopenfilename, asksaveasfilename
5-
from tkinter.simpledialog import askstring
65
import os
7-
#1.2
6+
from tkinter.simpledialog import askstring
7+
import sys
8+
89
class NotePy:
910
def __init__(self, **kwargs):
11+
# Initialize main window
1012
self.__root = tk.Tk()
1113
self.__root.title("Untitled - NotePy")
1214

15+
# Set window size
1316
self.__thisWidth = kwargs.get('width', 600)
14-
self.__thisHeight = kwargs.get('height', 600)
17+
self.__thisHeight = kwargs.get('height', 460)
1518

19+
# Center the window
1620
screenWidth = self.__root.winfo_screenwidth()
1721
screenHeight = self.__root.winfo_screenheight()
1822
left = (screenWidth / 2) - (self.__thisWidth / 2)
1923
top = (screenHeight / 2) - (self.__thisHeight / 2)
2024
self.__root.geometry(f'{self.__thisWidth}x{self.__thisHeight}+{int(left)}+{int(top)}')
2125

26+
# Set icon (use a placeholder or remove if not available)
2227
try:
23-
self.__root.iconbitmap("Notepad.ico")
28+
self.__root.iconbitmap("NotePy.ico")
2429
except tk.TclError:
2530
pass
2631

32+
# Create a frame for the text area and scrollbar
2733
self.__mainFrame = ttk.Frame(self.__root)
2834
self.__mainFrame.grid(sticky='nsew')
2935

36+
# Create a frame for the status bar
3037
self.__statusFrame = ttk.Frame(self.__root)
3138
self.__statusFrame.grid(row=1, column=0, sticky='ew')
3239

40+
# Create a text area with a scrollbar
3341
self.__thisTextArea = tk.Text(self.__mainFrame, wrap='word', font=('Arial', 12))
3442
self.__thisScrollBar = ttk.Scrollbar(self.__mainFrame, orient='vertical', command=self.__thisTextArea.yview)
3543
self.__thisTextArea.config(yscrollcommand=self.__thisScrollBar.set)
3644

45+
# Pack widgets into the main frame
3746
self.__thisTextArea.grid(row=0, column=0, sticky='nsew')
3847
self.__thisScrollBar.grid(row=0, column=1, sticky='ns')
3948

49+
# Configure row and column weights
4050
self.__mainFrame.grid_rowconfigure(0, weight=1)
4151
self.__mainFrame.grid_columnconfigure(0, weight=1)
4252

53+
# Status bar elements
4354
self.__statusBar = tk.Label(self.__statusFrame, text="Ln 1 | Col 1 | 100% | CRLF | UTF-8", anchor='w')
4455
self.__statusBar.grid(row=0, column=0, sticky='ew')
4556

57+
# Create menu bar
4658
self.__thisMenuBar = tk.Menu(self.__root)
4759
self.__root.config(menu=self.__thisMenuBar)
4860

61+
# File menu
4962
self.__thisFileMenu = tk.Menu(self.__thisMenuBar, tearoff=0)
5063
self.__thisFileMenu.add_command(label="New", command=self.__newFile, accelerator="Ctrl+N")
64+
self.__thisFileMenu.add_command(label="New Window", command=self.__newWindow, accelerator="Ctrl+Shift+N")
5165
self.__thisFileMenu.add_command(label="Open", command=self.__openFile, accelerator="Ctrl+O")
5266
self.__thisFileMenu.add_command(label="Save", command=self.__saveFile, accelerator="Ctrl+S")
67+
self.__thisFileMenu.add_command(label="Save As", command=self.__saveAsFile, accelerator="Ctrl+Shift+S")
5368
self.__thisFileMenu.add_separator()
5469
self.__thisFileMenu.add_command(label="Exit", command=self.__quitApplication, accelerator="Ctrl+Q")
5570
self.__thisMenuBar.add_cascade(label="File", menu=self.__thisFileMenu)
5671

72+
# Edit menu
5773
self.__thisEditMenu = tk.Menu(self.__thisMenuBar, tearoff=0)
5874
self.__thisEditMenu.add_command(label="Cut", command=self.__cut, accelerator="Ctrl+X")
5975
self.__thisEditMenu.add_command(label="Copy", command=self.__copy, accelerator="Ctrl+C")
@@ -62,42 +78,59 @@ def __init__(self, **kwargs):
6278
self.__thisEditMenu.add_command(label="Redo", command=self.__redo, accelerator="Ctrl+Y")
6379
self.__thisEditMenu.add_command(label="Find", command=self.__findReplace, accelerator="Ctrl+F")
6480
self.__thisEditMenu.add_command(label="Replace", command=self.__findReplace, accelerator="Ctrl+H")
81+
self.__thisEditMenu.add_command(label="Select All", command=self.__selectAll, accelerator="Ctrl+A")
6582
self.__thisMenuBar.add_cascade(label="Edit", menu=self.__thisEditMenu)
6683

84+
# Format menu
6785
self.__thisFormatMenu = tk.Menu(self.__thisMenuBar, tearoff=0)
6886
self.__thisFormatMenu.add_command(label="Font Size", command=self.__setFontSize)
6987
self.__thisFormatMenu.add_command(label="Font Style", command=self.__setFontStyle)
7088
self.__thisMenuBar.add_cascade(label="Format", menu=self.__thisFormatMenu)
7189

90+
# Help menu
7291
self.__thisHelpMenu = tk.Menu(self.__thisMenuBar, tearoff=0)
7392
self.__thisHelpMenu.add_command(label="About NotePy", command=self.__showAbout)
7493
self.__thisMenuBar.add_cascade(label="Help", menu=self.__thisHelpMenu)
7594

95+
# Initialize file variable
7696
self.__file = None
7797
self.__line_endings = "CRLF"
7898
self.__encoding = "UTF-8"
7999

100+
# Bind events
80101
self.__thisTextArea.bind('<KeyRelease>', self.__updateStatusBar)
81102
self.__root.bind_all('<Control-n>', lambda e: self.__newFile())
103+
self.__root.bind_all('<Control-N>', lambda e: self.__newWindow())
82104
self.__root.bind_all('<Control-o>', lambda e: self.__openFile())
83105
self.__root.bind_all('<Control-s>', lambda e: self.__saveFile())
106+
self.__root.bind_all('<Control-S>', lambda e: self.__saveAsFile())
84107
self.__root.bind_all('<Control-q>', lambda e: self.__quitApplication())
85108
self.__root.bind_all('<Control-x>', lambda e: self.__cut())
86109
self.__root.bind_all('<Control-c>', lambda e: self.__copy())
87110
self.__root.bind_all('<Control-v>', lambda e: self.__paste())
88111
self.__root.bind_all('<Control-z>', lambda e: self.__undo())
89112
self.__root.bind_all('<Control-y>', lambda e: self.__redo())
113+
self.__root.bind_all('<Control-a>', lambda e: self.__selectAll())
90114
self.__root.bind_all('<Control-f>', lambda e: self.__findReplace())
91115
self.__root.bind_all('<Control-h>', lambda e: self.__findReplace())
92116

117+
# Open file if provided as an argument (for "Open with NotePy" functionality)
118+
if len(sys.argv) > 1:
119+
self.__file = sys.argv[1]
120+
self.__openFile(initial_open=True)
121+
122+
def __newWindow(self):
123+
os.system(f'python "{__file__}"')
124+
93125
def __quitApplication(self):
94126
self.__root.destroy()
95127

96128
def __showAbout(self):
97129
showinfo("NotePy", "Having trust issue with Microsoft Products? Here you are, a FREE and OPEN SOURCE Notepad created in Python! Created by: Long Do (http://longdo.pythonanywhere.com/)")
98130

99-
def __openFile(self):
100-
self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")])
131+
def __openFile(self, initial_open=False):
132+
if not initial_open:
133+
self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")])
101134
if self.__file:
102135
self.__root.title(os.path.basename(self.__file) + " - NotePy")
103136
self.__thisTextArea.delete(1.0, tk.END)
@@ -113,12 +146,18 @@ def __newFile(self):
113146

114147
def __saveFile(self):
115148
if self.__file is None:
116-
self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")])
149+
self.__saveAsFile()
150+
else:
151+
with open(self.__file, "w", encoding=self.__encoding) as file:
152+
file.write(self.__thisTextArea.get(1.0, tk.END))
153+
self.__root.title(os.path.basename(self.__file) + " - NotePy")
154+
155+
def __saveAsFile(self):
156+
self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")])
117157
if self.__file:
118158
with open(self.__file, "w", encoding=self.__encoding) as file:
119159
file.write(self.__thisTextArea.get(1.0, tk.END))
120160
self.__root.title(os.path.basename(self.__file) + " - NotePy")
121-
self.__updateStatusBar()
122161

123162
def __cut(self):
124163
self.__thisTextArea.event_generate("<<Cut>>")
@@ -130,70 +169,55 @@ def __paste(self):
130169
self.__thisTextArea.event_generate("<<Paste>>")
131170

132171
def __undo(self):
133-
self.__thisTextArea.event_generate("<<Undo>>")
172+
try:
173+
self.__thisTextArea.edit_undo()
174+
except tk.TclError:
175+
pass
134176

135177
def __redo(self):
136-
self.__thisTextArea.event_generate("<<Redo>>")
178+
try:
179+
self.__thisTextArea.edit_redo()
180+
except tk.TclError:
181+
pass
137182

138183
def __findReplace(self):
139-
findReplaceWindow = tk.Toplevel(self.__root)
140-
findReplaceWindow.title("Find and Replace")
141-
tk.Label(findReplaceWindow, text="Find:").grid(row=0, column=0, sticky='e')
142-
findEntry = tk.Entry(findReplaceWindow, width=30)
143-
findEntry.grid(row=0, column=1, padx=5, pady=5)
144-
tk.Label(findReplaceWindow, text="Replace with:").grid(row=1, column=0, sticky='e')
145-
replaceEntry = tk.Entry(findReplaceWindow, width=30)
146-
replaceEntry.grid(row=1, column=1, padx=5, pady=5)
147-
tk.Button(findReplaceWindow, text="Find", command=lambda: self.__find(findEntry.get())).grid(row=2, column=0, padx=5, pady=5)
148-
tk.Button(findReplaceWindow, text="Replace", command=lambda: self.__replace(findEntry.get(), replaceEntry.get())).grid(row=2, column=1, padx=5, pady=5)
149-
tk.Button(findReplaceWindow, text="Cancel", command=findReplaceWindow.destroy).grid(row=2, column=2, padx=5, pady=5)
150-
151-
def __find(self, search_text):
152-
content = self.__thisTextArea.get(1.0, tk.END)
153-
index = content.find(search_text)
154-
if index != -1:
155-
self.__thisTextArea.mark_set("insert", f"1.0+{index}c")
156-
self.__thisTextArea.see("insert")
157-
158-
def __replace(self, search_text, replace_text):
159-
content = self.__thisTextArea.get(1.0, tk.END)
160-
new_content = content.replace(search_text, replace_text)
184+
find_what = askstring("Find", "Enter text to find:")
185+
replace_with = askstring("Replace", "Replace with (leave empty to skip):")
186+
187+
text_content = self.__thisTextArea.get(1.0, tk.END)
161188
self.__thisTextArea.delete(1.0, tk.END)
162-
self.__thisTextArea.insert(1.0, new_content)
189+
190+
if replace_with:
191+
text_content = text_content.replace(find_what, replace_with)
192+
193+
self.__thisTextArea.insert(1.0, text_content)
194+
self.__updateStatusBar()
195+
196+
def __selectAll(self):
197+
self.__thisTextArea.tag_add('sel', '1.0', 'end')
163198

164199
def __setFontSize(self):
165200
size = askstring("Font Size", "Enter font size:")
166-
if size:
167-
try:
168-
size = int(size)
169-
current_font = self.__thisTextArea.cget("font")
170-
font_family, font_size = current_font.rsplit(' ', 1)
171-
self.__thisTextArea.config(font=(font_family, size))
172-
except ValueError:
173-
showinfo("Error", "Invalid font size.")
201+
if size and size.isdigit():
202+
self.__thisTextArea.config(font=("Arial", int(size)))
174203

175204
def __setFontStyle(self):
176-
font_style = askstring("Font Style", "Enter font style (e.g., Arial, Courier):")
177-
if font_style:
178-
current_font = self.__thisTextArea.cget("font")
179-
font_family, font_size = current_font.rsplit(' ', 1)
180-
self.__thisTextArea.config(font=(font_style, font_size))
205+
style = askstring("Font Style", "Enter font style (e.g., bold, italic):")
206+
if style:
207+
current_font = self.__thisTextArea['font'].split()
208+
if len(current_font) > 1:
209+
current_font[-1] = style
210+
else:
211+
current_font.append(style)
212+
self.__thisTextArea.config(font=" ".join(current_font))
181213

182214
def __updateStatusBar(self, event=None):
183-
content = self.__thisTextArea.get(1.0, tk.END)
184-
num_lines = int(self.__thisTextArea.index('end-1c').split('.')[0])
185-
num_cols = len(self.__thisTextArea.get(tk.INSERT + " linestart", tk.INSERT))
186-
num_words = len(content.split())
187-
188-
line, col = map(int, self.__thisTextArea.index(tk.INSERT).split('.'))
189-
line_endings = self.__line_endings
190-
encoding = self.__encoding
191-
192-
self.__statusBar.config(text=f"Ln {line} | Col {col} | {num_words} Words | {line_endings} | {encoding}")
215+
line, column = self.__thisTextArea.index(tk.INSERT).split('.')
216+
self.__statusBar.config(text=f"Ln {line} | Col {column} | 100% | {self.__line_endings} | {self.__encoding}")
193217

194218
def run(self):
195219
self.__root.mainloop()
196220

197-
if __name__ == "__main__":
198-
app = NotePy(width=600, height=460)
221+
if __name__ == '__main__':
222+
app = NotePy()
199223
app.run()

0 commit comments

Comments
 (0)