mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
Menu bar definition in backend (#681)
* initial menu layout working * removed api.rs functions * no action shortcut for no-op * code review * nitpicks
This commit is contained in:
@@ -10,8 +10,8 @@ use crate::frontend::utility_types::{FileType, FrontendImageData};
|
||||
use crate::input::InputPreprocessorMessageHandler;
|
||||
use crate::layout::layout_message::LayoutTarget;
|
||||
use crate::layout::widgets::{
|
||||
DropdownEntryData, DropdownInput, IconButton, LayoutRow, NumberInput, NumberInputIncrementBehavior, OptionalInput, PopoverButton, RadioEntryData, RadioInput, Separator, SeparatorDirection,
|
||||
SeparatorType, Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
DropdownEntryData, DropdownInput, IconButton, Layout, LayoutGroup, NumberInput, NumberInputIncrementBehavior, OptionalInput, PopoverButton, RadioEntryData, RadioInput, Separator,
|
||||
SeparatorDirection, SeparatorType, Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
};
|
||||
use crate::message_prelude::*;
|
||||
use crate::viewport_tools::vector_editor::vector_shape::VectorShape;
|
||||
@@ -519,7 +519,7 @@ impl DocumentMessageHandler {
|
||||
}
|
||||
|
||||
pub fn update_document_widgets(&self, responses: &mut VecDeque<Message>) {
|
||||
let document_bar_layout = WidgetLayout::new(vec![LayoutRow::Row {
|
||||
let document_bar_layout = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::OptionalInput(OptionalInput {
|
||||
checked: self.snapping_enabled,
|
||||
@@ -657,7 +657,7 @@ impl DocumentMessageHandler {
|
||||
],
|
||||
}]);
|
||||
|
||||
let document_mode_layout = WidgetLayout::new(vec![LayoutRow::Row {
|
||||
let document_mode_layout = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::DropdownInput(DropdownInput {
|
||||
entries: vec![vec![
|
||||
@@ -693,7 +693,7 @@ impl DocumentMessageHandler {
|
||||
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: document_bar_layout,
|
||||
layout: Layout::WidgetLayout(document_bar_layout),
|
||||
layout_target: LayoutTarget::DocumentBar,
|
||||
}
|
||||
.into(),
|
||||
@@ -701,7 +701,7 @@ impl DocumentMessageHandler {
|
||||
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: document_mode_layout,
|
||||
layout: Layout::WidgetLayout(document_mode_layout),
|
||||
layout_target: LayoutTarget::DocumentMode,
|
||||
}
|
||||
.into(),
|
||||
@@ -762,7 +762,7 @@ impl DocumentMessageHandler {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let layer_tree_options = WidgetLayout::new(vec![LayoutRow::Row {
|
||||
let layer_tree_options = WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::DropdownInput(DropdownInput {
|
||||
entries: blend_mode_menu_entries,
|
||||
@@ -815,7 +815,7 @@ impl DocumentMessageHandler {
|
||||
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: layer_tree_options,
|
||||
layout: Layout::WidgetLayout(layer_tree_options),
|
||||
layout_target: LayoutTarget::LayerTreeOptions,
|
||||
}
|
||||
.into(),
|
||||
|
||||
10
editor/src/document/menu_bar_message.rs
Normal file
10
editor/src/document/menu_bar_message.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use crate::message_prelude::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[remain::sorted]
|
||||
#[impl_message(Message, PortfolioMessage, MenuBar)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum MenuBarMessage {
|
||||
SendLayout,
|
||||
}
|
||||
313
editor/src/document/menu_bar_message_handler.rs
Normal file
313
editor/src/document/menu_bar_message_handler.rs
Normal file
@@ -0,0 +1,313 @@
|
||||
use super::MenuBarMessage;
|
||||
use crate::input::keyboard::Key;
|
||||
use crate::layout::layout_message::LayoutTarget;
|
||||
use crate::layout::widgets::*;
|
||||
use crate::message_prelude::*;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct MenuBarMessageHandler {}
|
||||
|
||||
impl MessageHandler<MenuBarMessage, ()> for MenuBarMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_action(&mut self, message: MenuBarMessage, _data: (), responses: &mut VecDeque<Message>) {
|
||||
use MenuBarMessage::*;
|
||||
|
||||
#[remain::sorted]
|
||||
match message {
|
||||
SendLayout => self.register_properties(responses, LayoutTarget::MenuBar),
|
||||
}
|
||||
}
|
||||
|
||||
fn actions(&self) -> ActionList {
|
||||
actions!(MenuBarMessageDiscriminant;)
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyHolder for MenuBarMessageHandler {
|
||||
fn properties(&self) -> Layout {
|
||||
Layout::MenuLayout(MenuLayout::new(vec![
|
||||
MenuColumn {
|
||||
label: "File".into(),
|
||||
children: vec![
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "New…".into(),
|
||||
icon: Some("File".into()),
|
||||
action: MenuEntry::create_action(|_| DialogMessage::RequestNewDocumentDialog.into()),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyN]),
|
||||
children: None,
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Open…".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyO]),
|
||||
action: MenuEntry::create_action(|_| PortfolioMessage::OpenDocument.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Open Recent".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyO]),
|
||||
action: MenuEntry::no_action(),
|
||||
icon: None,
|
||||
children: Some(vec![
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Reopen Last Closed".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyT]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Clear Recently Opened".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Some Recent File.gdd".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Another Recent File.gdd".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "An Older File.gdd".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Some Other Older File.gdd".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Yet Another Older File.gdd".into(),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
]),
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Close".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyW]),
|
||||
action: MenuEntry::create_action(|_| PortfolioMessage::CloseActiveDocumentWithConfirmation.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Close All".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyAlt, Key::KeyW]),
|
||||
action: MenuEntry::create_action(|_| DialogMessage::CloseAllDocumentsWithConfirmation.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Save".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyS]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::SaveDocument.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Save As…".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyS]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::SaveDocument.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Save All".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyAlt, Key::KeyS]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Auto-Save".into(),
|
||||
icon: Some("CheckboxChecked".into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Import…".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyI]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Export…".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyE]),
|
||||
action: MenuEntry::create_action(|_| DialogMessage::RequestExportDialog.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![MenuEntry {
|
||||
label: "Quit".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyQ]),
|
||||
..MenuEntry::default()
|
||||
}],
|
||||
],
|
||||
},
|
||||
MenuColumn {
|
||||
label: "Edit".into(),
|
||||
children: vec![
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Undo".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyZ]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::Undo.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Redo".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyZ]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::Redo.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Cut".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyX]),
|
||||
action: MenuEntry::create_action(|_| PortfolioMessage::Cut { clipboard: Clipboard::Device }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Copy".into(),
|
||||
icon: Some("Copy".into()),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyC]),
|
||||
action: MenuEntry::create_action(|_| PortfolioMessage::Copy { clipboard: Clipboard::Device }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
// TODO: Fix this
|
||||
// { label: "Paste", icon: "Paste", shortcut: ["KeyControl", "KeyV"], action: async (): Promise<void> => editor.instance.paste() },
|
||||
],
|
||||
],
|
||||
},
|
||||
MenuColumn {
|
||||
label: "Layer".into(),
|
||||
children: vec![vec![
|
||||
MenuEntry {
|
||||
label: "Select All".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyA]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::SelectAllLayers.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Deselect All".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyAlt, Key::KeyA]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::DeselectAllLayers.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Order".into(),
|
||||
action: MenuEntry::no_action(),
|
||||
children: Some(vec![vec![
|
||||
MenuEntry {
|
||||
label: "Raise To Front".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyLeftBracket]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MAX }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Raise".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyRightBracket]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::ReorderSelectedLayers { relative_index_offset: 1 }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Lower".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyLeftBracket]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::ReorderSelectedLayers { relative_index_offset: -1 }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Lower to Back".into(),
|
||||
shortcut: Some(vec![Key::KeyControl, Key::KeyShift, Key::KeyRightBracket]),
|
||||
action: MenuEntry::create_action(|_| DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MIN }.into()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
]]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
]],
|
||||
},
|
||||
MenuColumn {
|
||||
label: "Document".into(),
|
||||
children: vec![vec![MenuEntry {
|
||||
label: "Menu entries coming soon".into(),
|
||||
..MenuEntry::default()
|
||||
}]],
|
||||
},
|
||||
MenuColumn {
|
||||
label: "View".into(),
|
||||
children: vec![vec![MenuEntry {
|
||||
label: "Show/Hide Node Graph (In Development)".into(),
|
||||
action: MenuEntry::create_action(|_| WorkspaceMessage::NodeGraphToggleVisibility.into()),
|
||||
..MenuEntry::default()
|
||||
}]],
|
||||
},
|
||||
MenuColumn {
|
||||
label: "Help".into(),
|
||||
children: vec![
|
||||
vec![MenuEntry {
|
||||
label: "About Graphite".into(),
|
||||
action: MenuEntry::create_action(|_| DialogMessage::RequestAboutGraphiteDialog.into()),
|
||||
..MenuEntry::default()
|
||||
}],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Report a Bug".into(),
|
||||
action: MenuEntry::create_action(|_| {
|
||||
FrontendMessage::TriggerVisitLink {
|
||||
url: "https://github.com/GraphiteEditor/Graphite/issues/new".into(),
|
||||
}
|
||||
.into()
|
||||
}),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Visit on GitHub".into(),
|
||||
action: MenuEntry::create_action(|_| {
|
||||
FrontendMessage::TriggerVisitLink {
|
||||
url: "https://github.com/GraphiteEditor/Graphite".into(),
|
||||
}
|
||||
.into()
|
||||
}),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
vec![
|
||||
MenuEntry {
|
||||
label: "Debug: Set Log Level".into(),
|
||||
action: MenuEntry::no_action(),
|
||||
children: Some(vec![vec![
|
||||
MenuEntry {
|
||||
label: "Log Level Info".into(),
|
||||
action: MenuEntry::create_action(|_| GlobalMessage::LogInfo.into()),
|
||||
shortcut: Some(vec![Key::Key1]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Log Level Debug".into(),
|
||||
action: MenuEntry::create_action(|_| GlobalMessage::LogDebug.into()),
|
||||
shortcut: Some(vec![Key::Key2]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Log Level Trace".into(),
|
||||
action: MenuEntry::create_action(|_| GlobalMessage::LogTrace.into()),
|
||||
shortcut: Some(vec![Key::Key3]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
]]),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
MenuEntry {
|
||||
label: "Debug: Panic (DANGER)".into(),
|
||||
action: MenuEntry::create_action(|_| panic!()),
|
||||
..MenuEntry::default()
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
]))
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ mod artboard_message;
|
||||
mod artboard_message_handler;
|
||||
mod document_message;
|
||||
mod document_message_handler;
|
||||
mod menu_bar_message;
|
||||
mod menu_bar_message_handler;
|
||||
mod movement_message;
|
||||
mod movement_message_handler;
|
||||
mod overlays_message;
|
||||
@@ -34,6 +36,11 @@ pub use movement_message::{MovementMessage, MovementMessageDiscriminant};
|
||||
#[doc(inline)]
|
||||
pub use movement_message_handler::MovementMessageHandler;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use menu_bar_message::{MenuBarMessage, MenuBarMessageDiscriminant};
|
||||
#[doc(inline)]
|
||||
pub use menu_bar_message_handler::MenuBarMessageHandler;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use overlays_message::{OverlaysMessage, OverlaysMessageDiscriminant};
|
||||
#[doc(inline)]
|
||||
|
||||
@@ -14,6 +14,9 @@ pub enum PortfolioMessage {
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Document(DocumentMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
MenuBar(MenuBarMessage),
|
||||
|
||||
// Messages
|
||||
AutoSaveActiveDocument,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::clipboards::{CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
|
||||
use super::DocumentMessageHandler;
|
||||
use super::{DocumentMessageHandler, MenuBarMessageHandler};
|
||||
use crate::consts::{DEFAULT_DOCUMENT_NAME, GRAPHITE_DOCUMENT_VERSION};
|
||||
use crate::frontend::utility_types::FrontendDocumentDetails;
|
||||
use crate::input::InputPreprocessorMessageHandler;
|
||||
@@ -15,6 +15,7 @@ use std::collections::{HashMap, VecDeque};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PortfolioMessageHandler {
|
||||
menu_bar_message_handler: MenuBarMessageHandler,
|
||||
documents: HashMap<u64, DocumentMessageHandler>,
|
||||
document_ids: Vec<u64>,
|
||||
active_document_id: u64,
|
||||
@@ -130,6 +131,7 @@ impl Default for PortfolioMessageHandler {
|
||||
copy_buffer: [EMPTY_VEC; INTERNAL_CLIPBOARD_COUNT as usize],
|
||||
active_document_id: starting_key,
|
||||
font_cache: Default::default(),
|
||||
menu_bar_message_handler: MenuBarMessageHandler::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +147,8 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
|
||||
// Sub-messages
|
||||
#[remain::unsorted]
|
||||
Document(message) => self.documents.get_mut(&self.active_document_id).unwrap().process_action(message, (ipp, &self.font_cache), responses),
|
||||
#[remain::unsorted]
|
||||
MenuBar(message) => self.menu_bar_message_handler.process_action(message, (), responses),
|
||||
|
||||
// Messages
|
||||
AutoSaveActiveDocument => responses.push_back(PortfolioMessage::AutoSaveDocument { document_id: self.active_document_id }.into()),
|
||||
|
||||
@@ -3,8 +3,8 @@ use super::utility_types::TargetDocument;
|
||||
use crate::document::properties_panel_message::TransformOp;
|
||||
use crate::layout::layout_message::LayoutTarget;
|
||||
use crate::layout::widgets::{
|
||||
ColorInput, FontInput, IconLabel, LayoutRow, NumberInput, PopoverButton, RadioEntryData, RadioInput, Separator, SeparatorDirection, SeparatorType, TextAreaInput, TextInput, TextLabel, Widget,
|
||||
WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
ColorInput, FontInput, IconLabel, Layout, LayoutGroup, NumberInput, PopoverButton, RadioEntryData, RadioInput, Separator, SeparatorDirection, SeparatorType, TextAreaInput, TextInput, TextLabel,
|
||||
Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
};
|
||||
use crate::message_prelude::*;
|
||||
|
||||
@@ -141,14 +141,14 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
|
||||
ClearSelection => {
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(vec![]),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(vec![])),
|
||||
layout_target: LayoutTarget::PropertiesOptions,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(vec![]),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(vec![])),
|
||||
layout_target: LayoutTarget::PropertiesSections,
|
||||
}
|
||||
.into(),
|
||||
@@ -212,14 +212,14 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout_target: LayoutTarget::PropertiesOptions,
|
||||
layout: WidgetLayout::default(),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::default()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout_target: LayoutTarget::PropertiesSections,
|
||||
layout: WidgetLayout::default(),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::default()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
@@ -243,7 +243,7 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
|
||||
}
|
||||
|
||||
fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Message>, font_cache: &FontCache) {
|
||||
let options_bar = vec![LayoutRow::Row {
|
||||
let options_bar = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::IconLabel(IconLabel {
|
||||
icon: "NodeArtboard".into(),
|
||||
@@ -288,10 +288,10 @@ fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Me
|
||||
panic!("Artboard must have a solid fill")
|
||||
};
|
||||
|
||||
vec![LayoutRow::Section {
|
||||
vec![LayoutGroup::Section {
|
||||
name: "Artboard".into(),
|
||||
layout: vec![
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Location".into(),
|
||||
@@ -333,7 +333,7 @@ fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Me
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Dimensions".into(),
|
||||
@@ -375,7 +375,7 @@ fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Me
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Background".into(),
|
||||
@@ -409,14 +409,14 @@ fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Me
|
||||
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(options_bar),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(options_bar)),
|
||||
layout_target: LayoutTarget::PropertiesOptions,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(properties_body),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(properties_body)),
|
||||
layout_target: LayoutTarget::PropertiesSections,
|
||||
}
|
||||
.into(),
|
||||
@@ -424,7 +424,7 @@ fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDeque<Me
|
||||
}
|
||||
|
||||
fn register_artwork_layer_properties(layer: &Layer, responses: &mut VecDeque<Message>, font_cache: &FontCache) {
|
||||
let options_bar = vec![LayoutRow::Row {
|
||||
let options_bar = vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
match &layer.data {
|
||||
LayerDataType::Folder(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
|
||||
@@ -497,25 +497,25 @@ fn register_artwork_layer_properties(layer: &Layer, responses: &mut VecDeque<Mes
|
||||
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(options_bar),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(options_bar)),
|
||||
layout_target: LayoutTarget::PropertiesOptions,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
responses.push_back(
|
||||
LayoutMessage::SendLayout {
|
||||
layout: WidgetLayout::new(properties_body),
|
||||
layout: Layout::WidgetLayout(WidgetLayout::new(properties_body)),
|
||||
layout_target: LayoutTarget::PropertiesSections,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutRow {
|
||||
LayoutRow::Section {
|
||||
fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutGroup {
|
||||
LayoutGroup::Section {
|
||||
name: "Transform".into(),
|
||||
layout: vec![
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Location".into(),
|
||||
@@ -557,7 +557,7 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Rotation".into(),
|
||||
@@ -582,7 +582,7 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Scale".into(),
|
||||
@@ -624,7 +624,7 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Dimensions".into(),
|
||||
@@ -670,13 +670,13 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutRow {
|
||||
}
|
||||
}
|
||||
|
||||
fn node_section_font(layer: &TextLayer) -> LayoutRow {
|
||||
fn node_section_font(layer: &TextLayer) -> LayoutGroup {
|
||||
let font = layer.font.clone();
|
||||
let size = layer.size;
|
||||
LayoutRow::Section {
|
||||
LayoutGroup::Section {
|
||||
name: "Font".into(),
|
||||
layout: vec![
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Text".into(),
|
||||
@@ -692,7 +692,7 @@ fn node_section_font(layer: &TextLayer) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Font".into(),
|
||||
@@ -717,7 +717,7 @@ fn node_section_font(layer: &TextLayer) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Style".into(),
|
||||
@@ -742,7 +742,7 @@ fn node_section_font(layer: &TextLayer) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Size".into(),
|
||||
@@ -772,7 +772,7 @@ fn node_section_font(layer: &TextLayer) -> LayoutRow {
|
||||
}
|
||||
}
|
||||
|
||||
fn node_gradient_type(gradient: &Gradient) -> LayoutRow {
|
||||
fn node_gradient_type(gradient: &Gradient) -> LayoutGroup {
|
||||
let selected_index = match gradient.gradient_type {
|
||||
GradientType::Linear => 0,
|
||||
GradientType::Radial => 1,
|
||||
@@ -781,7 +781,7 @@ fn node_gradient_type(gradient: &Gradient) -> LayoutRow {
|
||||
cloned_gradient_linear.gradient_type = GradientType::Linear;
|
||||
let mut cloned_gradient_radial = gradient.clone();
|
||||
cloned_gradient_radial.gradient_type = GradientType::Radial;
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Gradient Type".into(),
|
||||
@@ -824,10 +824,10 @@ fn node_gradient_type(gradient: &Gradient) -> LayoutRow {
|
||||
}
|
||||
}
|
||||
|
||||
fn node_gradient_color(gradient: &Gradient, percent_label: &'static str, position: usize) -> LayoutRow {
|
||||
fn node_gradient_color(gradient: &Gradient, percent_label: &'static str, position: usize) -> LayoutGroup {
|
||||
let gradient_clone = Rc::new(gradient.clone());
|
||||
let send_fill_message = move |new_gradient: Gradient| PropertiesPanelMessage::ModifyFill { fill: Fill::Gradient(new_gradient) }.into();
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: format!("Gradient: {}", percent_label),
|
||||
@@ -860,11 +860,11 @@ fn node_gradient_color(gradient: &Gradient, percent_label: &'static str, positio
|
||||
}
|
||||
}
|
||||
|
||||
fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
|
||||
fn node_section_fill(fill: &Fill) -> Option<LayoutGroup> {
|
||||
match fill {
|
||||
Fill::Solid(_) | Fill::None => Some(LayoutRow::Section {
|
||||
Fill::Solid(_) | Fill::None => Some(LayoutGroup::Section {
|
||||
name: "Fill".into(),
|
||||
layout: vec![LayoutRow::Row {
|
||||
layout: vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Color".into(),
|
||||
@@ -893,14 +893,14 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
|
||||
],
|
||||
}],
|
||||
}),
|
||||
Fill::Gradient(gradient) => Some(LayoutRow::Section {
|
||||
Fill::Gradient(gradient) => Some(LayoutGroup::Section {
|
||||
name: "Fill".into(),
|
||||
layout: vec![node_gradient_type(gradient), node_gradient_color(gradient, "0%", 0), node_gradient_color(gradient, "100%", 1)],
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
|
||||
// We have to make multiple variables because they get moved into different closures.
|
||||
let internal_stroke1 = stroke.clone();
|
||||
let internal_stroke2 = stroke.clone();
|
||||
@@ -914,10 +914,10 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
let internal_stroke10 = stroke.clone();
|
||||
let internal_stroke11 = stroke.clone();
|
||||
|
||||
LayoutRow::Section {
|
||||
LayoutGroup::Section {
|
||||
name: "Stroke".into(),
|
||||
layout: vec![
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Color".into(),
|
||||
@@ -939,7 +939,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Weight".into(),
|
||||
@@ -964,7 +964,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Dash Lengths".into(),
|
||||
@@ -985,7 +985,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Dash Offset".into(),
|
||||
@@ -1010,7 +1010,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Line Cap".into(),
|
||||
@@ -1057,7 +1057,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
})),
|
||||
],
|
||||
},
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Line Join".into(),
|
||||
@@ -1105,7 +1105,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
|
||||
],
|
||||
},
|
||||
// TODO: Gray out this row when Line Join isn't set to Miter
|
||||
LayoutRow::Row {
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
WidgetHolder::new(Widget::TextLabel(TextLabel {
|
||||
value: "Miter Limit".into(),
|
||||
|
||||
Reference in New Issue
Block a user