diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index ea04e0ae..30cff95c 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -173,6 +173,7 @@ pub enum FrontendMessage { origin: (f64, f64), spacing: f64, interval: f64, + visible: bool, }, UpdateDocumentScrollbars { position: (f64, f64), diff --git a/editor/src/messages/input_mapper/default_mapping.rs b/editor/src/messages/input_mapper/default_mapping.rs index 2f197319..1244447c 100644 --- a/editor/src/messages/input_mapper/default_mapping.rs +++ b/editor/src/messages/input_mapper/default_mapping.rs @@ -343,6 +343,7 @@ pub fn default_mapping() -> Mapping { entry!(KeyDown(KeyI); modifiers=[Accel], action_dispatch=PortfolioMessage::Import), entry!(KeyDown(KeyX); modifiers=[Accel], action_dispatch=PortfolioMessage::Cut { clipboard: Clipboard::Device }), entry!(KeyDown(KeyC); modifiers=[Accel], action_dispatch=PortfolioMessage::Copy { clipboard: Clipboard::Device }), + entry!(KeyDown(KeyR); modifiers=[Alt], action_dispatch=PortfolioMessage::ToggleRulers), // // FrontendMessage entry!(KeyDown(KeyV); modifiers=[Accel], action_dispatch=FrontendMessage::TriggerPaste), diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index c27f63ba..d01be393 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -30,6 +30,12 @@ use graphene_core::raster::ImageFrame; use glam::{DAffine2, DVec2}; use serde::{Deserialize, Serialize}; +/// Utility function for providing a default boolean value to serde. +#[inline(always)] +fn return_true() -> bool { + true +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DocumentMessageHandler { pub document_legacy: DocumentLegacy, @@ -43,6 +49,8 @@ pub struct DocumentMessageHandler { #[serde(skip)] pub snapping_state: SnappingState, pub overlays_visible: bool, + #[serde(default = "return_true")] + pub rulers_visible: bool, #[serde(skip)] pub document_undo_history: VecDeque, @@ -81,6 +89,7 @@ impl Default for DocumentMessageHandler { view_mode: ViewMode::default(), snapping_state: SnappingState::default(), overlays_visible: true, + rulers_visible: true, document_undo_history: VecDeque::new(), document_redo_history: VecDeque::new(), @@ -614,6 +623,7 @@ impl MessageHandler> for DocumentMessageHand origin: ruler_origin.into(), spacing: ruler_spacing, interval: ruler_interval, + visible: self.rulers_visible, }); } RenderScrollbars => { diff --git a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs index aed125a5..083f35a1 100644 --- a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs @@ -6,14 +6,15 @@ use crate::messages::prelude::*; #[derive(Debug, Clone, Default)] pub struct MenuBarMessageHandler { no_active_document: bool, + rulers_hidden: bool, } -impl MessageHandler for MenuBarMessageHandler { +impl MessageHandler for MenuBarMessageHandler { #[remain::check] - fn process_message(&mut self, message: MenuBarMessage, responses: &mut VecDeque, has_active_document: bool) { + fn process_message(&mut self, message: MenuBarMessage, responses: &mut VecDeque, (has_active_document, rulers_hidden): (bool, bool)) { use MenuBarMessage::*; self.no_active_document = !has_active_document; - + self.rulers_hidden = rulers_hidden; #[remain::sorted] match message { SendLayout => self.send_layout(responses, LayoutTarget::MenuBar), @@ -289,8 +290,17 @@ impl LayoutHolder for MenuBarMessageHandler { disabled: no_active_document, ..MenuBarEntry::default() }, + ], + vec![ MenuBarEntry { - label: "Zoom to Fit".into(), + label: "Zoom to Fit Selection".into(), + shortcut: action_keys!(NavigationMessageDiscriminant::FitViewportToSelection), + action: MenuBarEntry::create_action(|_| NavigationMessage::FitViewportToSelection.into()), + disabled: no_active_document, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Zoom to Fit All".into(), shortcut: action_keys!(DocumentMessageDiscriminant::ZoomCanvasToFitAll), action: MenuBarEntry::create_action(|_| DocumentMessage::ZoomCanvasToFitAll.into()), disabled: no_active_document, @@ -312,9 +322,10 @@ impl LayoutHolder for MenuBarMessageHandler { }, ], vec![MenuBarEntry { - label: "Frame Selected".into(), - shortcut: action_keys!(NavigationMessageDiscriminant::FitViewportToSelection), - action: MenuBarEntry::create_action(|_| NavigationMessage::FitViewportToSelection.into()), + label: "Rulers".into(), + icon: Some(if self.rulers_hidden { "CheckboxUnchecked" } else { "CheckboxChecked" }.into()), + shortcut: action_keys!(PortfolioMessageDiscriminant::ToggleRulers), + action: MenuBarEntry::create_action(|_| PortfolioMessage::ToggleRulers.into()), disabled: no_active_document, ..MenuBarEntry::default() }], diff --git a/editor/src/messages/portfolio/portfolio_message.rs b/editor/src/messages/portfolio/portfolio_message.rs index 646a5cf4..402df949 100644 --- a/editor/src/messages/portfolio/portfolio_message.rs +++ b/editor/src/messages/portfolio/portfolio_message.rs @@ -114,6 +114,7 @@ pub enum PortfolioMessage { document_id: u64, layer_path: Vec, }, + ToggleRulers, UpdateDocumentWidgets, UpdateOpenDocumentsList, } diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 057b506c..e3df517d 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -38,7 +38,13 @@ impl MessageHandler self.menu_bar_message_handler.process_message(message, responses, has_active_document), + PortfolioMessage::MenuBar(message) => { + if let Some(document_id) = self.active_document_id { + if let Some(document) = self.documents.get_mut(&document_id) { + self.menu_bar_message_handler.process_message(message, responses, (has_active_document, document.rulers_visible)); + } + } + } #[remain::unsorted] PortfolioMessage::Document(message) => { if let Some(document_id) = self.active_document_id { @@ -517,6 +523,14 @@ impl MessageHandler { + if let Some(document) = self.active_document_mut() { + document.rulers_visible = !document.rulers_visible; + + responses.add(DocumentMessage::RenderRulers); + responses.add(MenuBarMessage::SendLayout); + } + } PortfolioMessage::UpdateDocumentWidgets => { if let Some(document) = self.active_document() { document.update_document_widgets(responses); @@ -552,6 +566,7 @@ impl MessageHandler { await tick(); - const { origin, spacing, interval } = data; - updateDocumentRulers(origin, spacing, interval); + const { origin, spacing, interval, visible } = data; + updateDocumentRulers(origin, spacing, interval, visible); }); // Update mouse cursor icon @@ -440,13 +442,17 @@ - - - + {#if rulersVisible} + + + + {/if} - - - + {#if rulersVisible} + + + + {/if} {#if cursorEyedropper}
diff --git a/frontend/src/wasm-communication/messages.ts b/frontend/src/wasm-communication/messages.ts index 36411871..b72b7a84 100644 --- a/frontend/src/wasm-communication/messages.ts +++ b/frontend/src/wasm-communication/messages.ts @@ -473,6 +473,8 @@ export class UpdateDocumentRulers extends JsMessage { readonly spacing!: number; readonly interval!: number; + + readonly visible!: boolean; } export class UpdateEyedropperSamplingState extends JsMessage {