From cfb4dabbd5467d63d7b7d9621ad74c6e34ade152 Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 12:31:36 -0500 Subject: [PATCH 1/6] Fix clock icon and add tooltip --- Assets/Icons/clock.png | Bin 1532 -> 4010 bytes toolbar.py | 14 ++++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Assets/Icons/clock.png b/Assets/Icons/clock.png index 3c01ef4ce28317c2c921a3b8fce1f786c6ca9299..1dc7adf9258c885836906810bf16eaf81e921238 100644 GIT binary patch literal 4010 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 literal 1532 zcmX|Bdr(w$7`?2>Z$FTa%NHufLlzf8QN)R{MSSdCu6Qqxb&&;SKo&PbeBpvCzGcUV zWwmrgM5iK%Oc|YgrITYrf{+rKiIR^-6G=tM2boQc`RH0rXXeZ~-}!yNf6gDD%VeD4 z>;0-X$8o;0B+lYE54A#24^k3~T`p3@W7(`325$e^;JeD;IbTQhNmv5Y*yS8qQv3kXd@^UFP4V~@X z_iWM`^c(5tx^m;!(ar4^XJ6kvdJ%j$<>`u!aU~Dj*}dmA2ilJ&X1Q{lAJQTm5pgl( zk-Rv*VB6)gj)+5jZrOTWvqk(yvq`+7afbX711AJO*x_yYm1guMR)b{ znT^*pyTvVuqHC&iB{gH0_DP6Uepe?}2QI4`HKCuMZoR6htf)xzgb{2#jAmsJ&x%22 zg^WaW`_i}7*bdP z=#LTdUrGg(5VI-Rj<5?U`V`E_^(}INs!%`LiE-mU#PI0*i+tSPzCm0YZX<) zd(X5QRKt2tw(3Y0uREIaT$3r&ALv$6@fu(Bgggbna z^|Gd_!jY&3e-hjHL${MjZ0Q zBS&HQfMW41>2W`qa5Lp&G1<^a4vZl;A~oP`I*6yJ1$WaqtfU?+qybDKPmH7h^dc?x zQyg}Zhs*nk{y$&0>@AddebiKr6YKf+Od(kaRc2%D?LU7c?64EgHA1ZmIT(S ze~yjv@0cfr*R(mrSZA@zhIQl-a$IYeWS2ab7uBkNITz)B`C~c!NaEX~&AHGufZGXz z_iAV9%#yYwDtT8)l%y@ayj{9=aMac_^D@Hg+A2kZGt*Ur(IkfyYtK*0m9=HZ+|qqp z dict[str, tk.PhotoImage | None]: """ @@ -123,7 +124,7 @@ def load_images(self) -> dict[str, tk.PhotoImage | None]: return images - def create_button(self, action: str, parent_frame: tk.Frame, images: dict[str, tk.PhotoImage | None]) -> None: + def create_button(self, action: str, parent_frame: tk.Frame, images: dict[str, tk.PhotoImage | None], hovertext: str) -> None: """ Helper method to create a button in the specified frame with an icon. @@ -164,6 +165,7 @@ def create_button(self, action: str, parent_frame: tk.Frame, images: dict[str, t borderwidth=0, highlightthickness=0, ) + Hovertip(btn, hovertext, 500) btn.pack(side=tk.LEFT, padx=10, pady=2) # Minimal spacing between buttons self.buttons[action] = btn # Store button reference From 78a9554c998f58f0abdf133493ef5c44be5a8728 Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 12:38:23 -0500 Subject: [PATCH 2/6] ctrl s --- menus.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/menus.py b/menus.py index fdded35..6876daf 100644 --- a/menus.py +++ b/menus.py @@ -121,9 +121,12 @@ def __init__( self.serial_port = SerialPort(None, 115200, 1, None) """The serial port configuration.""" + self.open_file_path: str | None = None + """The file path for the current open file.""" + # Define menu items and their corresponding dropdown options menus = { - "Fichier": ["Nouveau", "Ouvrir", "Enregistrer", "Quitter"], + "Fichier": ["Nouveau", "Ouvrir", "Enregistrer", "Enregistrer sous", "Quitter"], "Microcontrôleur": ["Choisir un microcontrôleur", "Table de correspondance", "Configurer le port série"], "Exporter": ["Vérifier", "Téléverser"], "Aide": ["Documentation", "À propos"], @@ -132,7 +135,8 @@ def __init__( menu_commands = { "Nouveau": self.new_file, "Ouvrir": self.open_file, - "Enregistrer": self.save_file, + "Enregistrer": lambda: self.save_file(False), + "Enregistrer sous": self.save_file, "Quitter": self.parent.quit, "Configurer le port série": self.configure_ports, "Table de correspondance": self.show_correspondence_table, @@ -158,6 +162,8 @@ def __init__( self.parent.bind("", self.close_dropdown, add="+") self.canvas.bind("", self.close_dropdown, add="+") + self.parent.bind("", lambda _: self.save_file(False), add="+") + def select_microcontroller(self): """Handler for microcontroller selection.""" # Create a new top-level window for the dialog @@ -405,6 +411,7 @@ def close_dropdown(self, event): def new_file(self): """Handler for the 'New' menu item.""" # Clear the canvas and reset the circuit + self.open_file_path = None self.board.sketcher.clear_board() self.board.fill_matrix_1260_pts() self.board.draw_blank_board_model() @@ -456,6 +463,7 @@ def open_file(self): print(f"Unspecified component: {key}") messagebox.showinfo("Ouvrir un fichier", f"Circuit chargé depuis {file_path}") + self.open_file_path = file_path except Exception as e: print(f"Error loading file: {e}") messagebox.showerror( @@ -521,12 +529,15 @@ def load_io(self, io_data): ] self.board.sketcher.circuit(x_o, y_o, model=model_io) - def save_file(self): + def save_file(self, prompt_for_path: bool = True): """Handler for the 'Save' menu item.""" print("Save File") - file_path = filedialog.asksaveasfilename( - defaultextension=".json", filetypes=[("JSON files", "*.json"), ("All files", "*.*")] - ) + if prompt_for_path or not self.open_file_path: + file_path = filedialog.asksaveasfilename( + defaultextension=".json", filetypes=[("JSON files", "*.json"), ("All files", "*.*")] + ) + else: + file_path = self.open_file_path if file_path: try: circuit_data = deepcopy(self.current_dict_circuit) @@ -546,6 +557,7 @@ def save_file(self): json.dump(circuit_data, file, indent=4) print(f"Circuit saved to {file_path}") messagebox.showinfo("Sauvegarde réussie", f"Circuit sauvegardé dans {file_path}") + self.open_file_path = file_path except (TypeError, KeyError) as e: print(f"Error saving file: {e}") messagebox.showerror( From e04e68bc43001307d194d7eefea31b734e8a954d Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 12:49:19 -0500 Subject: [PATCH 3/6] Fix battery and window size --- arduino_logique.py | 2 +- breadboard.py | 2 +- component_sketch.py | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arduino_logique.py b/arduino_logique.py index 9219388..0d5656a 100644 --- a/arduino_logique.py +++ b/arduino_logique.py @@ -24,7 +24,7 @@ def main(): # Creating main window win = tk.Tk() win.title("Laboratoire virtuel de circuit logique - GIF-1002") - win.geometry("1700x800") # Initial window size + win.geometry("1500x800") # Initial window size win.resizable(False, False) # Disabling window resizing win.configure(bg="#333333") # Setting consistent background color diff --git a/breadboard.py b/breadboard.py index e3395d9..1eeb973 100644 --- a/breadboard.py +++ b/breadboard.py @@ -225,7 +225,7 @@ def draw_blank_board_model(self, x_origin: int = 50, y_origin: int = 10, battery ] self.sketcher.circuit(x_origin, y_origin, scale=self.sketcher.scale_factor, model=blank_board_model) - battery_x = x_origin + 1200 # Adjust as needed for proper positioning + battery_x = x_origin + 1050 # Adjust as needed for proper positioning battery_y = y_origin + 300 # Adjust as needed for proper positioning # Reset all matrix elements' states to FREE diff --git a/component_sketch.py b/component_sketch.py index e8cc9fc..872b65e 100644 --- a/component_sketch.py +++ b/component_sketch.py @@ -2764,8 +2764,8 @@ def draw_battery( original_width = battery_photo.width() original_height = battery_photo.height() - new_width = int(original_width * scale * 0.7) - new_height = int(original_height * scale * 0.7) + new_width = int(original_width * scale * 0.4) + new_height = int(original_height * scale * 0.4) scale_x = new_width / original_width scale_y = new_height / original_height @@ -2817,8 +2817,8 @@ def draw_battery( if neg_wire_end: neg_wire_end_x, neg_wire_end_y = neg_wire_end else: - neg_wire_end_x = neg_wire_start_x - 100 * scale # Wires go to the left - neg_wire_end_y = neg_wire_start_y + neg_wire_end_x = neg_wire_start_x - 50 * scale # Wires go to the left + neg_wire_end_y = neg_wire_start_y - 50 * scale # Wires go up self.draw_battery_wire( wire_id=neg_wire_id, @@ -2834,8 +2834,8 @@ def draw_battery( if pos_wire_end: pos_wire_end_x, pos_wire_end_y = pos_wire_end else: - pos_wire_end_x = pos_wire_start_x - 100 * scale - pos_wire_end_y = pos_wire_start_y + pos_wire_end_x = pos_wire_start_x - 50 * scale + pos_wire_end_y = pos_wire_start_y + 50 * scale # Wires go down self.draw_battery_wire( wire_id=pos_wire_id, From d0a20c8d162c8074bc578908b412eca29180257d Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 13:00:12 -0500 Subject: [PATCH 4/6] toolbar fix --- arduino_logique.py | 2 +- toolbar.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arduino_logique.py b/arduino_logique.py index 0d5656a..98af890 100644 --- a/arduino_logique.py +++ b/arduino_logique.py @@ -50,7 +50,7 @@ def main(): # Creating the toolbar instance toolbar = Toolbar(parent=win, canvas=canvas, sketcher=sketcher, current_dict_circuit=sketcher.current_dict_circuit) # Placing the secondary top bar in row=1, column=1 (spanning only the canvas area) - toolbar.topbar_frame.grid(row=1, column=1, sticky="ew", padx=(0, 10), pady=(0, 0)) + toolbar.topbar_frame.grid(row=1, column=1, sticky="ew", padx=(0, 0), pady=(0, 0)) # Set initial scale factor initial_scale = 1.0 # Equivalent to 10.0 / 10.0 diff --git a/toolbar.py b/toolbar.py index b082acb..415bf75 100644 --- a/toolbar.py +++ b/toolbar.py @@ -95,6 +95,7 @@ def create_topbar(self, parent: tk.Tk): borderwidth=0, highlightthickness=0, ) + Hovertip(self.color_button, "Choisir une couleur pour les composantes", 500) self.color_button.pack(side=tk.LEFT, padx=2, pady=2) self.create_button("Delete", right_frame, images, "Supprimer un composant") From ee72916e4255c35444d78327a147451d17af0128 Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 13:11:57 -0500 Subject: [PATCH 5/6] toggle sidebar --- arduino_logique.py | 24 ++++++++++++++++++++++-- sidebar.py | 31 ++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/arduino_logique.py b/arduino_logique.py index 98af890..957ff94 100644 --- a/arduino_logique.py +++ b/arduino_logique.py @@ -4,10 +4,9 @@ simulating logic circuits using Tkinter. It includes functionality to initialize a canvas, draw a breadboard, etc. """ - +import os from pathlib import Path import tkinter as tk -from tkinter import font from breadboard import Breadboard from component_sketch import ComponentSketcher from menus import Menus @@ -15,6 +14,11 @@ from toolbar import Toolbar from utils import resource_path +if os.name == "darwin" or os.name == "posix": + from tkinter import font + from tkmacosx import Button # type: ignore +else: + from tkinter import Button, font def main(): """ @@ -69,6 +73,22 @@ def main(): toolbar=toolbar, ) + def toggle_sidebar(): + sidebar.toggle_sidebar() + if sidebar.is_sidebar_visible: + toggle_sidebar_btn.config(text="<<") + else: + toggle_sidebar_btn.config(text=">>") + + toggle_sidebar_btn = Button( + win, + text="<<", + command=toggle_sidebar, + bg="#333333", + fg="#FFFFFF", + ) + toggle_sidebar_btn.grid(row=1, column=0, sticky="w") + def refresh_sidebar(): sidebar.refresh() win.after(5000, refresh_sidebar) diff --git a/sidebar.py b/sidebar.py index 37498f3..bf65543 100644 --- a/sidebar.py +++ b/sidebar.py @@ -78,26 +78,35 @@ def __init__( self.saved_bindings: dict[str, Callable] = {} # Creating the sidebar frame - sidebar_frame = tk.Frame(parent, bg="#333333", width=275, bd=0, highlightthickness=0) - sidebar_frame.grid(row=2, column=0, sticky="nsew", padx=0, pady=0) - sidebar_frame.grid_propagate(False) # Preventing frame from resizing + self.sidebar_frame = tk.Frame(parent, bg="#333333", width=275, bd=0, highlightthickness=0) + self.sidebar_frame.grid(row=2, column=0, sticky="nsew", padx=0, pady=0) + self.sidebar_frame.grid_propagate(False) # Preventing frame from resizing + + self.is_sidebar_visible = True # Configuring grid weights for the sidebar - sidebar_frame.grid_rowconfigure(0, weight=0) # Search bar - sidebar_frame.grid_rowconfigure(1, weight=0) # Chips label - sidebar_frame.grid_rowconfigure(2, weight=8) # Chips area (80%) - sidebar_frame.grid_rowconfigure(3, weight=0) # Manage button - sidebar_frame.grid_columnconfigure(0, weight=1) + self.sidebar_frame.grid_rowconfigure(0, weight=0) # Search bar + self.sidebar_frame.grid_rowconfigure(1, weight=0) # Chips label + self.sidebar_frame.grid_rowconfigure(2, weight=8) # Chips area (80%) + self.sidebar_frame.grid_rowconfigure(3, weight=0) # Manage button + self.sidebar_frame.grid_columnconfigure(0, weight=1) self.sidebar_grid = SidebarGrid(columns=2, visible_rows=12, grid_capacity=24) # Creating sidebar components - self.create_search_bar(sidebar_frame) - self.create_chips_area(sidebar_frame) - self.create_manage_button(sidebar_frame) + self.create_search_bar(self.sidebar_frame) + self.create_chips_area(self.sidebar_frame) + self.create_manage_button(self.sidebar_frame) self.chip_files_mtimes = get_chip_modification_times() + def toggle_sidebar(self): + if self.is_sidebar_visible: + self.sidebar_frame.grid_remove() + else: + self.sidebar_frame.grid() + self.is_sidebar_visible = not self.is_sidebar_visible + def initialize_chip_data(self, current_dict_circuit, chip_images_path) -> None: """ Initializes the chip data for the sidebar. From b28ccfc36d7e060cd4bf74400cc07d225473f478 Mon Sep 17 00:00:00 2001 From: Charles-Olivier Trudel Date: Sat, 7 Dec 2024 13:22:47 -0500 Subject: [PATCH 6/6] FIx buttons --- menus.py | 2 +- toolbar.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/menus.py b/menus.py index 6876daf..fc1a0c6 100644 --- a/menus.py +++ b/menus.py @@ -156,7 +156,7 @@ def __init__( fg="white", font=("FiraCode-Bold", 12), ) - self.microcontroller_label.pack(side="right", padx=10) + self.microcontroller_label.pack(side="right", fill="y", padx=175) # Bind to parent to close dropdowns when clicking outside self.parent.bind("", self.close_dropdown, add="+") diff --git a/toolbar.py b/toolbar.py index 415bf75..7927779 100644 --- a/toolbar.py +++ b/toolbar.py @@ -68,10 +68,10 @@ def create_topbar(self, parent: tk.Tk): # Create left and right subframes left_frame = tk.Frame(self.topbar_frame, bg="#505050") - left_frame.pack(side=tk.LEFT, padx=5, pady=5) + left_frame.pack(side=tk.LEFT, padx=50, pady=5) right_frame = tk.Frame(self.topbar_frame, bg="#505050") - right_frame.pack(side=tk.RIGHT, padx=5, pady=5) + right_frame.pack(after=left_frame, side=tk.LEFT, padx=100, pady=5) # Load images images = self.load_images()