#!/usr/bin/env python3

# Pygame color chart - hover a color to see RGB, HSV, and CMY
# (C) 2026, bensnotebook.net
# Released under MIT License
# v2.0

import pygame
from sys import exit
from math import ceil
pygame.init()

SQUARE_SIZE = 32
ROW_LENGTH = 30
TEXT_HEIGHT = 28
TEXT_COLOR = pygame.Color(255, 255, 255)
CURSOR_COLOR = pygame.Color(240, 240, 0)
COLORS = list(pygame.color.THECOLORS.items())

WINDOW_WIDTH = SQUARE_SIZE * ROW_LENGTH
WINDOW_HEIGHT = SQUARE_SIZE * ceil(len(COLORS) / ROW_LENGTH) + TEXT_HEIGHT
pygame.display.set_caption(f"View the {len(COLORS)} named Pygame colors")
display = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
font = pygame.font.Font(None, TEXT_HEIGHT)
background = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT)).convert()
clock = pygame.time.Clock()

def round3(x):
    return round(x, 3)

x = y = 0
for c in COLORS:
    pygame.draw.rect(background, c[1], (x, y, SQUARE_SIZE, SQUARE_SIZE))
    x += SQUARE_SIZE
    if x == display.get_width():
        x = 0
        y += SQUARE_SIZE
display.blit(background, (0, 0))
dirty = True

idx = -1
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            pygame.quit()
            exit()
        
        elif event.type == pygame.MOUSEMOTION:
            (x, y) = event.pos
            idx = (x // SQUARE_SIZE) + ROW_LENGTH * (y // SQUARE_SIZE)
            if idx >= len(COLORS):
                idx = None
                continue
            
            (color_name, color) = COLORS[idx]
            color = pygame.Color(color[0], color[1], color[2])
            color_rgb = f"RGB {str(color[:3])}"
            color_hsv = f"HSV {str(tuple(map(round, color.hsva[:3])))}"
            color_cmy = f"CMY {str(tuple(map(round3, color.cmy)))}"
            text = "       ".join((color_name, color_rgb, color_hsv, color_cmy))
            
            display.blit(background, (0, 0))
            text_surface = font.render(text, True, TEXT_COLOR)
            text_rect = text_surface.get_rect()
            text_rect.midbottom = (WINDOW_WIDTH // 2, WINDOW_HEIGHT)
            display.blit(text_surface, text_rect)
            cursor_rect = (x - x % SQUARE_SIZE,
                           y - y % SQUARE_SIZE,
                           SQUARE_SIZE,
                           SQUARE_SIZE)
            pygame.draw.rect(display, CURSOR_COLOR, cursor_rect, width=2)
            dirty = True
    
    if idx is None or (not pygame.mouse.get_focused() and idx is not None):
        idx = None
        display.blit(background, (0, 0))
        dirty = True

    if dirty:
        pygame.display.flip()
        dirty = False

    clock.tick(20)
