Compare commits
	
		
			1 Commits
		
	
	
		
			10-08-2025
			...
			09-05-2025
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6051ad1546 | 
							
								
								
									
										75
									
								
								Changelog
									
									
									
									
									
								
							
							
						
						@@ -8,77 +8,10 @@ My standard System: Linux Mint 22 Cinnamon
 | 
			
		||||
 - for loops with lists replaced by List Comprehensions
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
10.08.2025
 | 
			
		||||
 | 
			
		||||
 - Wirepy divided into several scripts for better overview and maintenance
 | 
			
		||||
 | 
			
		||||
 - Own file dialogue is now used to open Wireguard files for the import.
 | 
			
		||||
 | 
			
		||||
 - New update notification. A canvas ring flashes when updates are available
 | 
			
		||||
 | 
			
		||||
 - UI size change now grow all widgets with.
 | 
			
		||||
 | 
			
		||||
 - Update Search at start of the app now starts in a thread to not stop the GUI
 | 
			
		||||
 | 
			
		||||
 - Logviewer replaces with new button in the menu bar,
 | 
			
		||||
   a new window opens in which the necessary infos stand when errors occur.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
01.08.2025
 | 
			
		||||
 | 
			
		||||
 - Replace Imagemanager with IconManager and remove ImageManager from wp_app_config.py
 | 
			
		||||
 | 
			
		||||
 - Logging improved
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
02-07-2025
 | 
			
		||||
 | 
			
		||||
- Complete code for faulty f" string configuration dur addicted and fixed
 | 
			
		||||
 | 
			
		||||
- updater replace Downloadbutton with Lx Tools installer
 | 
			
		||||
 | 
			
		||||
- remove logviewer icon 
 | 
			
		||||
 | 
			
		||||
- add settings.png icon for update button
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
27-06-2025
 | 
			
		||||
  
 | 
			
		||||
 - Header added for more modern desing
 | 
			
		||||
 | 
			
		||||
 - Sizes adjust the frames and labels improve
 | 
			
		||||
 | 
			
		||||
 - More modern desing for listbox, Address, Dns and Endpoint
 | 
			
		||||
 | 
			
		||||
 - ui works now better with rename button
 | 
			
		||||
 | 
			
		||||
 - add Image class for manage Images
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
23-06-2025
 | 
			
		||||
 | 
			
		||||
 - all msg_window with MassageDialog replaced
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
14-06-2025
 | 
			
		||||
 | 
			
		||||
 - replace msg_window with MassageDialog
 | 
			
		||||
 - vpn stop icon corrected
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
07-06-2025
 | 
			
		||||
 | 
			
		||||
 - ssl_decrypt now directly checks whether encrypted files are located in the specified directory. 
 | 
			
		||||
 - This method has been removed from common_tools. The path has been adjusted ssl_decrypt likely 
 | 
			
		||||
   had an incorrect path. No files were decrypted. This has been fixed. 
 | 
			
		||||
 - Key generation has been removed from ssl_decrypt, as it is only needed in ssl_encrypt.
 | 
			
		||||
 - Logviewer now in the settings menu. Moduls now as libs in share_libs.
 | 
			
		||||
 - The Lx Tools installer is there to ensure that everything required for the selected app is installed.
 | 
			
		||||
04-06-2025
 | 
			
		||||
 | 
			
		||||
 - large update in the module were outsourced and can now be used as
 | 
			
		||||
   dependencies to wirepy us other apps from git.ilunix.de
 | 
			
		||||
 | 
			
		||||
   ### Added
 | 
			
		||||
13-04-20255
 | 
			
		||||
@@ -118,14 +51,12 @@ My standard System: Linux Mint 22 Cinnamon
 | 
			
		||||
 - Tunnels are now read from the directory to view them in the list. 
 | 
			
		||||
   To display only own tunnels, and read errors are minimized.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ### Added
 | 
			
		||||
10-11-2024
 | 
			
		||||
 | 
			
		||||
 - Fix Checkbutton Autostart when first install Wire-Py
 | 
			
		||||
 - Update Translate Files
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ### Added
 | 
			
		||||
10-11-2024
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 1.8 KiB  | 
| 
		 Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 346 B  | 
| 
		 Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 242 B  | 
| 
		 Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 297 B  | 
| 
		 Before Width: | Height: | Size: 104 B  | 
| 
		 Before Width: | Height: | Size: 179 B  | 
| 
		 Before Width: | Height: | Size: 106 B  | 
| 
		 Before Width: | Height: | Size: 183 B  | 
| 
		 Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 286 B  | 
| 
		 Before Width: | Height: | Size: 151 B  | 
