From 3c58b5c0c248d6fed81e2f2c0fa0188f2f929d18 Mon Sep 17 00:00:00 2001 From: Klemek Date: Fri, 27 Aug 2021 10:56:36 +0200 Subject: [PATCH] more menu actions --- watchy-image-editor/app.py | 58 ++++++++++++++++++++++++------ watchy-image-editor/explorer.py | 29 +++++++++++++-- watchy-image-editor/image.py | 2 +- watchy-image-editor/input_popup.py | 26 ++++++++++++++ 4 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 watchy-image-editor/input_popup.py diff --git a/watchy-image-editor/app.py b/watchy-image-editor/app.py index 33a6619..a1b5a2c 100644 --- a/watchy-image-editor/app.py +++ b/watchy-image-editor/app.py @@ -1,14 +1,15 @@ import tkinter as tk -from tkinter import ttk, filedialog +from tkinter import ttk, filedialog, messagebox from typing import Optional from enum import Enum import os.path from explorer import Explorer from image_view import ImageView +from input_popup import InputPopup from file import File from image import Image -from bitmap import Bitmap +from bitmap import Bitmap, BitmapError class MenuEntryType(Enum): @@ -32,16 +33,16 @@ class App(ttk.Frame): "New image...", "_file_new_image", MenuEntryType.NEED_FILE, - ), # TODO _file_new_image + ), ("", "", MenuEntryType.SEPARATOR), - ("Quit", "_file_quit", MenuEntryType.DEFAULT), # TODO _file_quit + ("Quit", "_file_quit", MenuEntryType.DEFAULT), ], "Image": [ ( "Edit Image Name...", "_image_edit_name", MenuEntryType.NEED_IMAGE, - ), # TODO _image_edit_name + ), ( "Edit Image Size...", "_image_edit_size", @@ -51,17 +52,17 @@ class App(ttk.Frame): "Move Image Up", "_image_move_up", MenuEntryType.NEED_IMAGE, - ), # TODO _image_move_up + ), ( "Move Image Down", "_image_move_down", MenuEntryType.NEED_IMAGE, - ), # TODO _image_move_down + ), ( "Delete Image", "_image_delete", MenuEntryType.NEED_IMAGE, - ), # TODO _image_delete + ), ], "Bitmap": [ ( @@ -234,15 +235,50 @@ class App(ttk.Frame): def _file_close(self) -> None: self.open_file(None) + def _file_new_image(self) -> None: + popup = InputPopup( + self, + title="New image", + message="Please enter image name", + ) + if popup.value: + self.current_file.images += [Image(popup.value, 20, 20, empty=True)] + self.update() + + def _file_quit(self) -> None: + self.parent.destroy() + + def _image_edit_name(self) -> None: + popup = InputPopup( + self, + title="Edit image name", + message="Please enter image name", + initial_value=self.explorer.current_image.name, + ) + if popup.value: + self.explorer.current_image.name = popup.value + self.update() + + def _image_move_up(self) -> None: + self.explorer.move_up() + + def _image_move_down(self) -> None: + self.explorer.move_down() + + def _image_delete(self) -> None: + self.explorer.delete() + def _bmp_import_image(self) -> None: path = filedialog.askopenfilename( filetypes=Bitmap.FILE_TYPES, defaultextension=Bitmap.FILE_TYPES, ) if path: - # TODO error handling - self.current_image.import_bmp(path) - self.update() + try: + self.current_image.import_bmp(path) + self.update() + except BitmapError as e: + messagebox.showerror(title="Bitmap import error", message=str(e)) def _bmp_export_image(self) -> None: path = filedialog.asksaveasfilename( diff --git a/watchy-image-editor/explorer.py b/watchy-image-editor/explorer.py index a0db1e6..bdb3862 100644 --- a/watchy-image-editor/explorer.py +++ b/watchy-image-editor/explorer.py @@ -16,8 +16,8 @@ class Explorer(ttk.Frame): self.explorer = ttk.Treeview(self, columns=("size")) self.explorer.heading("#0", text="name") self.explorer.heading("size", text="size") - self.explorer.column("#0", width=100, anchor="w") - self.explorer.column("size", width=100, anchor="w") + self.explorer.column("#0", width=150, anchor="w") + self.explorer.column("size", width=80, anchor="w") self.explorer.grid(row=0, column=0, sticky="nsw") self.explorer.bind("<>", self.explorer_item_click) @@ -47,6 +47,29 @@ class Explorer(ttk.Frame): self.current_id = id self.explorer.selection_set(str(id)) + def move_up(self) -> None: + if self.current_id > 0: + id = self.current_id + images = self.current_file.images + images[id], images[id - 1] = images[id - 1], images[id] + self.current_id -= 1 + self.focus(self.current_id) + self.update(self.current_file, False) + + def move_down(self) -> None: + if self.current_id < self.size - 1: + id = self.current_id + images = self.current_file.images + images[id], images[id + 1] = images[id + 1], images[id] + self.current_id += 1 + self.focus(self.current_id) + self.update(self.current_file, False) + + def delete(self) -> None: + del self.current_file.images[self.current_id] + self.current_id = min(self.current_id, self.size - 1) + self.update(self.current_file, True) + def update(self, file: File, force: bool): focus_id = self.current_id @@ -77,7 +100,7 @@ class Explorer(ttk.Frame): text=f"{image.name}{'*' if image.modified else ''}", values=[f"{image.width}x{image.height}"], ) - if self.size > 0 and focus_id != self.current_id: + if self.size > 0 and (focus_id != self.current_id or force): self.focus(focus_id) def explorer_item_click(self, event) -> None: diff --git a/watchy-image-editor/image.py b/watchy-image-editor/image.py index 7a35a28..be01d23 100644 --- a/watchy-image-editor/image.py +++ b/watchy-image-editor/image.py @@ -11,7 +11,7 @@ class Image: self.height = height self.modified = False if empty: - self.data = [0] * (width * height) // 8 + self.data = [0] * ((width * height) // 8) self.modified = True else: self.data = [] diff --git a/watchy-image-editor/input_popup.py b/watchy-image-editor/input_popup.py new file mode 100644 index 0000000..4ecb54c --- /dev/null +++ b/watchy-image-editor/input_popup.py @@ -0,0 +1,26 @@ +import tkinter as tk +from tkinter import ttk + + +class InputPopup(tk.Toplevel): + def __init__(self, parent, *, title: str, message: str, initial_value: str = ""): + super().__init__(parent) + self.title(title) + + self.value = None + + label = ttk.Label(self, text=message) + label.pack() + + self.entry = ttk.Entry(self) + self.entry.insert(0, initial_value) + self.entry.pack() + + button = ttk.Button(self, text="Ok", command=self.cleanup) + button.pack() + + parent.wait_window(self) + + def cleanup(self): + self.value = self.entry.get() + self.destroy() \ No newline at end of file