#!/usr/bin/env python3 """ Generate a simple icon for Path Juggler. Creates an .icns file for use with the macOS app bundle. Requires: pip install Pillow """ import subprocess import tempfile from pathlib import Path try: from PIL import Image, ImageDraw except ImportError: print("Pillow not installed. Install with: pip3 install Pillow") print("Or skip icon generation - the app will use a default icon.") exit(1) def create_icon_image(size: int) -> Image.Image: """Create a single icon image at the given size.""" img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # Background - purple/blue gradient-like color (juggler theme) margin = int(size * 0.08) radius = int(size * 0.18) # Draw rounded rectangle background draw.rounded_rectangle( [margin, margin, size - margin, size - margin], radius=radius, fill=(88, 86, 214, 255) # Purple-blue ) center_x = size // 2 center_y = size // 2 # Draw three "juggling balls" in an arc ball_radius = int(size * 0.09) arc_radius = int(size * 0.22) # Ball positions (arc above center) balls = [ (center_x - arc_radius, center_y - int(size * 0.08)), # Left (center_x, center_y - int(size * 0.18)), # Top center (center_x + arc_radius, center_y - int(size * 0.08)), # Right ] ball_colors = [ (255, 107, 107, 255), # Red/coral (78, 205, 196, 255), # Teal (255, 230, 109, 255), # Yellow ] for (bx, by), color in zip(balls, ball_colors): draw.ellipse( [bx - ball_radius, by - ball_radius, bx + ball_radius, by + ball_radius], fill=color ) # Draw path arrows (two crossing paths) arrow_color = (255, 255, 255, 200) line_width = max(2, int(size * 0.025)) # Left-to-right arrow arrow_y = center_y + int(size * 0.15) arrow_start = margin + int(size * 0.1) arrow_end = size - margin - int(size * 0.1) draw.line( [(arrow_start, arrow_y), (arrow_end - int(size * 0.08), arrow_y)], fill=arrow_color, width=line_width ) # Arrow head head_size = int(size * 0.06) draw.polygon([ (arrow_end, arrow_y), (arrow_end - head_size, arrow_y - head_size // 2), (arrow_end - head_size, arrow_y + head_size // 2), ], fill=arrow_color) return img def create_icns(output_path: Path): """Create an .icns file with all required sizes.""" sizes = [16, 32, 64, 128, 256, 512, 1024] with tempfile.TemporaryDirectory() as tmpdir: iconset_path = Path(tmpdir) / "icon.iconset" iconset_path.mkdir() for size in sizes: img = create_icon_image(size) img.save(iconset_path / f"icon_{size}x{size}.png") if size <= 512: img_2x = create_icon_image(size * 2) img_2x.save(iconset_path / f"icon_{size}x{size}@2x.png") result = subprocess.run( ["iconutil", "-c", "icns", str(iconset_path), "-o", str(output_path)], capture_output=True, text=True ) if result.returncode != 0: print(f"iconutil failed: {result.stderr}") return False return True def main(): script_dir = Path(__file__).parent output_path = script_dir / "AppIcon.icns" print("Generating Path Juggler icon...") if create_icns(output_path): print(f"Icon created: {output_path}") print("\nTo use this icon in the build:") print("1. Edit build_app.sh") print("2. Find the line: icon=None,") print("3. Change it to: icon='AppIcon.icns',") else: print("Failed to create icon") if __name__ == "__main__": main()