Skip to main content

agg_gui/widgets/on_screen_keyboard/
style.rs

1//! Visual styling — colors, radii, spacings — keyed by the user's input
2//! profile (iOS / Android / generic mobile).
3//!
4//! Kept as a flat data struct so the layout engine never branches on the
5//! profile — it just reads tokens off the [`Style`]. Future themes
6//! (dark mode, high-contrast, brand variants) plug in here.
7
8use crate::color::Color;
9use crate::input_profile::InputProfile;
10
11/// Tokens consumed by the keyboard painters.
12#[derive(Debug, Clone, Copy)]
13pub struct Style {
14    // ── Panel
15    /// Color behind all keys.
16    pub panel_bg: Color,
17    /// Hairline at the top edge of the panel.
18    pub panel_top_border: Color,
19    /// Padding around the key grid.
20    pub panel_padding_horizontal: f64,
21    pub panel_padding_top: f64,
22    pub panel_padding_bottom: f64,
23    /// Total height target per row of keys (logical pixels).
24    pub row_height: f64,
25    /// Gap between adjacent keys in a row.
26    pub key_h_gap: f64,
27    /// Gap between rows.
28    pub key_v_gap: f64,
29    /// Key corner radius.
30    pub key_corner_radius: f64,
31
32    // ── Standard key
33    pub key_face_bg: Color,
34    pub key_face_bg_pressed: Color,
35    pub key_face_text: Color,
36    pub key_face_text_pressed: Color,
37    pub key_shadow: Color,
38    pub key_shadow_offset_y: f64,
39    /// Font size for letter caps (digits + symbols inherit this).
40    pub letter_font_size: f64,
41    /// Font size for utility key labels ("space", "return", "ABC", "123").
42    pub utility_font_size: f64,
43
44    // ── Utility key (shift / backspace / mode / return)
45    pub util_key_bg: Color,
46    pub util_key_bg_pressed: Color,
47    pub util_key_text: Color,
48    /// Accent applied to the Return key (matches platform send-button color).
49    pub return_key_bg: Color,
50    pub return_key_text: Color,
51    pub return_key_bg_pressed: Color,
52}
53
54impl Style {
55    /// Pick the style appropriate for the active input profile.
56    pub fn for_profile(profile: InputProfile) -> Self {
57        match profile {
58            InputProfile::MobileIOS => ios(),
59            InputProfile::MobileAndroid => android(),
60            // Desktop never paints the keyboard, but fall through to
61            // a neutral default in case the host enabled it anyway
62            // (e.g. an unrecognised tablet, or testing on desktop).
63            InputProfile::Desktop | InputProfile::MobileOther => neutral(),
64        }
65    }
66}
67
68fn ios() -> Style {
69    Style {
70        panel_bg: Color::from_rgb8(0xD1, 0xD5, 0xDB), // iOS light gray tray
71        panel_top_border: Color::from_rgba8(0, 0, 0, 0x33),
72        panel_padding_horizontal: 4.0,
73        panel_padding_top: 8.0,
74        panel_padding_bottom: 18.0, // home-indicator safe area
75        row_height: 44.0,
76        key_h_gap: 6.0,
77        key_v_gap: 10.0,
78        key_corner_radius: 5.0,
79        key_face_bg: Color::from_rgb8(0xFE, 0xFE, 0xFE),
80        key_face_bg_pressed: Color::from_rgb8(0xBC, 0xC0, 0xC9),
81        key_face_text: Color::from_rgb8(0x10, 0x10, 0x18),
82        key_face_text_pressed: Color::from_rgb8(0x10, 0x10, 0x18),
83        key_shadow: Color::from_rgba8(0, 0, 0, 0x4D),
84        key_shadow_offset_y: -1.0, // Y-up: shadow paints below = -Y
85        letter_font_size: 22.0,
86        utility_font_size: 15.0,
87        util_key_bg: Color::from_rgb8(0xAB, 0xB0, 0xBC),
88        util_key_bg_pressed: Color::from_rgb8(0xFE, 0xFE, 0xFE),
89        util_key_text: Color::from_rgb8(0x10, 0x10, 0x18),
90        return_key_bg: Color::from_rgb8(0x00, 0x7A, 0xFF), // iOS system blue
91        return_key_text: Color::from_rgb8(0xFF, 0xFF, 0xFF),
92        return_key_bg_pressed: Color::from_rgb8(0x00, 0x57, 0xBE),
93    }
94}
95
96fn android() -> Style {
97    Style {
98        panel_bg: Color::from_rgb8(0x20, 0x20, 0x24), // Material dark surface
99        panel_top_border: Color::from_rgba8(0xFF, 0xFF, 0xFF, 0x14),
100        panel_padding_horizontal: 4.0,
101        panel_padding_top: 6.0,
102        panel_padding_bottom: 14.0,
103        row_height: 48.0,
104        key_h_gap: 4.0,
105        key_v_gap: 6.0,
106        key_corner_radius: 6.0,
107        key_face_bg: Color::from_rgb8(0x2C, 0x2C, 0x32), // Material slightly raised
108        key_face_bg_pressed: Color::from_rgb8(0x43, 0x47, 0x55),
109        key_face_text: Color::from_rgb8(0xE8, 0xEA, 0xF0),
110        key_face_text_pressed: Color::from_rgb8(0xFF, 0xFF, 0xFF),
111        key_shadow: Color::from_rgba8(0, 0, 0, 0x60),
112        key_shadow_offset_y: -1.0,
113        letter_font_size: 20.0,
114        utility_font_size: 14.0,
115        util_key_bg: Color::from_rgb8(0x1A, 0x1A, 0x1E),
116        util_key_bg_pressed: Color::from_rgb8(0x33, 0x36, 0x3E),
117        util_key_text: Color::from_rgb8(0xC4, 0xCB, 0xDB),
118        return_key_bg: Color::from_rgb8(0x1A, 0x73, 0xE8), // Material blue 600
119        return_key_text: Color::from_rgb8(0xFF, 0xFF, 0xFF),
120        return_key_bg_pressed: Color::from_rgb8(0x12, 0x5A, 0xC0),
121    }
122}
123
124fn neutral() -> Style {
125    Style {
126        panel_bg: Color::from_rgb8(0x18, 0x18, 0x22),
127        panel_top_border: Color::from_rgba8(0xFF, 0xFF, 0xFF, 0x33),
128        panel_padding_horizontal: 4.0,
129        panel_padding_top: 8.0,
130        panel_padding_bottom: 12.0,
131        row_height: 46.0,
132        key_h_gap: 5.0,
133        key_v_gap: 8.0,
134        key_corner_radius: 6.0,
135        key_face_bg: Color::from_rgb8(0x2A, 0x2B, 0x36),
136        key_face_bg_pressed: Color::from_rgb8(0x44, 0x46, 0x55),
137        key_face_text: Color::from_rgb8(0xE7, 0xE8, 0xF0),
138        key_face_text_pressed: Color::from_rgb8(0xFF, 0xFF, 0xFF),
139        key_shadow: Color::from_rgba8(0, 0, 0, 0x55),
140        key_shadow_offset_y: -1.0,
141        letter_font_size: 20.0,
142        utility_font_size: 14.0,
143        util_key_bg: Color::from_rgb8(0x1F, 0x20, 0x2A),
144        util_key_bg_pressed: Color::from_rgb8(0x33, 0x36, 0x44),
145        util_key_text: Color::from_rgb8(0xC4, 0xC7, 0xD5),
146        return_key_bg: Color::from_rgb8(0x3B, 0x82, 0xF6),
147        return_key_text: Color::from_rgb8(0xFF, 0xFF, 0xFF),
148        return_key_bg_pressed: Color::from_rgb8(0x2B, 0x66, 0xD0),
149    }
150}