diff --git a/__pycache__/cfd_animated_icon.cpython-312.pyc b/__pycache__/cfd_animated_icon.cpython-312.pyc index 9fa6450..b6c4248 100644 Binary files a/__pycache__/cfd_animated_icon.cpython-312.pyc and b/__pycache__/cfd_animated_icon.cpython-312.pyc differ diff --git a/__pycache__/custom_file_dialog.cpython-312.pyc b/__pycache__/custom_file_dialog.cpython-312.pyc index 911dd35..4778ff9 100644 Binary files a/__pycache__/custom_file_dialog.cpython-312.pyc and b/__pycache__/custom_file_dialog.cpython-312.pyc differ diff --git a/cfd_animated_icon.py b/cfd_animated_icon.py index 8a874f7..f7608e8 100644 --- a/cfd_animated_icon.py +++ b/cfd_animated_icon.py @@ -29,6 +29,7 @@ class AnimatedIcon(tk.Canvas): self.use_pillow = use_pillow and PIL_AVAILABLE self.running = False self.angle = 0 + self.pulse_animation = False self.color_rgb = _hex_to_rgb(self.color) self.highlight_color_rgb = _hex_to_rgb(self.highlight_color) @@ -46,13 +47,44 @@ class AnimatedIcon(tk.Canvas): def _draw_canvas_frame(self): self.delete("all") - if self.animation_type == "line": + if self.pulse_animation: + self._draw_canvas_pulse() + elif self.animation_type == "line": self._draw_canvas_line() elif self.animation_type == "double_arc": self._draw_canvas_double_arc() elif self.animation_type == "counter_arc": self._draw_canvas_counter_arc() + def _draw_canvas_pulse(self): + center_x, center_y = self.width / 2, self.height / 2 + alpha = (sin(self.angle * 5) + 1) / 2 # Faster pulse + r = int(alpha * (self.highlight_color_rgb[0] - self.color_rgb[0]) + self.color_rgb[0]) + g = int(alpha * (self.highlight_color_rgb[1] - self.color_rgb[1]) + self.color_rgb[1]) + b = int(alpha * (self.highlight_color_rgb[2] - self.color_rgb[2]) + self.color_rgb[2]) + pulse_color = f"#{r:02x}{g:02x}{b:02x}" + + if self.animation_type == "line": + for i in range(8): + angle = i * (pi / 4) + start_x = center_x + cos(angle) * (self.width * 0.2) + start_y = center_y + sin(angle) * (self.height * 0.2) + end_x = center_x + cos(angle) * (self.width * 0.4) + end_y = center_y + sin(angle) * (self.height * 0.4) + self.create_line(start_x, start_y, end_x, end_y, fill=pulse_color, width=2) + elif self.animation_type == "double_arc": + radius = min(center_x, center_y) * 0.8 + bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) + self.create_arc(bbox, start=0, extent=359.9, style=tk.ARC, outline=pulse_color, width=2) + elif self.animation_type == "counter_arc": + radius_outer = min(center_x, center_y) * 0.8 + bbox_outer = (center_x - radius_outer, center_y - radius_outer, center_x + radius_outer, center_y + radius_outer) + self.create_arc(bbox_outer, start=0, extent=359.9, style=tk.ARC, outline=pulse_color, width=2) + radius_inner = min(center_x, center_y) * 0.6 + bbox_inner = (center_x - radius_inner, center_y - radius_inner, center_x + radius_inner, center_y + radius_inner) + self.create_arc(bbox_inner, start=0, extent=359.9, style=tk.ARC, outline=self.color, width=2) + + def _draw_canvas_line(self): center_x, center_y = self.width / 2, self.height / 2 for i in range(8): @@ -98,7 +130,9 @@ class AnimatedIcon(tk.Canvas): def _draw_pillow_frame(self): self.draw.rectangle([0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0)) - if self.animation_type == "line": + if self.pulse_animation: + self._draw_pillow_pulse() + elif self.animation_type == "line": self._draw_pillow_line() elif self.animation_type == "double_arc": self._draw_pillow_double_arc() @@ -110,6 +144,34 @@ class AnimatedIcon(tk.Canvas): self.delete("all") self.create_image(0, 0, anchor="nw", image=self.photo_image) + def _draw_pillow_pulse(self): + center_x, center_y = self.width * 2, self.height * 2 + alpha = (sin(self.angle * 5) + 1) / 2 # Faster pulse + r = int(alpha * (self.highlight_color_rgb[0] - self.color_rgb[0]) + self.color_rgb[0]) + g = int(alpha * (self.highlight_color_rgb[1] - self.color_rgb[1]) + self.color_rgb[1]) + b = int(alpha * (self.highlight_color_rgb[2] - self.color_rgb[2]) + self.color_rgb[2]) + pulse_color = (r, g, b) + + if self.animation_type == "line": + for i in range(12): + angle = i * (pi / 6) + start_x = center_x + cos(angle) * (self.width * 0.8) + start_y = center_y + sin(angle) * (self.height * 0.8) + end_x = center_x + cos(angle) * (self.width * 1.6) + end_y = center_y + sin(angle) * (self.height * 1.6) + self.draw.line([(start_x, start_y), (end_x, end_y)], fill=pulse_color, width=6, joint="curve") + elif self.animation_type == "double_arc": + radius = min(center_x, center_y) * 0.8 + bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) + self.draw.arc(bbox, start=0, end=360, fill=pulse_color, width=5) + elif self.animation_type == "counter_arc": + radius_outer = min(center_x, center_y) * 0.8 + bbox_outer = (center_x - radius_outer, center_y - radius_outer, center_x + radius_outer, center_y + radius_outer) + self.draw.arc(bbox_outer, start=0, end=360, fill=pulse_color, width=7) + radius_inner = min(center_x, center_y) * 0.6 + bbox_inner = (center_x - radius_inner, center_y - radius_inner, center_x + radius_inner, center_y + radius_inner) + self.draw.arc(bbox_inner, start=0, end=360, fill=self.color_rgb, width=7) + def _draw_pillow_line(self): center_x, center_y = self.width * 2, self.height * 2 for i in range(12): @@ -239,17 +301,20 @@ class AnimatedIcon(tk.Canvas): self._draw_frame() self.after(30, self._animate) - def start(self): + def start(self, pulse=False): if not self.running: + self.pulse_animation = pulse self.running = True self._animate() def stop(self): self.running = False + self.pulse_animation = False self._draw_stopped_frame() def hide(self): self.running = False + self.pulse_animation = False self.delete("all") def show_full_circle(self): diff --git a/custom_file_dialog.py b/custom_file_dialog.py index 89f1654..233883f 100644 --- a/custom_file_dialog.py +++ b/custom_file_dialog.py @@ -251,10 +251,6 @@ class CustomFileDialog(tk.Toplevel): self.widget_manager.path_entry.bind( "", self.handle_path_entry_return) - # Bind focus events to show the static animation - self.widget_manager.path_entry.bind("", self.show_search_ready) - self.widget_manager.filename_entry.bind("", self.show_search_ready) - self.bind("", self.show_search_bar) # Bind the delete key only in "save" mode @@ -283,7 +279,7 @@ class CustomFileDialog(tk.Toplevel): # If not animating, activate search entry self.widget_manager.filename_entry.focus_set() self.search_mode = True # Ensure search mode is active - self.widget_manager.search_animation.show_full_circle() + self.widget_manager.search_animation.start(pulse=True) self.widget_manager.filename_entry.bind("", self.execute_search) self.widget_manager.filename_entry.bind("", self.hide_search_bar) @@ -306,6 +302,8 @@ class CustomFileDialog(tk.Toplevel): self.widget_manager.filename_entry.unbind("") if self.dialog_mode == "save": self.widget_manager.filename_entry.bind("", lambda e: self.on_save()) + else: + self.widget_manager.filename_entry.bind("", self.execute_search) self.populate_files() self.widget_manager.search_animation.hide() @@ -317,7 +315,7 @@ class CustomFileDialog(tk.Toplevel): self.hide_search_bar() return self.widget_manager.search_status_label.config(text=f"Suche nach '{search_term}'...") - self.widget_manager.search_animation.start() + self.widget_manager.search_animation.start(pulse=False) self.update_idletasks() self.search_thread = threading.Thread(target=self._perform_search_in_thread, args=(search_term,)) self.search_thread.start() @@ -466,6 +464,8 @@ class CustomFileDialog(tk.Toplevel): ) self.widget_manager.search_animation.grid(row=0, column=0, sticky='w', padx=(0, 5), pady=(4,0)) self.widget_manager.search_animation.bind("", lambda e: self.activate_search()) + self.widget_manager.search_animation.bind("", self._show_tooltip) + self.widget_manager.search_animation.bind("", self._hide_tooltip) if is_running: self.widget_manager.search_animation.start() @@ -1124,6 +1124,7 @@ class CustomFileDialog(tk.Toplevel): self.selected_item_frame = item_frame self.selected_file = path self.update_status_bar(path) # Pass selected path + self.show_search_ready() if not os.path.isdir(path): self.widget_manager.filename_entry.delete(0, tk.END) self.widget_manager.filename_entry.insert(0, os.path.basename(path)) @@ -1136,6 +1137,7 @@ class CustomFileDialog(tk.Toplevel): path = os.path.join(self.current_dir, item_text) self.selected_file = path self.update_status_bar(path) # Pass selected path + self.show_search_ready() if not os.path.isdir(self.selected_file): self.widget_manager.filename_entry.delete(0, tk.END) self.widget_manager.filename_entry.insert(0, item_text) @@ -1417,6 +1419,22 @@ class CustomFileDialog(tk.Toplevel): self.navigate_to(directory) self.after(100, lambda: self._select_file_in_view(filename)) + def _show_tooltip(self, event): + if hasattr(self, 'tooltip_window') and self.tooltip_window.winfo_exists(): + return + x = self.widget_manager.search_animation.winfo_rootx() + 25 + y = self.widget_manager.search_animation.winfo_rooty() + 25 + self.tooltip_window = tk.Toplevel(self) + self.tooltip_window.wm_overrideredirect(True) + self.tooltip_window.wm_geometry(f"+{x}+{y}") + label = tk.Label(self.tooltip_window, text="Klicken, um die Suche zu aktivieren", + background="#333333", foreground="#FFFFFF", relief="solid", borderwidth=1) + label.pack() + + def _hide_tooltip(self, event): + if hasattr(self, 'tooltip_window') and self.tooltip_window.winfo_exists(): + self.tooltip_window.destroy() + def start_rename(self, item_widget, item_path): if self.view_mode.get() == "icons": self._start_rename_icon_view(item_widget, item_path) diff --git a/mainwindow.py b/mainwindow.py index c7d103a..65766ee 100755 --- a/mainwindow.py +++ b/mainwindow.py @@ -33,7 +33,7 @@ class GlotzMol(tk.Tk): dialog = CustomFileDialog(self, initial_dir=os.path.expanduser("~"), filetypes=[("All Files", "*.*") - ]) + ], dialog_mode="save") # This is the crucial part: wait for the dialog to be closed self.wait_window(dialog) @@ -55,7 +55,7 @@ if __name__ == "__main__": style = ttk.Style(root) root.tk.call('source', f"{theme_path}/water.tcl") try: - root.tk.call('set_theme', 'dark') + root.tk.call('set_theme', 'light') except tk.TclError: pass root.mainloop()