| 
		 Before Width: | Height: | Size: 221 B  | 
| 
		 Before Width: | Height: | Size: 154 B  | 
| 
		 Before Width: | Height: | Size: 228 B  | 
| 
		 Before Width: | Height: | Size: 1.8 KiB  | 
| 
		 Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 326 B  | 
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 247 B  | 
| 
		 Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 299 B  | 
| 
		 Before Width: | Height: | Size: 107 B  | 
| 
		 Before Width: | Height: | Size: 185 B  | 
| 
		 Before Width: | Height: | Size: 106 B  | 
| 
		 Before Width: | Height: | Size: 183 B  | 
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 250 B  | 
| 
		 Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 263 B  | 
| 
		 Before Width: | Height: | Size: 167 B  | 
| 
		 Before Width: | Height: | Size: 251 B  | 
| 
		 Before Width: | Height: | Size: 154 B  | 
| 
		 Before Width: | Height: | Size: 228 B  | 
@@ -1,10 +1,5 @@
 | 
			
		||||
# Copyright © 2021 rdbende <rdbende@gmail.com>
 | 
			
		||||
# inspired by rdbende modified azure to water by Désire Werner Menrath polunga40@unity-mail.de 2024
 | 
			
		||||
# Update add New Style TButton.Borderless for Buttons without edge and without rounded corners by
 | 
			
		||||
# Désire Werner Menrath 28-07-2025
 | 
			
		||||
# Add Update Progressbars Round ends on Horizontal and Vertikal + add small bars
 | 
			
		||||
# Désire Werner Menrath 30-07-2025
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
source [file join [file dirname [info script]] theme light.tcl]
 | 
			
		||||
source [file join [file dirname [info script]] theme dark.tcl]
 | 
			
		||||
