Skip to main content

cvkg_render_native/
contracts.rs

1/// Rendering mode for a widget.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum RenderingMode {
4    /// Use native platform controls (buttons, text fields, etc.).
5    Native,
6    /// Use CVKG's GPU renderer for custom-drawn content.
7    Custom,
8    /// Hybrid: native container with custom rendering inside.
9    Hybrid,
10}
11
12/// Translation contract for a CVKG widget to its native representation.
13#[derive(Debug, Clone)]
14pub struct TranslationContract {
15    /// CVKG widget type name.
16    pub cvkg_type: &'static str,
17    /// Platform-specific type name (e.g., "NSView", "HWND", "GTKWidget").
18    pub platform_type: &'static str,
19    /// Whether this widget uses native controls or custom rendering.
20    pub rendering_mode: RenderingMode,
21    /// Whether accessibility is handled natively.
22    pub native_accessibility: bool,
23}
24
25/// Registry of translation contracts for all widget types.
26pub struct TranslationContractRegistry {
27    contracts: Vec<TranslationContract>,
28}
29
30impl TranslationContractRegistry {
31    /// Creates a new translation contract registry.
32    pub fn new() -> Self {
33        Self {
34            contracts: vec![
35                TranslationContract {
36                    cvkg_type: "Button",
37                    platform_type: "NSButton/Button/GTKButton",
38                    rendering_mode: RenderingMode::Native,
39                    native_accessibility: true,
40                },
41                TranslationContract {
42                    cvkg_type: "TextInput",
43                    platform_type: "NSTextField/TextBox/GTKEntry",
44                    rendering_mode: RenderingMode::Native,
45                    native_accessibility: true,
46                },
47                TranslationContract {
48                    cvkg_type: "Canvas",
49                    platform_type: "NSView/HWND/GtkDrawingArea",
50                    rendering_mode: RenderingMode::Custom,
51                    native_accessibility: false,
52                },
53                TranslationContract {
54                    cvkg_type: "TreeView",
55                    platform_type: "NSTableView/TreeView/GTKTreeView",
56                    rendering_mode: RenderingMode::Hybrid,
57                    native_accessibility: true,
58                },
59            ],
60        }
61    }
62
63    /// Look up the contract for a CVKG widget type.
64    pub fn find(&self, cvkg_type: &str) -> Option<&TranslationContract> {
65        self.contracts.iter().find(|c| c.cvkg_type == cvkg_type)
66    }
67}
68
69impl Default for TranslationContractRegistry {
70    fn default() -> Self {
71        Self::new()
72    }
73}
74
75/// Bidirectional state synchronization between CVKG and native widgets.
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub enum SyncDirection {
78    /// CVKG state drives native widget.
79    CvkgToNative,
80    /// Native widget state drives CVKG.
81    NativeToCvkg,
82    /// Both directions.
83    Bidirectional,
84}
85
86/// State synchronization contract for a widget.
87#[derive(Debug, Clone)]
88pub struct StateSyncContract {
89    /// Widget type name.
90    pub widget_type: &'static str,
91    /// Synchronization direction.
92    pub direction: SyncDirection,
93    /// Whether to debounce rapid changes.
94    pub debounce: bool,
95    /// Debounce interval in milliseconds.
96    pub debounce_ms: u64,
97}
98
99/// Registry of state synchronization contracts.
100pub struct StateSyncRegistry {
101    contracts: Vec<StateSyncContract>,
102}
103
104impl StateSyncRegistry {
105    /// Creates a new state sync registry.
106    pub fn new() -> Self {
107        Self {
108            contracts: vec![
109                StateSyncContract {
110                    widget_type: "Button",
111                    direction: SyncDirection::Bidirectional,
112                    debounce: false,
113                    debounce_ms: 0,
114                },
115                StateSyncContract {
116                    widget_type: "TextInput",
117                    direction: SyncDirection::Bidirectional,
118                    debounce: true,
119                    debounce_ms: 50,
120                },
121                StateSyncContract {
122                    widget_type: "Slider",
123                    direction: SyncDirection::Bidirectional,
124                    debounce: true,
125                    debounce_ms: 16,
126                },
127                StateSyncContract {
128                    widget_type: "Checkbox",
129                    direction: SyncDirection::Bidirectional,
130                    debounce: false,
131                    debounce_ms: 0,
132                },
133            ],
134        }
135    }
136
137    /// Finds a state sync contract for a widget type.
138    pub fn find(&self, widget_type: &str) -> Option<&StateSyncContract> {
139        self.contracts.iter().find(|c| c.widget_type == widget_type)
140    }
141}
142
143impl Default for StateSyncRegistry {
144    fn default() -> Self {
145        Self::new()
146    }
147}
148
149/// Widget virtualization configuration for UIs.
150#[derive(Debug, Clone, Copy)]
151pub struct WidgetVirtualizationConfig {
152    /// Number of widgets to render outside the viewport (buffer).
153    pub buffer_size: usize,
154    /// Whether to recycle widget native handles.
155    pub recycle_handles: bool,
156    /// Maximum number of active native handles.
157    pub max_active_handles: usize,
158}
159
160impl Default for WidgetVirtualizationConfig {
161    fn default() -> Self {
162        Self {
163            buffer_size: 5,
164            recycle_handles: true,
165            max_active_handles: 100,
166        }
167    }
168}
169
170/// Explicit mapping from AccessKit/CVKG role to platform accessibility concepts:
171/// macOS (AXRole), Windows (UIA ControlType), and Linux (ATK Role).
172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub struct SemanticRoleMapping {
174    /// The input AccessKit role.
175    pub role: accesskit::Role,
176    /// macOS AXRole string.
177    pub mac_ax_role: &'static str,
178    /// Windows UI Automation ControlType constant name or ID string.
179    pub win_uia_control_type: &'static str,
180    /// Linux ATK Role constant name or ID string.
181    pub linux_atk_role: &'static str,
182}
183
184/// Registry of semantic accessibility mappings.
185pub struct SemanticRoleRegistry {
186    mappings: Vec<SemanticRoleMapping>,
187}
188
189impl SemanticRoleRegistry {
190    /// Creates a new semantic role registry.
191    pub fn new() -> Self {
192        Self {
193            mappings: vec![
194                SemanticRoleMapping {
195                    role: accesskit::Role::Button,
196                    mac_ax_role: "AXButton",
197                    win_uia_control_type: "UIA_ButtonControlTypeId",
198                    linux_atk_role: "ATK_ROLE_PUSH_BUTTON",
199                },
200                SemanticRoleMapping {
201                    role: accesskit::Role::TextInput,
202                    mac_ax_role: "AXTextField",
203                    win_uia_control_type: "UIA_EditControlTypeId",
204                    linux_atk_role: "ATK_ROLE_ENTRY",
205                },
206                SemanticRoleMapping {
207                    role: accesskit::Role::CheckBox,
208                    mac_ax_role: "AXCheckBox",
209                    win_uia_control_type: "UIA_CheckBoxControlTypeId",
210                    linux_atk_role: "ATK_ROLE_CHECK_BOX",
211                },
212                SemanticRoleMapping {
213                    role: accesskit::Role::Slider,
214                    mac_ax_role: "AXSlider",
215                    win_uia_control_type: "UIA_SliderControlTypeId",
216                    linux_atk_role: "ATK_ROLE_SLIDER",
217                },
218                SemanticRoleMapping {
219                    role: accesskit::Role::Label,
220                    mac_ax_role: "AXStaticText",
221                    win_uia_control_type: "UIA_TextControlTypeId",
222                    linux_atk_role: "ATK_ROLE_LABEL",
223                },
224            ],
225        }
226    }
227
228    /// Look up the platform mappings for a given role.
229    pub fn find(&self, role: accesskit::Role) -> Option<&SemanticRoleMapping> {
230        self.mappings.iter().find(|m| m.role == role)
231    }
232}
233
234impl Default for SemanticRoleRegistry {
235    fn default() -> Self {
236        Self::new()
237    }
238}