From 2e3f84c8e402563a9c11850ad07d95f59cd43be3 Mon Sep 17 00:00:00 2001 From: Bobby Date: Sun, 6 Nov 2022 08:03:42 -0500 Subject: feat: window manager and file manager --- src/config/defaults.py | 4 +- src/helpers/managers.py | 50 +++++++++++++++++++++ src/helpers/preferences.py | 28 ------------ src/helpers/windows.py | 27 ++++++++++++ src/texty.py | 106 ++++++++++++++++++++++++++------------------- 5 files changed, 142 insertions(+), 73 deletions(-) create mode 100644 src/helpers/managers.py delete mode 100644 src/helpers/preferences.py create mode 100644 src/helpers/windows.py (limited to 'src') diff --git a/src/config/defaults.py b/src/config/defaults.py index 557ea61..f0da742 100644 --- a/src/config/defaults.py +++ b/src/config/defaults.py @@ -14,7 +14,8 @@ KEYBINDS = { "Open File": f"meta-O", # Open File "Save": f"meta-S", # Save "Save As": f"meta-Shift-S", # Save As - "Close": f"meta-W", # Close + "Close Tab": f"meta-W", # Close Tab + "Close": f"Alt-F4", # Close "Quit": f"meta-Q", # Quit "Undo": f"meta-Z", # Undo "Redo": f"meta-Shift-Z", # Redo @@ -36,6 +37,7 @@ KEYBINDS = { MAC_KEYBINDS = { "Preferences": f"meta-,", # Preferences + "Close Window": f"meta-Shift-W", # Close Window "Hide Texty": f"meta-H", # Hide Texty "Hide Others": f"meta-Shift-H", # Hide Others "Show All": f"meta-Shift-A", # Show All diff --git a/src/helpers/managers.py b/src/helpers/managers.py new file mode 100644 index 0000000..518762c --- /dev/null +++ b/src/helpers/managers.py @@ -0,0 +1,50 @@ +import json +import os + + +class PreferenceManager: + def __init__(self, default_prefs, preferences_file): + self.DEFAULT_PREFS, self.preferences = default_prefs, default_prefs + self.preferences_file = preferences_file + self.load() + + def load(self): + if os.path.exists(self.preferences_file): + with open(self.preferences_file, "r") as f: + self.preferences = json.load(f) + + def save(self): + with open(self.preferences_file, "w") as f: + json.dump(self.preferences, f) + + def get(self, key): + return self.preferences[key] + + def set(self, key, value): + self.preferences[key] = value + + def reset(self): + self.preferences = self.DEFAULT_PREFS + self.save() + + +class FileManager: + # keeps track of all open files and their contents + def __init__(self): + self.files = {} + + def open_file(self, path): + # open a file and store it in the files dict + with open(path, "r") as f: + contents = f.read() + self.files[path] = contents + + def save_file(self, path, contents): + # save a file + self.files[path] = contents + with open(path, "w") as f: + f.write(contents) + + def close_file(self, path): + # close a file + del self.files[path] diff --git a/src/helpers/preferences.py b/src/helpers/preferences.py deleted file mode 100644 index f190eeb..0000000 --- a/src/helpers/preferences.py +++ /dev/null @@ -1,28 +0,0 @@ -import json -import os - - -class PreferenceManager: - def __init__(self, default_prefs, preferences_file): - self.DEFAULT_PREFS, self.preferences = default_prefs, default_prefs - self.preferences_file = preferences_file - self.load() - - def load(self): - if os.path.exists(self.preferences_file): - with open(self.preferences_file, "r") as f: - self.preferences = json.load(f) - - def save(self): - with open(self.preferences_file, "w") as f: - json.dump(self.preferences, f) - - def get(self, key): - return self.preferences[key] - - def set(self, key, value): - self.preferences[key] = value - - def reset(self): - self.preferences = self.DEFAULT_PREFS - self.save() diff --git a/src/helpers/windows.py b/src/helpers/windows.py new file mode 100644 index 0000000..fc2ebbf --- /dev/null +++ b/src/helpers/windows.py @@ -0,0 +1,27 @@ +import tkinter as tk + + +class TextyWindow(tk.Toplevel): + def __init__(self, parent): + super().__init__(parent) + self.parent = parent + self.tabs = [] + geometry = self.parent.get_window_geometry() + self.geometry(geometry) + self.protocol("WM_DELETE_WINDOW", self.on_close) + + self.option_add("*tearOff", False) + self.parent.log("Tearoff disabled") + + # Bind Resize, Move, and Close + self.bind("", self.parent.save_prefs) + self.bind("", self.parent.save_prefs) + self.parent.log("Resize, Move, and Close bindings set to save preferences.") + + self.config(menu=self.parent.get_menubar()) + + def on_close(self): + if self.parent.system == "aqua": + self.destroy() + else: + self.quit() diff --git a/src/texty.py b/src/texty.py index 3b043e5..5e847a5 100644 --- a/src/texty.py +++ b/src/texty.py @@ -9,9 +9,8 @@ import tkinter as tk import click from config.defaults import DEFAULT_PREFS, KEYBINDS, MAC_KEYBINDS, PREFERENCES_FILE -from helpers.preferences import PreferenceManager - -logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) +from helpers.managers import FileManager, PreferenceManager +from helpers.windows import TextyWindow class Texty(tk.Tk): @@ -20,29 +19,24 @@ class Texty(tk.Tk): self.title("Texty") self.debug = debug self.prefs = PreferenceManager(DEFAULT_PREFS, PREFERENCES_FILE) - self.protocol("WM_DELETE_WINDOW", self.on_close) + self.fm = FileManager() self.system = self.call("tk", "windowingsystem") - self.log("Running Texty on %s" % self.system) - - self.option_add("*tearOff", False) - self.log("Tearoff disabled") - - # Bind Resize, Move, and Close - self.bind("", self.save_prefs) - self.bind("", self.save_prefs) - self.log("Resize, Move, and Close bindings set to save preferences.") - - # Set Geometry - self.set_geometry() + self.log( + "Running Texty on system: {}, platform: {}".format( + self.system, sys.platform + ) + ) - # Create Menu Bar - self.bind_menu() + self.withdraw() + self.create_window() - def log(self, message): - if self.debug: - logging.info(message) + def create_window(self): + window = TextyWindow(self) + window.grab_set() + window.focus_set() + window.mainloop() - def set_geometry(self): + def get_window_geometry(self): width = self.prefs.get("width") height = self.prefs.get("height") x_pos = ( @@ -55,27 +49,21 @@ class Texty(tk.Tk): if self.prefs.get("y_pos") == "center" else self.prefs.get("y_pos") ) - self.geometry(f"{width}x{height}+{x_pos}+{y_pos}") self.log( "Window geometry set to {}x{}+{}+{}".format(width, height, x_pos, y_pos) ) + return f"{width}x{height}+{x_pos}+{y_pos}" - def save_prefs(self, event): - if not self.debug: - self.prefs.set("width", self.winfo_width()) - self.prefs.set("height", self.winfo_height()) - self.prefs.set("x_pos", self.winfo_x()) - self.prefs.set("y_pos", self.winfo_y()) - self.prefs.save() - - def bind_menu(self): + def get_menubar(self): menubar = tk.Menu(self) + # Setting Keybinds meta = "Command" if self.system == "aqua" else "Control" keybinds = {k: v.replace("meta", meta) for k, v in KEYBINDS.items()} mac_keybinds = {k: v.replace("meta", meta) for k, v in MAC_KEYBINDS.items()} self.log("Keybinds set to %s" % keybinds) + # macOS specific menu items if self.system == "aqua": self.log("MacOS detected, Additional Keybinds set to %s" % mac_keybinds) appmenu = tk.Menu(menubar, name="apple") @@ -83,28 +71,58 @@ class Texty(tk.Tk): appmenu.add_command(label="About Texty") appmenu.add_separator() self.createcommand("tk::mac::ShowPreferences", self.show_preferences) + appmenu.add_separator() - self.config(menu=menubar) + # File Menu + filemenu = tk.Menu(menubar) + menubar.add_cascade(menu=filemenu, label="File") + filemenu.add_command( + label="New Text File", accelerator=keybinds["New Text File"] + ) + filemenu.add_command(label="New Window", accelerator=keybinds["New Window"]) + # filemenu.add_command(label="New Tab", accelerator=keybinds["New Tab"]) + filemenu.add_separator() + filemenu.add_command(label="Open File", accelerator=keybinds["Open File"]) + filemenu.add_command(label="Save", accelerator=keybinds["Save"]) + filemenu.add_command(label="Save As", accelerator=keybinds["Save As"]) + filemenu.add_separator() + # filemenu.add_command(label="Close Tab", accelerator=keybinds["Close Tab"]) + if self.system == "aqua": + filemenu.add_command( + label="Close Window", accelerator=mac_keybinds["Close Window"] + ) + else: + filemenu.add_command(label="Quit", accelerator=keybinds["Close"]) + + # Configure Menubar for the current window + return menubar + + # Event Logger + def log(self, message): + if self.debug: + logging.info(message) + + # Save Preferences + def save_prefs(self, event): + if not self.debug: + self.prefs.set("width", self.winfo_width()) + self.prefs.set("height", self.winfo_height()) + self.prefs.set("x_pos", self.winfo_x()) + self.prefs.set("y_pos", self.winfo_y()) + self.prefs.save() def show_preferences(self): print("Show Preferences") - def on_close(self): - if self.system == "aqua": - self.destroy() - else: - self.quit() - @click.command() @click.option("--debug", is_flag=True, help="Enable debug mode.") -def main(debug): +def runtexty(debug): + logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) if debug: logging.info("Running in debug mode. Preferences will not be saved.") - texty = Texty(debug=debug) - texty.protocol("WM_DELETE_WINDOW", texty.on_close) - texty.mainloop() + Texty(debug=debug) if __name__ == "__main__": - main() + runtexty() -- cgit v1.2.3