154 lines
7.5 KiB
Rust
154 lines
7.5 KiB
Rust
use muda::{CheckMenuItem, Menu, MenuEvent, MenuItem, PredefinedMenuItem, Submenu, accelerator::Accelerator};
|
|
use muda::accelerator::{Code, Modifiers};
|
|
|
|
pub const AP_PAREN: u32 = 1;
|
|
pub const AP_BRACKET: u32 = 2;
|
|
pub const AP_BRACE: u32 = 4;
|
|
pub const AP_SINGLE: u32 = 8;
|
|
pub const AP_DOUBLE: u32 = 16;
|
|
pub const AP_BACKTICK: u32 = 32;
|
|
|
|
pub struct AppMenu {
|
|
#[allow(dead_code)]
|
|
pub menu: Menu,
|
|
auto_pair_items: Vec<(u32, CheckMenuItem)>,
|
|
}
|
|
|
|
pub enum MenuAction {
|
|
NewNote,
|
|
Open,
|
|
Save,
|
|
SaveAs,
|
|
Quit,
|
|
Undo,
|
|
Redo,
|
|
Bold,
|
|
Italic,
|
|
InsertTable,
|
|
Evaluate,
|
|
LiveMode,
|
|
EditorMode,
|
|
ViewMode,
|
|
ZoomIn,
|
|
ZoomOut,
|
|
ZoomReset,
|
|
Find,
|
|
Settings,
|
|
ExportCrate,
|
|
ToggleAutoPair(u32),
|
|
ToggleBrowser,
|
|
}
|
|
|
|
impl AppMenu {
|
|
pub fn new(auto_pair_flags: u32) -> Self {
|
|
let menu = Menu::new();
|
|
|
|
let file = Submenu::new("File", true);
|
|
file.append(&MenuItem::with_id("new", "New Note", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyN)))).ok();
|
|
file.append(&MenuItem::with_id("open", "Open...", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyO)))).ok();
|
|
file.append(&MenuItem::with_id("browse", "Documents...", true, Some(Accelerator::new(Some(Modifiers::ALT), Code::KeyB)))).ok();
|
|
file.append(&PredefinedMenuItem::separator()).ok();
|
|
file.append(&MenuItem::with_id("save", "Save", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyS)))).ok();
|
|
file.append(&MenuItem::with_id("save_as", "Save As...", true, Some(Accelerator::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyS)))).ok();
|
|
file.append(&PredefinedMenuItem::separator()).ok();
|
|
file.append(&MenuItem::with_id("export_crate", "Export as Rust Library", true, Some(Accelerator::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyE)))).ok();
|
|
file.append(&PredefinedMenuItem::separator()).ok();
|
|
file.append(&MenuItem::with_id("quit", "Quit", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyQ)))).ok();
|
|
|
|
let edit = Submenu::new("Edit", true);
|
|
edit.append(&MenuItem::with_id("undo", "Undo", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyZ)))).ok();
|
|
edit.append(&MenuItem::with_id("redo", "Redo", true, Some(Accelerator::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyZ)))).ok();
|
|
edit.append(&PredefinedMenuItem::separator()).ok();
|
|
edit.append(&PredefinedMenuItem::cut(None)).ok();
|
|
edit.append(&PredefinedMenuItem::copy(None)).ok();
|
|
edit.append(&PredefinedMenuItem::paste(None)).ok();
|
|
edit.append(&PredefinedMenuItem::select_all(None)).ok();
|
|
edit.append(&PredefinedMenuItem::separator()).ok();
|
|
edit.append(&MenuItem::with_id("find", "Find...", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyF)))).ok();
|
|
edit.append(&PredefinedMenuItem::separator()).ok();
|
|
edit.append(&MenuItem::with_id("settings", "Settings...", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Comma)))).ok();
|
|
edit.append(&PredefinedMenuItem::separator()).ok();
|
|
edit.append(&MenuItem::with_id("bold", "Bold", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyB)))).ok();
|
|
edit.append(&MenuItem::with_id("italic", "Italic", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyI)))).ok();
|
|
edit.append(&MenuItem::with_id("table", "Insert Table", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyT)))).ok();
|
|
|
|
edit.append(&PredefinedMenuItem::separator()).ok();
|
|
let auto_pair_sub = Submenu::new("Auto Pair", true);
|
|
let pair_specs: [(u32, &str, &str); 6] = [
|
|
(AP_PAREN, "ap_paren", "Parens ( )"),
|
|
(AP_BRACKET, "ap_bracket", "Brackets [ ]"),
|
|
(AP_BRACE, "ap_brace", "Braces { }"),
|
|
(AP_SINGLE, "ap_single", "Single quotes ' '"),
|
|
(AP_DOUBLE, "ap_double", "Double quotes \" \""),
|
|
(AP_BACKTICK, "ap_backtick", "Backticks ` `"),
|
|
];
|
|
let mut auto_pair_items: Vec<(u32, CheckMenuItem)> = Vec::with_capacity(6);
|
|
for (bit, id, label) in pair_specs {
|
|
let item = CheckMenuItem::with_id(id, label, true, (auto_pair_flags & bit) != 0, None);
|
|
auto_pair_sub.append(&item).ok();
|
|
auto_pair_items.push((bit, item));
|
|
}
|
|
edit.append(&auto_pair_sub).ok();
|
|
|
|
let render = Submenu::new("Render", true);
|
|
render.append(&MenuItem::with_id("live", "Live", true, None)).ok();
|
|
render.append(&MenuItem::with_id("editor", "Editor", true, None)).ok();
|
|
render.append(&MenuItem::with_id("view", "View", true, None)).ok();
|
|
render.append(&PredefinedMenuItem::separator()).ok();
|
|
render.append(&MenuItem::with_id("eval", "Evaluate", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::KeyE)))).ok();
|
|
|
|
let view = Submenu::new("View", true);
|
|
view.append(&MenuItem::with_id("zoom_in", "Zoom In", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Equal)))).ok();
|
|
view.append(&MenuItem::with_id("zoom_out", "Zoom Out", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Minus)))).ok();
|
|
view.append(&MenuItem::with_id("zoom_reset", "Reset Zoom", true, Some(Accelerator::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::Digit0)))).ok();
|
|
|
|
menu.append(&file).ok();
|
|
menu.append(&edit).ok();
|
|
menu.append(&render).ok();
|
|
menu.append(&view).ok();
|
|
|
|
Self { menu, auto_pair_items }
|
|
}
|
|
|
|
pub fn set_auto_pair_check(&self, bit: u32, checked: bool) {
|
|
for (b, item) in &self.auto_pair_items {
|
|
if *b == bit { item.set_checked(checked); }
|
|
}
|
|
}
|
|
|
|
pub fn poll() -> Option<MenuAction> {
|
|
MenuEvent::receiver().try_recv().ok().and_then(|e| {
|
|
match e.id().0.as_str() {
|
|
"new" => Some(MenuAction::NewNote),
|
|
"open" => Some(MenuAction::Open),
|
|
"browse" => Some(MenuAction::ToggleBrowser),
|
|
"save" => Some(MenuAction::Save),
|
|
"save_as" => Some(MenuAction::SaveAs),
|
|
"quit" => Some(MenuAction::Quit),
|
|
"undo" => Some(MenuAction::Undo),
|
|
"redo" => Some(MenuAction::Redo),
|
|
"bold" => Some(MenuAction::Bold),
|
|
"italic" => Some(MenuAction::Italic),
|
|
"table" => Some(MenuAction::InsertTable),
|
|
"eval" => Some(MenuAction::Evaluate),
|
|
"live" => Some(MenuAction::LiveMode),
|
|
"editor" => Some(MenuAction::EditorMode),
|
|
"view" => Some(MenuAction::ViewMode),
|
|
"zoom_in" => Some(MenuAction::ZoomIn),
|
|
"zoom_out" => Some(MenuAction::ZoomOut),
|
|
"zoom_reset" => Some(MenuAction::ZoomReset),
|
|
"find" => Some(MenuAction::Find),
|
|
"settings" => Some(MenuAction::Settings),
|
|
"export_crate" => Some(MenuAction::ExportCrate),
|
|
"ap_paren" => Some(MenuAction::ToggleAutoPair(AP_PAREN)),
|
|
"ap_bracket" => Some(MenuAction::ToggleAutoPair(AP_BRACKET)),
|
|
"ap_brace" => Some(MenuAction::ToggleAutoPair(AP_BRACE)),
|
|
"ap_single" => Some(MenuAction::ToggleAutoPair(AP_SINGLE)),
|
|
"ap_double" => Some(MenuAction::ToggleAutoPair(AP_DOUBLE)),
|
|
"ap_backtick" => Some(MenuAction::ToggleAutoPair(AP_BACKTICK)),
|
|
_ => None,
|
|
}
|
|
})
|
|
}
|
|
}
|