@@ -18,7 +13,7 @@ proc set_theme {mode} {
 | 
			
		||||
		array set colors {
 | 
			
		||||
            -fg             "#ffffff"
 | 
			
		||||
            -bg             "#333333"
 | 
			
		||||
            -disabledfg     "#aaaaaa"
 | 
			
		||||
            -disabledfg     "#ffffff"
 | 
			
		||||
            -disabledbg     "#737373"
 | 
			
		||||
            -selectfg       "#000000"
 | 
			
		||||
            -selectbg       "#00c4ff"
 | 
			
		||||
@@ -58,7 +53,7 @@ proc set_theme {mode} {
 | 
			
		||||
            -fg             "#000000"
 | 
			
		||||
            -bg             "#ffffff"
 | 
			
		||||
            -disabledfg     "#737373"
 | 
			
		||||
            -disabledbg     "#f0f0f0"
 | 
			
		||||
            -disabledbg     "#ffffff"
 | 
			
		||||
            -selectfg       "#000000"
 | 
			
		||||
            -selectbg       "#00c4ff"
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										970
									
								
								animated_icon.py
									
									
									
									
									
								
							
							
						
						@@ -1,970 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
A Tkinter widget for displaying animated icons.
 | 
			
		||||
 | 
			
		||||
This module provides the AnimatedIcon class, a custom Tkinter Canvas widget
 | 
			
		||||
that can display various types of animations. It supports both native Tkinter
 | 
			
		||||
drawing and Pillow (PIL) for anti-aliased graphics if available.
 | 
			
		||||
"""
 | 
			
		||||
import tkinter as tk
 | 
			
		||||
from math import sin, cos, pi
 | 
			
		||||
from typing import Tuple, Optional
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from PIL import Image, ImageDraw, ImageTk
 | 
			
		||||
    PIL_AVAILABLE = True
 | 
			
		||||
except ImportError:
 | 
			
		||||
    PIL_AVAILABLE = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
 | 
			
		||||
    """Converts a hex color string to an RGB tuple."""
 | 
			
		||||
    hex_color = hex_color.lstrip('#')
 | 
			
		||||
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AnimatedIcon(tk.Canvas):
 | 
			
		||||
    """A custom Tkinter Canvas widget for displaying animations."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, master: tk.Misc, width: int = 20, height: int = 20, animation_type: str = "counter_arc", color: str = "#2a6fde", highlight_color: str = "#5195ff", use_pillow: bool = False, bg: Optional[str] = None) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Initializes the AnimatedIcon widget.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            master: The parent widget.
 | 
			
		||||
            width (int): The width of the icon.
 | 
			
		||||
            height (int): The height of the icon.
 | 
			
		||||
            animation_type (str): The type of animation to display.
 | 
			
		||||
                Options: "counter_arc", "double_arc", "line", "blink".
 | 
			
		||||
            color (str): The primary color of the icon.
 | 
			
		||||
            highlight_color (str): The highlight color of the icon.
 | 
			
		||||
            use_pillow (bool): Whether to use Pillow for drawing if available.
 | 
			
		||||
            bg (str): The background color of the canvas.
 | 
			
		||||
        """
 | 
			
		||||
        if bg is None:
 | 
			
		||||
            try:
 | 
			
		||||
                bg = master.cget("background")
 | 
			
		||||
            except tk.TclError:
 | 
			
		||||
                bg = "#f0f0f0"  # Fallback color
 | 
			
		||||
        super().__init__(master, width=width, height=height, bg=bg, highlightthickness=0)
 | 
			
		||||
 | 
			
		||||
        self.width = width
 | 
			
		||||
        self.height = height
 | 
			
		||||
        self.animation_type = animation_type
 | 
			
		||||
        self.color = color
 | 
			
		||||
        self.highlight_color = highlight_color
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self.image = Image.new(
 | 
			
		||||
                "RGBA", (width * 4, height * 4), (0, 0, 0, 0))
 | 
			
		||||
            self.draw = ImageDraw.Draw(self.image)
 | 
			
		||||
            self.photo_image = None
 | 
			
		||||
 | 
			
		||||
    def _draw_frame(self) -> None:
 | 
			
		||||
        """Draws a single frame of the animation."""
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self._draw_pillow_frame()
 | 
			
		||||
        else:
 | 
			
		||||
            self._draw_canvas_frame()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_frame(self) -> None:
 | 
			
		||||
        """Draws a frame using native Tkinter canvas methods."""
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        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()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_canvas_blink()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_pulse(self) -> None:
 | 
			
		||||
        """Draws the pulse animation using canvas methods."""
 | 
			
		||||
        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) -> None:
 | 
			
		||||
        """Draws the line animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        for i in range(8):
 | 
			
		||||
            angle = self.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)
 | 
			
		||||
            alpha = (cos(self.angle * 2 + i * (pi / 4)) + 1) / 2
 | 
			
		||||
 | 
			
		||||
            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])
 | 
			
		||||
            color = f"#{r:02x}{g:02x}{b:02x}"
 | 
			
		||||
 | 
			
		||||
            self.create_line(start_x, start_y, end_x,
 | 
			
		||||
                             end_y, fill=color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_double_arc(self) -> None:
 | 
			
		||||
        """Draws the double arc animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        bbox = (center_x - radius, center_y - radius,
 | 
			
		||||
                center_x + radius, center_y + radius)
 | 
			
		||||
 | 
			
		||||
        start_angle1 = -self.angle * 180 / pi
 | 
			
		||||
        extent1 = 120 + 60 * sin(-self.angle)
 | 
			
		||||
        self.create_arc(bbox, start=start_angle1, extent=extent1,
 | 
			
		||||
                        style=tk.ARC, outline=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
        start_angle2 = (-self.angle + pi) * 180 / pi
 | 
			
		||||
        extent2 = 120 + 60 * sin(-self.angle + pi / 2)
 | 
			
		||||
        self.create_arc(bbox, start=start_angle2, extent=extent2,
 | 
			
		||||
                        style=tk.ARC, outline=self.color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_counter_arc(self) -> None:
 | 
			
		||||
        """Draws the counter arc animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        start_angle1 = -self.angle * 180 / pi
 | 
			
		||||
        self.create_arc(bbox_outer, start=start_angle1, extent=150,
 | 
			
		||||
                        style=tk.ARC, outline=self.highlight_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)
 | 
			
		||||
        start_angle2 = self.angle * 180 / pi + 60
 | 
			
		||||
        self.create_arc(bbox_inner, start=start_angle2, extent=150,
 | 
			
		||||
                        style=tk.ARC, outline=self.color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_blink(self) -> None:
 | 
			
		||||
        """Draws the blink animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        alpha = (sin(self.angle * 2) + 1) / 2  # Slower blinking speed
 | 
			
		||||
        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])
 | 
			
		||||
        blink_color = f"#{r:02x}{g:02x}{b:02x}"
 | 
			
		||||
        self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y +
 | 
			
		||||
                        radius, start=0, extent=359.9, style=tk.ARC, outline=blink_color, width=4)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_frame(self) -> None:
 | 
			
		||||
        """Draws a frame using Pillow for anti-aliased graphics."""
 | 
			
		||||
        self.draw.rectangle(
 | 
			
		||||
            [0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0))
 | 
			
		||||
        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()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_pillow_counter_arc()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_pillow_blink()
 | 
			
		||||
 | 
			
		||||
        resized_image = self.image.resize(
 | 
			
		||||
            (self.width, self.height), Image.Resampling.LANCZOS)
 | 
			
		||||
        self.photo_image = ImageTk.PhotoImage(resized_image)
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        self.create_image(0, 0, anchor="nw", image=self.photo_image)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_pulse(self) -> None:
 | 
			
		||||
        """Draws the pulse animation using Pillow."""
 | 
			
		||||
        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) -> None:
 | 
			
		||||
        """Draws the line animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        for i in range(12):
 | 
			
		||||
            angle = self.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)
 | 
			
		||||
            alpha = (cos(self.angle * 2.5 + i * (pi / 6)) + 1) / 2
 | 
			
		||||
 | 
			
		||||
            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])
 | 
			
		||||
            color = (r, g, b)
 | 
			
		||||
 | 
			
		||||
            self.draw.line([(start_x, start_y), (end_x, end_y)],
 | 
			
		||||
                           fill=color, width=6, joint="curve")
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_double_arc(self) -> None:
 | 
			
		||||
        """Draws the double arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        bbox = (center_x - radius, center_y - radius,
 | 
			
		||||
                center_x + radius, center_y + radius)
 | 
			
		||||
 | 
			
		||||
        start_angle1 = self.angle * 180 / pi
 | 
			
		||||
        extent1 = 120 + 60 * sin(self.angle)
 | 
			
		||||
        self.draw.arc(bbox, start=start_angle1, end=start_angle1 +
 | 
			
		||||
                      extent1, fill=self.highlight_color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
        start_angle2 = (self.angle + pi) * 180 / pi
 | 
			
		||||
        extent2 = 120 + 60 * sin(self.angle + pi / 2)
 | 
			
		||||
        self.draw.arc(bbox, start=start_angle2, end=start_angle2 +
 | 
			
		||||
                      extent2, fill=self.color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_counter_arc(self) -> None:
 | 
			
		||||
        """Draws the counter arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        start_angle1 = self.angle * 180 / pi
 | 
			
		||||
        self.draw.arc(bbox_outer, start=start_angle1, end=start_angle1 +
 | 
			
		||||
                      150, fill=self.highlight_color_rgb, 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)
 | 
			
		||||
        start_angle2 = -self.angle * 180 / pi + 60
 | 
			
		||||
        self.draw.arc(bbox_inner, start=start_angle2,
 | 
			
		||||
                      end=start_angle2 + 150, fill=self.color_rgb, width=7)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_blink(self) -> None:
 | 
			
		||||
        """Draws the blink animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        alpha = (sin(self.angle * 2) + 1) / 2  # Slower blinking speed
 | 
			
		||||
        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])
 | 
			
		||||
        blink_color = (r, g, b)
 | 
			
		||||
        self.draw.arc((center_x - radius, center_y - radius, center_x + radius,
 | 
			
		||||
                      center_y + radius), start=0, end=360, fill=blink_color, width=10)
 | 
			
		||||
 | 
			
		||||
    def _draw_stopped_frame(self) -> None:
 | 
			
		||||
        """Draws the icon in its stopped (static) state."""
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self._draw_pillow_stopped_frame()
 | 
			
		||||
        else:
 | 
			
		||||
            self._draw_canvas_stopped_frame()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_stopped_frame(self) -> None:
 | 
			
		||||
        """Draws the stopped state using canvas methods."""
 | 
			
		||||
        if self.animation_type == "line":
 | 
			
		||||
            self._draw_canvas_line_stopped()
 | 
			
		||||
        elif self.animation_type == "double_arc":
 | 
			
		||||
            self._draw_canvas_double_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_canvas_counter_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_canvas_blink_stopped()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_line_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the line animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_double_arc_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the double arc animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_counter_arc_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the counter arc animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_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_blink_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the blink animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y +
 | 
			
		||||
                        radius, start=0, extent=359.9, style=tk.ARC, outline=self.highlight_color, width=4)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_stopped_frame(self) -> None:
 | 
			
		||||
        """Draws the stopped state using Pillow."""
 | 
			
		||||
        self.draw.rectangle(
 | 
			
		||||
            [0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0))
 | 
			
		||||
        if self.animation_type == "line":
 | 
			
		||||
            self._draw_pillow_line_stopped()
 | 
			
		||||
        elif self.animation_type == "double_arc":
 | 
			
		||||
            self._draw_pillow_double_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_pillow_counter_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_pillow_blink_stopped()
 | 
			
		||||
 | 
			
		||||
        resized_image = self.image.resize(
 | 
			
		||||
            (self.width, self.height), Image.Resampling.LANCZOS)
 | 
			
		||||
        self.photo_image = ImageTk.PhotoImage(resized_image)
 | 
			
		||||
        self.create_image(0, 0, anchor="nw", image=self.photo_image)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_line_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the line animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, width=6, joint="curve")
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_double_arc_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the double arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_counter_arc_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the counter arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, 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_blink_stopped(self) -> None:
 | 
			
		||||
        """Draws the stopped state for the blink animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        self.draw.arc((center_x - radius, center_y - radius, center_x + radius,
 | 
			
		||||
                      center_y + radius), start=0, end=360, fill=self.highlight_color_rgb, width=10)
 | 
			
		||||
 | 
			
		||||
    def _animate(self) -> None:
 | 
			
		||||
        """The main animation loop."""
 | 
			
		||||
        if self.running:
 | 
			
		||||
            self.angle += 0.1
 | 
			
		||||
            if self.angle > 2 * pi:
 | 
			
		||||
                self.angle -= 2 * pi
 | 
			
		||||
            self._draw_frame()
 | 
			
		||||
            self.after(30, self._animate)
 | 
			
		||||
 | 
			
		||||
    def start(self, pulse: bool = False) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Starts the animation.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            pulse (bool): If True, plays a pulsing animation instead of the main one.
 | 
			
		||||
        """
 | 
			
		||||
        if not self.running:
 | 
			
		||||
            self.pulse_animation = pulse
 | 
			
		||||
            self.running = True
 | 
			
		||||
            self._animate()
 | 
			
		||||
 | 
			
		||||
    def stop(self) -> None:
 | 
			
		||||
        """Stops the animation and shows the static 'stopped' frame."""
 | 
			
		||||
        self.running = False
 | 
			
		||||
        self.pulse_animation = False
 | 
			
		||||
        self._draw_stopped_frame()
 | 
			
		||||
 | 
			
		||||
    def hide(self) -> None:
 | 
			
		||||
        """Stops the animation and clears the canvas."""
 | 
			
		||||
        self.running = False
 | 
			
		||||
        self.pulse_animation = False
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
 | 
			
		||||
    def show_full_circle(self) -> None:
 | 
			
		||||
        """Shows the static 'stopped' frame without starting the animation."""
 | 
			
		||||
        if not self.running:
 | 
			
		||||
            self._draw_stopped_frame()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from PIL import Image, ImageDraw, ImageTk
 | 
			
		||||
    PIL_AVAILABLE = True
 | 
			
		||||
except ImportError:
 | 
			
		||||
    PIL_AVAILABLE = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _hex_to_rgb(hex_color):
 | 
			
		||||
    """Converts a hex color string to an RGB tuple."""
 | 
			
		||||
    hex_color = hex_color.lstrip('#')
 | 
			
		||||
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AnimatedIcon(tk.Canvas):
 | 
			
		||||
    """A custom Tkinter Canvas widget for displaying animations."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, master, width=20, height=20, animation_type="counter_arc", color="#2a6fde", highlight_color="#5195ff", use_pillow=False, bg=None):
 | 
			
		||||
        """
 | 
			
		||||
        Initializes the AnimatedIcon widget.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            master: The parent widget.
 | 
			
		||||
            width (int): The width of the icon.
 | 
			
		||||
            height (int): The height of the icon.
 | 
			
		||||
            animation_type (str): The type of animation to display.
 | 
			
		||||
                Options: "counter_arc", "double_arc", "line", "blink".
 | 
			
		||||
            color (str): The primary color of the icon.
 | 
			
		||||
            highlight_color (str): The highlight color of the icon.
 | 
			
		||||
            use_pillow (bool): Whether to use Pillow for drawing if available.
 | 
			
		||||
            bg (str): The background color of the canvas.
 | 
			
		||||
        """
 | 
			
		||||
        if bg is None:
 | 
			
		||||
            try:
 | 
			
		||||
                bg = master.cget("background")
 | 
			
		||||
            except tk.TclError:
 | 
			
		||||
                bg = "#f0f0f0"  # Fallback color
 | 
			
		||||
        super().__init__(master, width=width, height=height, bg=bg, highlightthickness=0)
 | 
			
		||||
 | 
			
		||||
        self.width = width
 | 
			
		||||
        self.height = height
 | 
			
		||||
        self.animation_type = animation_type
 | 
			
		||||
        self.color = color
 | 
			
		||||
        self.highlight_color = highlight_color
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self.image = Image.new(
 | 
			
		||||
                "RGBA", (width * 4, height * 4), (0, 0, 0, 0))
 | 
			
		||||
            self.draw = ImageDraw.Draw(self.image)
 | 
			
		||||
            self.photo_image = None
 | 
			
		||||
 | 
			
		||||
    def _draw_frame(self):
 | 
			
		||||
        """Draws a single frame of the animation."""
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self._draw_pillow_frame()
 | 
			
		||||
        else:
 | 
			
		||||
            self._draw_canvas_frame()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_frame(self):
 | 
			
		||||
        """Draws a frame using native Tkinter canvas methods."""
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        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()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_canvas_blink()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_pulse(self):
 | 
			
		||||
        """Draws the pulse animation using canvas methods."""
 | 
			
		||||
        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):
 | 
			
		||||
        """Draws the line animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        for i in range(8):
 | 
			
		||||
            angle = self.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)
 | 
			
		||||
            alpha = (cos(self.angle * 2 + i * (pi / 4)) + 1) / 2
 | 
			
		||||
 | 
			
		||||
            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])
 | 
			
		||||
            color = f"#{r:02x}{g:02x}{b:02x}"
 | 
			
		||||
 | 
			
		||||
            self.create_line(start_x, start_y, end_x,
 | 
			
		||||
                             end_y, fill=color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_double_arc(self):
 | 
			
		||||
        """Draws the double arc animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        bbox = (center_x - radius, center_y - radius,
 | 
			
		||||
                center_x + radius, center_y + radius)
 | 
			
		||||
 | 
			
		||||
        start_angle1 = -self.angle * 180 / pi
 | 
			
		||||
        extent1 = 120 + 60 * sin(-self.angle)
 | 
			
		||||
        self.create_arc(bbox, start=start_angle1, extent=extent1,
 | 
			
		||||
                        style=tk.ARC, outline=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
        start_angle2 = (-self.angle + pi) * 180 / pi
 | 
			
		||||
        extent2 = 120 + 60 * sin(-self.angle + pi / 2)
 | 
			
		||||
        self.create_arc(bbox, start=start_angle2, extent=extent2,
 | 
			
		||||
                        style=tk.ARC, outline=self.color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_counter_arc(self):
 | 
			
		||||
        """Draws the counter arc animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        start_angle1 = -self.angle * 180 / pi
 | 
			
		||||
        self.create_arc(bbox_outer, start=start_angle1, extent=150,
 | 
			
		||||
                        style=tk.ARC, outline=self.highlight_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)
 | 
			
		||||
        start_angle2 = self.angle * 180 / pi + 60
 | 
			
		||||
        self.create_arc(bbox_inner, start=start_angle2, extent=150,
 | 
			
		||||
                        style=tk.ARC, outline=self.color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_blink(self):
 | 
			
		||||
        """Draws the blink animation using canvas methods."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        alpha = (sin(self.angle * 2) + 1) / 2  # Slower blinking speed
 | 
			
		||||
        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])
 | 
			
		||||
        blink_color = f"#{r:02x}{g:02x}{b:02x}"
 | 
			
		||||
        self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y +
 | 
			
		||||
                        radius, start=0, extent=359.9, style=tk.ARC, outline=blink_color, width=4)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_frame(self):
 | 
			
		||||
        """Draws a frame using Pillow for anti-aliased graphics."""
 | 
			
		||||
        self.draw.rectangle(
 | 
			
		||||
            [0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0))
 | 
			
		||||
        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()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_pillow_counter_arc()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_pillow_blink()
 | 
			
		||||
 | 
			
		||||
        resized_image = self.image.resize(
 | 
			
		||||
            (self.width, self.height), Image.Resampling.LANCZOS)
 | 
			
		||||
        self.photo_image = ImageTk.PhotoImage(resized_image)
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        self.create_image(0, 0, anchor="nw", image=self.photo_image)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_pulse(self):
 | 
			
		||||
        """Draws the pulse animation using Pillow."""
 | 
			
		||||
        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):
 | 
			
		||||
        """Draws the line animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        for i in range(12):
 | 
			
		||||
            angle = self.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)
 | 
			
		||||
            alpha = (cos(self.angle * 2.5 + i * (pi / 6)) + 1) / 2
 | 
			
		||||
 | 
			
		||||
            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])
 | 
			
		||||
            color = (r, g, b)
 | 
			
		||||
 | 
			
		||||
            self.draw.line([(start_x, start_y), (end_x, end_y)],
 | 
			
		||||
                           fill=color, width=6, joint="curve")
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_double_arc(self):
 | 
			
		||||
        """Draws the double arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        bbox = (center_x - radius, center_y - radius,
 | 
			
		||||
                center_x + radius, center_y + radius)
 | 
			
		||||
 | 
			
		||||
        start_angle1 = self.angle * 180 / pi
 | 
			
		||||
        extent1 = 120 + 60 * sin(self.angle)
 | 
			
		||||
        self.draw.arc(bbox, start=start_angle1, end=start_angle1 +
 | 
			
		||||
                      extent1, fill=self.highlight_color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
        start_angle2 = (self.angle + pi) * 180 / pi
 | 
			
		||||
        extent2 = 120 + 60 * sin(self.angle + pi / 2)
 | 
			
		||||
        self.draw.arc(bbox, start=start_angle2, end=start_angle2 +
 | 
			
		||||
                      extent2, fill=self.color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_counter_arc(self):
 | 
			
		||||
        """Draws the counter arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        start_angle1 = self.angle * 180 / pi
 | 
			
		||||
        self.draw.arc(bbox_outer, start=start_angle1, end=start_angle1 +
 | 
			
		||||
                      150, fill=self.highlight_color_rgb, 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)
 | 
			
		||||
        start_angle2 = -self.angle * 180 / pi + 60
 | 
			
		||||
        self.draw.arc(bbox_inner, start=start_angle2,
 | 
			
		||||
                      end=start_angle2 + 150, fill=self.color_rgb, width=7)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_blink(self):
 | 
			
		||||
        """Draws the blink animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        alpha = (sin(self.angle * 2) + 1) / 2  # Slower blinking speed
 | 
			
		||||
        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])
 | 
			
		||||
        blink_color = (r, g, b)
 | 
			
		||||
        self.draw.arc((center_x - radius, center_y - radius, center_x + radius,
 | 
			
		||||
                      center_y + radius), start=0, end=360, fill=blink_color, width=10)
 | 
			
		||||
 | 
			
		||||
    def _draw_stopped_frame(self):
 | 
			
		||||
        """Draws the icon in its stopped (static) state."""
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
        if self.use_pillow:
 | 
			
		||||
            self._draw_pillow_stopped_frame()
 | 
			
		||||
        else:
 | 
			
		||||
            self._draw_canvas_stopped_frame()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_stopped_frame(self):
 | 
			
		||||
        """Draws the stopped state using canvas methods."""
 | 
			
		||||
        if self.animation_type == "line":
 | 
			
		||||
            self._draw_canvas_line_stopped()
 | 
			
		||||
        elif self.animation_type == "double_arc":
 | 
			
		||||
            self._draw_canvas_double_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_canvas_counter_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_canvas_blink_stopped()
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_line_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the line animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_double_arc_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the double arc animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_color, width=2)
 | 
			
		||||
 | 
			
		||||
    def _draw_canvas_counter_arc_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the counter arc animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        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=self.highlight_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_blink_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the blink animation."""
 | 
			
		||||
        center_x, center_y = self.width / 2, self.height / 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y +
 | 
			
		||||
                        radius, start=0, extent=359.9, style=tk.ARC, outline=self.highlight_color, width=4)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_stopped_frame(self):
 | 
			
		||||
        """Draws the stopped state using Pillow."""
 | 
			
		||||
        self.draw.rectangle(
 | 
			
		||||
            [0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0))
 | 
			
		||||
        if self.animation_type == "line":
 | 
			
		||||
            self._draw_pillow_line_stopped()
 | 
			
		||||
        elif self.animation_type == "double_arc":
 | 
			
		||||
            self._draw_pillow_double_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "counter_arc":
 | 
			
		||||
            self._draw_pillow_counter_arc_stopped()
 | 
			
		||||
        elif self.animation_type == "blink":
 | 
			
		||||
            self._draw_pillow_blink_stopped()
 | 
			
		||||
 | 
			
		||||
        resized_image = self.image.resize(
 | 
			
		||||
            (self.width, self.height), Image.Resampling.LANCZOS)
 | 
			
		||||
        self.photo_image = ImageTk.PhotoImage(resized_image)
 | 
			
		||||
        self.create_image(0, 0, anchor="nw", image=self.photo_image)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_line_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the line animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, width=6, joint="curve")
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_double_arc_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the double arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, width=5)
 | 
			
		||||
 | 
			
		||||
    def _draw_pillow_counter_arc_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the counter arc animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        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=self.highlight_color_rgb, 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_blink_stopped(self):
 | 
			
		||||
        """Draws the stopped state for the blink animation using Pillow."""
 | 
			
		||||
        center_x, center_y = self.width * 2, self.height * 2
 | 
			
		||||
        radius = min(center_x, center_y) * 0.8
 | 
			
		||||
        self.draw.arc((center_x - radius, center_y - radius, center_x + radius,
 | 
			
		||||
                      center_y + radius), start=0, end=360, fill=self.highlight_color_rgb, width=10)
 | 
			
		||||
 | 
			
		||||
    def _animate(self):
 | 
			
		||||
        """The main animation loop."""
 | 
			
		||||
        if self.running:
 | 
			
		||||
            self.angle += 0.1
 | 
			
		||||
            if self.angle > 2 * pi:
 | 
			
		||||
                self.angle -= 2 * pi
 | 
			
		||||
            self._draw_frame()
 | 
			
		||||
            self.after(30, self._animate)
 | 
			
		||||
 | 
			
		||||
    def start(self, pulse=False):
 | 
			
		||||
        """
 | 
			
		||||
        Starts the animation.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            pulse (bool): If True, plays a pulsing animation instead of the main one.
 | 
			
		||||
        """
 | 
			
		||||
        if not self.running:
 | 
			
		||||
            self.pulse_animation = pulse
 | 
			
		||||
            self.running = True
 | 
			
		||||
            self._animate()
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        """Stops the animation and shows the static 'stopped' frame."""
 | 
			
		||||
        self.running = False
 | 
			
		||||
        self.pulse_animation = False
 | 
			
		||||
        self._draw_stopped_frame()
 | 
			
		||||
 | 
			
		||||
    def hide(self):
 | 
			
		||||
        """Stops the animation and clears the canvas."""
 | 
			
		||||
        self.running = False
 | 
			
		||||
        self.pulse_animation = False
 | 
			
		||||
        self.delete("all")
 | 
			
		||||
 | 
			
		||||
    def show_full_circle(self):
 | 
			
		||||
        """Shows the static 'stopped' frame without starting the animation."""
 | 
			
		||||
        if not self.running:
 | 
			
		||||
            self._draw_stopped_frame()
 | 
			
		||||
							
								
								
									
										13
									
								
								logger.py
									
									
									
									
									
								
							
							
						
						@@ -1,13 +0,0 @@
 | 
			
		||||
class Logger:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self._log_func = print  # Default to print if not initialized
 | 
			
		||||
 | 
			
		||||
    def init_logger(self, log_func):
 | 
			
		||||
        self._log_func = log_func
 | 
			
		||||
 | 
			
		||||
    def log(self, message):
 | 
			
		||||
        self._log_func(message)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Global instance
 | 
			
		||||
app_logger = Logger()
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 5.7 KiB  | 
| 
		 Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.7 KiB  | 
| 
		 Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 4.5 KiB  | 
| 
		 Before Width: | Height: | Size: 7.0 KiB  | 
| 
		 Before Width: | Height: | Size: 64 KiB  | 
| 
		 Before Width: | Height: | Size: 64 KiB  | 
| 
		 Before Width: | Height: | Size: 3.5 KiB  | 
| 
		 Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 697 B  | 
| 
		 Before Width: | Height: | Size: 40 KiB  | 
| 
		 Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 10 KiB  | 
| 
		 Before Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 257 KiB  | 
| 
		 Before Width: | Height: | Size: 257 KiB  | 
| 
		 Before Width: | Height: | Size: 257 KiB  | 
| 
		 Before Width: | Height: | Size: 6.2 KiB  | 
| 
		 Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 662 B  | 
| 
		 Before Width: | Height: | Size: 661 B  | 
| 
		 Before Width: | Height: | Size: 4.9 KiB  | 
| 
		 Before Width: | Height: | Size: 969 B  | 
| 
		 Before Width: | Height: | Size: 665 B  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1014 B  | 
| 
		 Before Width: | Height: | Size: 524 B  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 5.1 KiB  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 939 B  | 
| 
		 Before Width: | Height: | Size: 995 B  | 
| 
		 Before Width: | Height: | Size: 1021 B  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 971 B  | 
| 
		 Before Width: | Height: | Size: 766 B  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 546 B  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.6 KiB  | 
| 
		 Before Width: | Height: | Size: 801 B  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 906 B  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 1.4 KiB  | 
| 
		 Before Width: | Height: | Size: 1.5 KiB  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 978 B  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 4.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB  | 
| 
		 Before Width: | Height: | Size: 760 B  | 
| 
		 Before Width: | Height: | Size: 838 B  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 6.1 KiB  | 
| 
		 Before Width: | Height: | Size: 5.8 KiB  | 
| 
		 Before Width: | Height: | Size: 3.5 KiB  | 
| 
		 Before Width: | Height: | Size: 875 B  | 
| 
		 Before Width: | Height: | Size: 816 B  | 
| 
		 Before Width: | Height: | Size: 10 KiB  |