1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/// Events emitted by the app to the host/wrapper
/// The host handles these platform-specifically (file dialogs, menus, etc.)
#[derive(Debug, Clone, PartialEq)]
pub enum AppEvent {
/// Request to save current project
/// Host should: Show save dialog (if needed), call save_to_json(), write file
/// filename: default filename without extension (e.g., "myproject")
/// extension: file extension (e.g., "json", "denrim")
RequestSave { filename: String, extension: String },
/// Request to save with new name/location
/// Host should: Show "Save As" dialog, call save_to_json(), write file
/// filename: default filename without extension (e.g., "myproject")
/// extension: file extension (e.g., "json", "denrim")
RequestSaveAs { filename: String, extension: String },
/// Request to open a project
/// Host should: Show open dialog, read file, call load_from_json()
/// extension: file extension to filter (e.g., "json", "denrim")
RequestOpen { extension: String },
/// Request to create new project
/// Host should: Prompt to save current (if dirty), call new_project()
RequestNew,
/// Request to close current project
/// Host should: Prompt to save (if dirty), close window/document
RequestClose,
/// Request to export project in different format
/// Host should: Show export dialog with format options
RequestExport { format: String, filename: String },
/// Request to import file(s) into current project
/// Host should: Show import dialog for specified file types, read files, pass data to app
RequestImport { file_types: Vec<String> },
/// Request to show project browser/gallery
/// Host should: Show browser UI or switch to browser mode
RequestShowBrowser,
/// App state changed (for dirty tracking)
/// Host should: Update window title, enable save button, etc.
StateChanged { has_unsaved_changes: bool },
/// Request to perform undo operation
/// Host should: Call app's undo() method
RequestUndo,
/// Request to perform redo operation
/// Host should: Call app's redo() method
RequestRedo,
}
/// Queue for app events that will be consumed by the host
#[derive(Default)]
pub struct AppEventQueue {
events: Vec<AppEvent>,
}
impl AppEventQueue {
pub fn new() -> Self {
Self { events: Vec::new() }
}
/// Emit an event to the host
pub fn emit(&mut self, event: AppEvent) {
self.events.push(event);
}
/// Take all pending events (consumes them)
pub fn take(&mut self) -> Vec<AppEvent> {
std::mem::take(&mut self.events)
}
/// Check if there are pending events
pub fn has_events(&self) -> bool {
!self.events.is_empty()
}
/// Peek at events without consuming
pub fn peek(&self) -> &[AppEvent] {
&self.events
}
}