From ddb0c8c2496b99a559fd9b045b86c256b501a3a7 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 28 Feb 2025 17:07:32 -0800 Subject: [PATCH] Reorganize the menu bar and add additional commands to it --- .../preferences_dialog_message_handler.rs | 28 +- .../portfolio/document/document_message.rs | 3 + .../document/document_message_handler.rs | 24 ++ .../menu_bar/menu_bar_message_handler.rs | 333 +++++++++++++----- .../tool/tool_messages/select_tool.rs | 16 + .../assets/icon-16px-solid/folder-open.svg | 3 + .../assets/icon-16px-solid/select-parent.svg | 13 + .../icon-16px-solid/turn-negative-90.svg | 4 + .../icon-16px-solid/turn-positive-90.svg | 4 + frontend/src/utility-functions/icons.ts | 8 + 10 files changed, 337 insertions(+), 99 deletions(-) create mode 100644 frontend/assets/icon-16px-solid/folder-open.svg create mode 100644 frontend/assets/icon-16px-solid/select-parent.svg create mode 100644 frontend/assets/icon-16px-solid/turn-negative-90.svg create mode 100644 frontend/assets/icon-16px-solid/turn-positive-90.svg diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index 47cb43c9..c8bc65b8 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -41,6 +41,7 @@ impl PreferencesDialogMessageHandler { let zoom_with_scroll_tooltip = "Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads)"; let zoom_with_scroll = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), CheckboxInput::new(preferences.zoom_with_scroll) .tooltip(zoom_with_scroll_tooltip) @@ -60,7 +61,11 @@ impl PreferencesDialogMessageHandler { let editing_header = vec![TextLabel::new("Editing").italic(true).widget_holder()]; - let selection_label = vec![Separator::new(SeparatorType::Unrelated).widget_holder(), TextLabel::new("Selection").widget_holder()]; + let selection_label = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), + Separator::new(SeparatorType::Unrelated).widget_holder(), + TextLabel::new("Selection").widget_holder(), + ]; let selection_mode = RadioInput::new(vec![ RadioEntryData::new(SelectionMode::Touched.to_string()) @@ -93,6 +98,11 @@ impl PreferencesDialogMessageHandler { ]) .selected_index(Some(preferences.selection_mode as u32)) .widget_holder(); + let selection_mode = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), + Separator::new(SeparatorType::Unrelated).widget_holder(), + selection_mode, + ]; // ============ // EXPERIMENTAL @@ -102,6 +112,7 @@ impl PreferencesDialogMessageHandler { let node_graph_section_tooltip = "Appearance of the wires running between node connections in the graph"; let node_graph_wires_label = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), TextLabel::new("Node Graph Wires").tooltip(node_graph_section_tooltip).widget_holder(), ]; @@ -117,9 +128,15 @@ impl PreferencesDialogMessageHandler { ]) .selected_index(Some(preferences.graph_wire_style as u32)) .widget_holder(); + let graph_wire_style = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), + Separator::new(SeparatorType::Unrelated).widget_holder(), + graph_wire_style, + ]; let vello_tooltip = "Use the experimental Vello renderer (your browser must support WebGPU)"; let use_vello = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), CheckboxInput::new(preferences.use_vello && preferences.supports_wgpu()) .tooltip(vello_tooltip) @@ -135,6 +152,7 @@ impl PreferencesDialogMessageHandler { let vector_mesh_tooltip = "Allow tools to produce vector meshes, where more than two segments can connect to an anchor point.\n\nCurrently this does not properly handle line joins and fills."; let vector_meshes = vec![ + Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), CheckboxInput::new(preferences.vector_meshes) .tooltip(vector_mesh_tooltip) @@ -169,14 +187,10 @@ impl PreferencesDialogMessageHandler { LayoutGroup::Row { widgets: zoom_with_scroll }, LayoutGroup::Row { widgets: editing_header }, LayoutGroup::Row { widgets: selection_label }, - LayoutGroup::Row { - widgets: vec![Separator::new(SeparatorType::Unrelated).widget_holder(), selection_mode], - }, + LayoutGroup::Row { widgets: selection_mode }, LayoutGroup::Row { widgets: experimental_header }, LayoutGroup::Row { widgets: node_graph_wires_label }, - LayoutGroup::Row { - widgets: vec![Separator::new(SeparatorType::Unrelated).widget_holder(), graph_wire_style], - }, + LayoutGroup::Row { widgets: graph_wire_style }, LayoutGroup::Row { widgets: use_vello }, LayoutGroup::Row { widgets: vector_meshes }, // LayoutGroup::Row { widgets: imaginate_server_hostname }, diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index db2919da..7f567ba8 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -60,6 +60,9 @@ pub enum DocumentMessage { FlipSelectedLayers { flip_axis: FlipAxis, }, + RotateSelectedLayers { + degrees: f64, + }, GraphViewOverlay { open: bool, }, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 2f7c0557..e2d3e976 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -454,6 +454,30 @@ impl MessageHandler> for DocumentMessag } } } + DocumentMessage::RotateSelectedLayers { degrees } => { + // Get the bounding box of selected layers in viewport space + if let Some([min, max]) = self.selected_visible_and_unlock_layers_bounding_box_viewport() { + // Calculate the center of the bounding box to use as rotation pivot + let center = (max + min) / 2.; + // Transform that moves pivot point to origin + let bbox_trans = DAffine2::from_translation(-center); + + let mut added_transaction = false; + for layer in self.network_interface.selected_nodes(&[]).unwrap().selected_unlocked_layers(&self.network_interface) { + if !added_transaction { + responses.add(DocumentMessage::AddTransaction); + added_transaction = true; + } + + responses.add(GraphOperationMessage::TransformChange { + layer, + transform: DAffine2::from_angle(degrees.to_radians()), + transform_in: TransformIn::Scope { scope: bbox_trans }, + skip_rerender: false, + }); + } + } + } DocumentMessage::GraphViewOverlay { open } => { self.graph_view_overlay_open = open; 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 f18d3ca9..1cb0a9f9 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 @@ -1,8 +1,10 @@ +use graphene_std::vector::misc::BooleanOperation; + use crate::messages::debug::utility_types::MessageLoggingVerbosity; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; -use crate::messages::portfolio::document::utility_types::misc::GroupFolderType; +use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType}; use crate::messages::prelude::*; pub struct MenuBarMessageData { @@ -199,8 +201,26 @@ impl LayoutHolder for MenuBarMessageHandler { ..MenuBarEntry::default() }, ], + vec![ + MenuBarEntry { + label: "Duplicate".into(), + icon: Some("Copy".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::DuplicateSelectedLayers), + action: MenuBarEntry::create_action(|_| DocumentMessage::DuplicateSelectedLayers.into()), + disabled: no_active_document || !has_selected_nodes, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Delete".into(), + icon: Some("Trash".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers), + action: MenuBarEntry::create_action(|_| DocumentMessage::DeleteSelectedLayers.into()), + disabled: no_active_document || !has_selected_nodes, + ..MenuBarEntry::default() + }, + ], vec![MenuBarEntry { - label: "Remove Artboards".into(), + label: "Convert to Infinite Canvas".into(), icon: Some("Artboard".into()), action: MenuBarEntry::create_action(|_| DocumentMessage::RemoveArtboards.into()), disabled: no_active_document, @@ -212,17 +232,17 @@ impl LayoutHolder for MenuBarMessageHandler { "Layer".into(), no_active_document, MenuBarEntryChildren(vec![ + vec![MenuBarEntry { + label: "New".into(), + icon: Some("NewLayer".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder), + action: MenuBarEntry::create_action(|_| DocumentMessage::CreateEmptyFolder.into()), + disabled: no_active_document, + ..MenuBarEntry::default() + }], vec![ MenuBarEntry { - label: "New Layer".into(), - icon: Some("NewLayer".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::CreateEmptyFolder), - action: MenuBarEntry::create_action(|_| DocumentMessage::CreateEmptyFolder.into()), - disabled: no_active_document, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Group Selected".into(), + label: "Group".into(), icon: Some("Folder".into()), shortcut: action_keys!(DocumentMessageDiscriminant::GroupSelectedLayers), action: MenuBarEntry::create_action(|_| { @@ -235,14 +255,216 @@ impl LayoutHolder for MenuBarMessageHandler { ..MenuBarEntry::default() }, MenuBarEntry { - label: "Delete Selected".into(), - icon: Some("Trash".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::DeleteSelectedLayers), - action: MenuBarEntry::create_action(|_| DocumentMessage::DeleteSelectedLayers.into()), - disabled: no_active_document || !has_selected_nodes, + label: "Ungroup".into(), + icon: Some("FolderOpen".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::UngroupSelectedLayers), + action: MenuBarEntry::create_action(|_| DocumentMessage::UngroupSelectedLayers.into()), + disabled: no_active_document || !has_selected_layers, ..MenuBarEntry::default() }, ], + vec![ + MenuBarEntry { + label: "Hide/Show".into(), + icon: Some("EyeHide".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::ToggleSelectedVisibility), + action: MenuBarEntry::create_action(|_| DocumentMessage::ToggleSelectedVisibility.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Lock/Unlock".into(), + icon: Some("PadlockLocked".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::ToggleSelectedLocked), + action: MenuBarEntry::create_action(|_| DocumentMessage::ToggleSelectedLocked.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + ], + vec![ + MenuBarEntry { + label: "Grab".into(), + icon: Some("TransformationGrab".into()), + shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginGrab), + action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginGrab.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Rotate".into(), + icon: Some("TransformationRotate".into()), + shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginRotate), + action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginRotate.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Scale".into(), + icon: Some("TransformationScale".into()), + shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginScale), + action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginScale.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + ], + vec![ + MenuBarEntry { + label: "Arrange".into(), + icon: Some("StackHollow".into()), + action: MenuBarEntry::no_action(), + disabled: no_active_document || !has_selected_layers, + children: MenuBarEntryChildren(vec![ + vec![ + MenuBarEntry { + label: "Raise To Front".into(), + icon: Some("Stack".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersRaiseToFront), + action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersRaiseToFront.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Raise".into(), + icon: Some("StackRaise".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersRaise), + action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersRaise.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Lower".into(), + icon: Some("StackLower".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersLower), + action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersLower.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Lower to Back".into(), + icon: Some("StackBottom".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersLowerToBack), + action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersLowerToBack.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }, + ], + vec![MenuBarEntry { + label: "Reverse".into(), + icon: Some("StackReverse".into()), + action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersReverse.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }], + ]), + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Align".into(), + icon: Some("AlignVerticalCenter".into()), + action: MenuBarEntry::no_action(), + disabled: no_active_document || !has_selected_layers, + children: MenuBarEntryChildren({ + let choices = [ + [ + (AlignAxis::X, AlignAggregate::Min, "AlignLeft", "Align Left"), + (AlignAxis::X, AlignAggregate::Center, "AlignHorizontalCenter", "Align Horizontal Center"), + (AlignAxis::X, AlignAggregate::Max, "AlignRight", "Align Right"), + ], + [ + (AlignAxis::Y, AlignAggregate::Min, "AlignTop", "Align Top"), + (AlignAxis::Y, AlignAggregate::Center, "AlignVerticalCenter", "Align Vertical Center"), + (AlignAxis::Y, AlignAggregate::Max, "AlignBottom", "Align Bottom"), + ], + ]; + + choices + .into_iter() + .map(|group| { + group + .into_iter() + .map(|(axis, aggregate, icon, name)| MenuBarEntry { + label: name.into(), + icon: Some(icon.into()), + action: MenuBarEntry::create_action(move |_| DocumentMessage::AlignSelectedLayers { axis, aggregate }.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }) + .collect() + }) + .collect() + }), + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Flip".into(), + icon: Some("FlipVertical".into()), + action: MenuBarEntry::no_action(), + disabled: no_active_document || !has_selected_layers, + children: MenuBarEntryChildren(vec![{ + [(FlipAxis::X, "FlipHorizontal", "Horizontal"), (FlipAxis::Y, "FlipVertical", "Vertical")] + .into_iter() + .map(|(flip_axis, icon, name)| MenuBarEntry { + label: name.into(), + icon: Some(icon.into()), + action: MenuBarEntry::create_action(move |_| DocumentMessage::FlipSelectedLayers { flip_axis }.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }) + .collect() + }]), + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Turn".into(), + icon: Some("TurnPositive90".into()), + action: MenuBarEntry::no_action(), + disabled: no_active_document || !has_selected_layers, + children: MenuBarEntryChildren(vec![{ + [(-90., "TurnNegative90", "Turn -90°"), (90., "TurnPositive90", "Turn 90°")] + .into_iter() + .map(|(degrees, icon, name)| MenuBarEntry { + label: name.into(), + icon: Some(icon.into()), + action: MenuBarEntry::create_action(move |_| DocumentMessage::RotateSelectedLayers { degrees }.into()), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }) + .collect() + }]), + ..MenuBarEntry::default() + }, + MenuBarEntry { + label: "Boolean".into(), + icon: Some("BooleanSubtractFront".into()), + action: MenuBarEntry::no_action(), + disabled: no_active_document || !has_selected_layers, + children: MenuBarEntryChildren(vec![{ + let operations = BooleanOperation::list(); + let icons = BooleanOperation::icons(); + operations + .into_iter() + .zip(icons) + .map(move |(operation, icon)| MenuBarEntry { + label: operation.to_string(), + icon: Some(icon.into()), + action: MenuBarEntry::create_action(move |_| { + let group_folder_type = GroupFolderType::BooleanOperation(operation); + DocumentMessage::GroupSelectedLayers { group_folder_type }.into() + }), + disabled: no_active_document || !has_selected_layers, + ..MenuBarEntry::default() + }) + .collect() + }]), + ..MenuBarEntry::default() + }, + ], + ]), + ), + MenuBarEntry::new_root( + "Select".into(), + no_active_document, + MenuBarEntryChildren(vec![ vec![ MenuBarEntry { label: "Select All".into(), @@ -262,11 +484,14 @@ impl LayoutHolder for MenuBarMessageHandler { }, MenuBarEntry { label: "Select Parent".into(), + icon: Some("SelectParent".into()), shortcut: action_keys!(DocumentMessageDiscriminant::SelectParentLayer), action: MenuBarEntry::create_action(|_| DocumentMessage::SelectParentLayer.into()), disabled: no_active_document || !has_selected_nodes, ..MenuBarEntry::default() }, + ], + vec![ MenuBarEntry { label: "Previous Selection".into(), icon: Some("HistoryUndo".into()), @@ -284,82 +509,6 @@ impl LayoutHolder for MenuBarMessageHandler { ..MenuBarEntry::default() }, ], - vec![ - MenuBarEntry { - label: "Grab Selected".into(), - icon: Some("TransformationGrab".into()), - shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginGrab), - action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginGrab.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Rotate Selected".into(), - icon: Some("TransformationRotate".into()), - shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginRotate), - action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginRotate.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Scale Selected".into(), - icon: Some("TransformationScale".into()), - shortcut: action_keys!(TransformLayerMessageDiscriminant::BeginScale), - action: MenuBarEntry::create_action(|_| TransformLayerMessage::BeginScale.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - ], - vec![MenuBarEntry { - label: "Order".into(), - icon: Some("StackHollow".into()), - action: MenuBarEntry::no_action(), - disabled: no_active_document || !has_selected_layers, - children: MenuBarEntryChildren(vec![ - vec![ - MenuBarEntry { - label: "Raise To Front".into(), - icon: Some("Stack".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersRaiseToFront), - action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersRaiseToFront.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Raise".into(), - icon: Some("StackRaise".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersRaise), - action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersRaise.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Lower".into(), - icon: Some("StackLower".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersLower), - action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersLower.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - MenuBarEntry { - label: "Lower to Back".into(), - icon: Some("StackBottom".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersLowerToBack), - action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersLowerToBack.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }, - ], - vec![MenuBarEntry { - label: "Reverse".into(), - icon: Some("StackReverse".into()), - action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersReverse.into()), - disabled: no_active_document || !has_selected_layers, - ..MenuBarEntry::default() - }], - ]), - ..MenuBarEntry::default() - }], ]), ), MenuBarEntry::new_root( diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 56a71558..ef061f2e 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -168,6 +168,18 @@ impl SelectTool { }) } + fn turn_widgets(&self, disabled: bool) -> impl Iterator { + [(-90., "TurnNegative90", "Turn -90°"), (90., "TurnPositive90", "Turn 90°")] + .into_iter() + .map(move |(degrees, icon, name)| { + IconButton::new(icon, 24) + .tooltip(name) + .on_update(move |_| DocumentMessage::RotateSelectedLayers { degrees }.into()) + .disabled(disabled) + .widget_holder() + }) + } + fn boolean_widgets(&self, selected_count: usize) -> impl Iterator { let operations = BooleanOperation::list(); let icons = BooleanOperation::icons(); @@ -218,6 +230,10 @@ impl LayoutHolder for SelectTool { widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.extend(self.flip_widgets(disabled)); + // Turn + widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); + widgets.extend(self.turn_widgets(disabled)); + // Boolean widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.extend(self.boolean_widgets(self.tool_data.selected_layers_count)); diff --git a/frontend/assets/icon-16px-solid/folder-open.svg b/frontend/assets/icon-16px-solid/folder-open.svg new file mode 100644 index 00000000..bbad2de6 --- /dev/null +++ b/frontend/assets/icon-16px-solid/folder-open.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/icon-16px-solid/select-parent.svg b/frontend/assets/icon-16px-solid/select-parent.svg new file mode 100644 index 00000000..d42c5b58 --- /dev/null +++ b/frontend/assets/icon-16px-solid/select-parent.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/frontend/assets/icon-16px-solid/turn-negative-90.svg b/frontend/assets/icon-16px-solid/turn-negative-90.svg new file mode 100644 index 00000000..8e676791 --- /dev/null +++ b/frontend/assets/icon-16px-solid/turn-negative-90.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/assets/icon-16px-solid/turn-positive-90.svg b/frontend/assets/icon-16px-solid/turn-positive-90.svg new file mode 100644 index 00000000..567d6ee0 --- /dev/null +++ b/frontend/assets/icon-16px-solid/turn-positive-90.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/utility-functions/icons.ts b/frontend/src/utility-functions/icons.ts index 58dacceb..eb963bb9 100644 --- a/frontend/src/utility-functions/icons.ts +++ b/frontend/src/utility-functions/icons.ts @@ -127,6 +127,7 @@ import FileImport from "@graphite-frontend/assets/icon-16px-solid/file-import.sv import File from "@graphite-frontend/assets/icon-16px-solid/file.svg"; import FlipHorizontal from "@graphite-frontend/assets/icon-16px-solid/flip-horizontal.svg"; import FlipVertical from "@graphite-frontend/assets/icon-16px-solid/flip-vertical.svg"; +import FolderOpen from "@graphite-frontend/assets/icon-16px-solid/folder-open.svg"; import Folder from "@graphite-frontend/assets/icon-16px-solid/folder.svg"; import FrameAll from "@graphite-frontend/assets/icon-16px-solid/frame-all.svg"; import FrameSelected from "@graphite-frontend/assets/icon-16px-solid/frame-selected.svg"; @@ -171,6 +172,7 @@ import ReverseRadialGradientToRight from "@graphite-frontend/assets/icon-16px-so import Reverse from "@graphite-frontend/assets/icon-16px-solid/reverse.svg"; import Save from "@graphite-frontend/assets/icon-16px-solid/save.svg"; import SelectAll from "@graphite-frontend/assets/icon-16px-solid/select-all.svg"; +import SelectParent from "@graphite-frontend/assets/icon-16px-solid/select-parent.svg"; import Settings from "@graphite-frontend/assets/icon-16px-solid/settings.svg"; import SmallDot from "@graphite-frontend/assets/icon-16px-solid/small-dot.svg"; import StackBottom from "@graphite-frontend/assets/icon-16px-solid/stack-bottom.svg"; @@ -185,6 +187,8 @@ import TransformationGrab from "@graphite-frontend/assets/icon-16px-solid/transf import TransformationRotate from "@graphite-frontend/assets/icon-16px-solid/transformation-rotate.svg"; import TransformationScale from "@graphite-frontend/assets/icon-16px-solid/transformation-scale.svg"; import Trash from "@graphite-frontend/assets/icon-16px-solid/trash.svg"; +import TurnNegative90 from "@graphite-frontend/assets/icon-16px-solid/turn-negative-90.svg"; +import TurnPositive90 from "@graphite-frontend/assets/icon-16px-solid/turn-positive-90.svg"; import UserManual from "@graphite-frontend/assets/icon-16px-solid/user-manual.svg"; import ViewModeNormal from "@graphite-frontend/assets/icon-16px-solid/view-mode-normal.svg"; import ViewModeOutline from "@graphite-frontend/assets/icon-16px-solid/view-mode-outline.svg"; @@ -240,6 +244,7 @@ const SOLID_16PX = { FlipHorizontal: { svg: FlipHorizontal, size: 16 }, FlipVertical: { svg: FlipVertical, size: 16 }, Folder: { svg: Folder, size: 16 }, + FolderOpen: { svg: FolderOpen, size: 16 }, FrameAll: { svg: FrameAll, size: 16 }, FrameSelected: { svg: FrameSelected, size: 16 }, GraphiteLogo: { svg: GraphiteLogo, size: 16 }, @@ -283,6 +288,7 @@ const SOLID_16PX = { ReverseRadialGradientToRight: { svg: ReverseRadialGradientToRight, size: 16 }, Save: { svg: Save, size: 16 }, SelectAll: { svg: SelectAll, size: 16 }, + SelectParent: { svg: SelectParent, size: 16 }, Settings: { svg: Settings, size: 16 }, SmallDot: { svg: SmallDot, size: 16 }, Stack: { svg: Stack, size: 16 }, @@ -297,6 +303,8 @@ const SOLID_16PX = { TransformationRotate: { svg: TransformationRotate, size: 16 }, TransformationScale: { svg: TransformationScale, size: 16 }, Trash: { svg: Trash, size: 16 }, + TurnNegative90: { svg: TurnNegative90, size: 16 }, + TurnPositive90: { svg: TurnPositive90, size: 16 }, UserManual: { svg: UserManual, size: 16 }, ViewModeNormal: { svg: ViewModeNormal, size: 16 }, ViewModeOutline: { svg: ViewModeOutline, size: 16 },