Skip to main content

custom_colors/
custom_colors.rs

1//! Demonstrates the RGB color capabilities with beautiful gradients and color transitions.
2
3use minui::Window;
4use minui::define_colors;
5use minui::prelude::*;
6
7// Define some custom RGB color schemes
8define_colors! {
9    // Sunset theme
10    pub const SUNSET_ORANGE = (Color::rgb(255, 165, 0), Color::Black);
11    pub const SUNSET_RED = (Color::rgb(255, 69, 0), Color::Black);
12    pub const SUNSET_PURPLE = (Color::rgb(148, 0, 211), Color::Black);
13
14    // Ocean theme
15    pub const OCEAN_DEEP = (Color::rgb(0, 105, 148), Color::Black);
16    pub const OCEAN_MEDIUM = (Color::rgb(0, 191, 255), Color::Black);
17    pub const OCEAN_LIGHT = (Color::rgb(173, 216, 230), Color::Black);
18
19    // Forest theme
20    pub const FOREST_DARK = (Color::rgb(34, 139, 34), Color::Black);
21    pub const FOREST_BRIGHT = (Color::rgb(124, 252, 0), Color::Black);
22
23    // Neon theme
24    pub const NEON_PINK = (Color::rgb(255, 20, 147), Color::Black);
25    pub const NEON_CYAN = (Color::rgb(0, 255, 255), Color::Black);
26    pub const NEON_GREEN = (Color::rgb(57, 255, 20), Color::Black);
27}
28
29/// Example showing RGB colors, gradients, and custom color schemes.
30///
31/// This example demonstrates:
32/// 1. Creating RGB colors with custom values
33/// 2. Generating smooth color gradients
34/// 3. Using predefined color schemes
35/// 4. Creating visual effects with colors
36fn main() -> minui::Result<()> {
37    let mut app = App::new(())?;
38
39    app.run(
40        |_state, event| {
41            // Return false to exit.
42            //
43            // The keyboard handler may emit:
44            // - `Event::KeyWithModifiers(KeyKind::Char('q'))` (modifier-aware), or
45            // - `Event::Character('q')` (legacy fallback).
46            match event {
47                Event::KeyWithModifiers(k) if matches!(k.key, KeyKind::Char('q')) => false,
48                Event::Character('q') => false,
49                _ => true,
50            }
51        },
52        |_state, window| {
53            let (width, height) = window.get_size();
54
55            // Title
56            window.write_str(0, 0, "RGB Color & Gradient Demo (press 'q' to quit)")?;
57
58            // --- All drawing calls happen here ---
59            draw_rainbow_gradient(window, 2, width)?;
60            draw_color_themes(window, 6)?;
61            draw_vertical_gradient(window, 12, width, height)?;
62            draw_color_blocks(window, height)?;
63
64            window.end_frame()?;
65            Ok(())
66        },
67    )?;
68
69    Ok(())
70}
71
72fn draw_rainbow_gradient(window: &mut dyn Window, start_y: u16, width: u16) -> minui::Result<()> {
73    window.write_str(start_y, 0, "Rainbow Gradient:")?;
74
75    let gradient_y = start_y + 1;
76    let gradient_width = (width - 2).min(60); // Limit width for better display
77
78    for x in 0..gradient_width {
79        // Create a rainbow effect by cycling through hue
80        let hue = (x as f32 / gradient_width as f32) * 360.0;
81        let (r, g, b) = hsl_to_rgb(hue, 1.0, 0.5);
82
83        let color = ColorPair::new(Color::rgb(r, g, b), Color::Black);
84        window.write_str_colored(gradient_y, x + 1, "█", color)?;
85    }
86
87    Ok(())
88}
89
90fn draw_color_themes(window: &mut dyn Window, start_y: u16) -> minui::Result<()> {
91    window.write_str(start_y, 0, "Color Themes:")?;
92
93    // Sunset theme
94    window.write_str(start_y + 1, 0, "Sunset: ")?;
95    window.write_str_colored(start_y + 1, 8, "█████", SUNSET_ORANGE)?;
96    window.write_str_colored(start_y + 1, 13, "█████", SUNSET_RED)?;
97    window.write_str_colored(start_y + 1, 18, "█████", SUNSET_PURPLE)?;
98
99    // Ocean theme
100    window.write_str(start_y + 2, 0, "Ocean:  ")?;
101    window.write_str_colored(start_y + 2, 8, "█████", OCEAN_DEEP)?;
102    window.write_str_colored(start_y + 2, 13, "█████", OCEAN_MEDIUM)?;
103    window.write_str_colored(start_y + 2, 18, "█████", OCEAN_LIGHT)?;
104
105    // Forest theme
106    window.write_str(start_y + 3, 0, "Forest: ")?;
107    window.write_str_colored(start_y + 3, 8, "█████", FOREST_DARK)?;
108    window.write_str_colored(start_y + 3, 13, "█████", FOREST_BRIGHT)?;
109
110    // Neon theme
111    window.write_str(start_y + 4, 0, "Neon:   ")?;
112    window.write_str_colored(start_y + 4, 8, "█████", NEON_PINK)?;
113    window.write_str_colored(start_y + 4, 13, "█████", NEON_CYAN)?;
114    window.write_str_colored(start_y + 4, 18, "█████", NEON_GREEN)?;
115
116    Ok(())
117}
118
119fn draw_vertical_gradient(
120    window: &mut dyn Window,
121    start_y: u16,
122    width: u16,
123    height: u16,
124) -> minui::Result<()> {
125    if start_y + 10 > height {
126        return Ok(()); // Not enough space
127    }
128
129    window.write_str(start_y, 0, "Vertical Blue-to-Red Gradient:")?;
130
131    let gradient_height = (height - start_y - 2).min(8);
132    let gradient_width = (width - 2).min(30);
133
134    for y in 0..gradient_height {
135        let ratio = y as f32 / gradient_height as f32;
136
137        // Interpolate from blue to red
138        let r = (ratio * 255.0) as u8;
139        let g = 0;
140        let b = ((1.0 - ratio) * 255.0) as u8;
141
142        let color = ColorPair::new(Color::rgb(r, g, b), Color::Black);
143
144        for x in 0..gradient_width {
145            window.write_str_colored(start_y + 1 + y, x + 1, "█", color)?;
146        }
147    }
148
149    Ok(())
150}
151
152fn draw_color_blocks(window: &mut dyn Window, height: u16) -> minui::Result<()> {
153    let start_y = height.saturating_sub(6);
154
155    window.write_str(start_y, 0, "RGB Color Examples:")?;
156
157    // Show some specific RGB values with labels
158    let colors = [
159        (Color::rgb(255, 0, 0), "Pure Red (255,0,0)"),
160        (Color::rgb(0, 255, 0), "Pure Green (0,255,0)"),
161        (Color::rgb(0, 0, 255), "Pure Blue (0,0,255)"),
162        (Color::rgb(255, 255, 0), "Yellow (255,255,0)"),
163        (Color::rgb(255, 0, 255), "Magenta (255,0,255)"),
164        (Color::rgb(0, 255, 255), "Cyan (0,255,255)"),
165    ];
166
167    for (i, (color, label)) in colors.iter().enumerate() {
168        let y = start_y + 1 + (i as u16 / 3);
169        let x = (i % 3) * 25;
170
171        let color_pair = ColorPair::new(*color, Color::Black);
172        window.write_str_colored(y, x as u16, "███", color_pair)?;
173        window.write_str(y, x as u16 + 4, label)?;
174    }
175
176    Ok(())
177}
178
179/// Convert HSL (Hue, Saturation, Lightness) to RGB
180/// This helps create smooth color gradients
181fn hsl_to_rgb(h: f32, s: f32, l: f32) -> (u8, u8, u8) {
182    let h = h / 60.0;
183    let c = (1.0 - (2.0 * l - 1.0).abs()) * s;
184    let x = c * (1.0 - (h % 2.0 - 1.0).abs());
185    let m = l - c / 2.0;
186
187    let (r_prime, g_prime, b_prime) = if h < 1.0 {
188        (c, x, 0.0)
189    } else if h < 2.0 {
190        (x, c, 0.0)
191    } else if h < 3.0 {
192        (0.0, c, x)
193    } else if h < 4.0 {
194        (0.0, x, c)
195    } else if h < 5.0 {
196        (x, 0.0, c)
197    } else {
198        (c, 0.0, x)
199    };
200
201    let r = ((r_prime + m) * 255.0) as u8;
202    let g = ((g_prime + m) * 255.0) as u8;
203    let b = ((b_prime + m) * 255.0) as u8;
204
205    (r, g, b)
206}