@@ -7,6 +7,7 @@ use super::{vectorize_layer_metadata, PropertiesPanelMessageHandler};
7
7
use super :: { ArtboardMessageHandler , MovementMessageHandler , OverlaysMessageHandler , TransformLayerMessageHandler } ;
8
8
use crate :: consts:: { ASYMPTOTIC_EFFECT , DEFAULT_DOCUMENT_NAME , FILE_SAVE_SUFFIX , GRAPHITE_DOCUMENT_VERSION , SCALE_EFFECT , SCROLLBAR_SPACING , VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR } ;
9
9
use crate :: frontend:: utility_types:: { FileType , FrontendImageData } ;
10
+ use crate :: input:: input_mapper:: action_keys:: action_shortcut;
10
11
use crate :: input:: InputPreprocessorMessageHandler ;
11
12
use crate :: layout:: layout_message:: LayoutTarget ;
12
13
use crate :: layout:: widgets:: {
@@ -549,6 +550,7 @@ impl DocumentMessageHandler {
549
550
icon: "Snapping" . into( ) ,
550
551
tooltip: "Snapping" . into( ) ,
551
552
on_update: WidgetCallback :: new( |optional_input: & OptionalInput | DocumentMessage :: SetSnapping { snap: optional_input. checked } . into( ) ) ,
553
+ ..Default :: default ( )
552
554
} ) ) ,
553
555
WidgetHolder :: new( Widget :: PopoverButton ( PopoverButton {
554
556
header: "Snapping" . into( ) ,
@@ -564,6 +566,7 @@ impl DocumentMessageHandler {
564
566
icon: "Grid" . into( ) ,
565
567
tooltip: "Grid" . into( ) ,
566
568
on_update: WidgetCallback :: new( |_| DialogMessage :: RequestComingSoonDialog { issue: Some ( 318 ) } . into( ) ) ,
569
+ ..Default :: default ( )
567
570
} ) ) ,
568
571
WidgetHolder :: new( Widget :: PopoverButton ( PopoverButton {
569
572
header: "Grid" . into( ) ,
@@ -579,6 +582,7 @@ impl DocumentMessageHandler {
579
582
icon: "Overlays" . into( ) ,
580
583
tooltip: "Overlays" . into( ) ,
581
584
on_update: WidgetCallback :: new( |optional_input: & OptionalInput | DocumentMessage :: SetOverlaysVisibility { visible: optional_input. checked } . into( ) ) ,
585
+ ..Default :: default ( )
582
586
} ) ) ,
583
587
WidgetHolder :: new( Widget :: PopoverButton ( PopoverButton {
584
588
header: "Overlays" . into( ) ,
@@ -841,14 +845,16 @@ impl DocumentMessageHandler {
841
845
} ) ) ,
842
846
WidgetHolder :: new( Widget :: IconButton ( IconButton {
843
847
icon: "NodeFolder" . into( ) ,
844
- tooltip: "New Folder (Ctrl+Shift+N)" . into( ) , // TODO: Customize this tooltip for the Mac version of the keyboard shortcut
848
+ tooltip: "New Folder" . into( ) ,
849
+ tooltip_shortcut: action_shortcut!( DocumentMessageDiscriminant :: CreateEmptyFolder ) ,
845
850
size: 24 ,
846
851
on_update: WidgetCallback :: new( |_| DocumentMessage :: CreateEmptyFolder { container_path: vec![ ] } . into( ) ) ,
847
852
..Default :: default ( )
848
853
} ) ) ,
849
854
WidgetHolder :: new( Widget :: IconButton ( IconButton {
850
855
icon: "Trash" . into( ) ,
851
- tooltip: "Delete Selected (Del)" . into( ) , // TODO: Customize this tooltip for the Mac version of the keyboard shortcut
856
+ tooltip: "Delete Selected" . into( ) ,
857
+ tooltip_shortcut: action_shortcut!( DocumentMessageDiscriminant :: DeleteSelectedLayers ) ,
852
858
size: 24 ,
853
859
on_update: WidgetCallback :: new( |_| DocumentMessage :: DeleteSelectedLayers . into( ) ) ,
854
860
..Default :: default ( )
@@ -864,6 +870,62 @@ impl DocumentMessageHandler {
864
870
. into ( ) ,
865
871
) ;
866
872
}
873
+
874
+ pub fn selected_layers_reorder ( & mut self , relative_index_offset : isize , responses : & mut VecDeque < Message > ) {
875
+ self . backup ( responses) ;
876
+
877
+ let all_layer_paths = self . all_layers_sorted ( ) ;
878
+ let selected_layers = self . selected_layers_sorted ( ) ;
879
+
880
+ let first_or_last_selected_layer = match relative_index_offset. signum ( ) {
881
+ -1 => selected_layers. first ( ) ,
882
+ 1 => selected_layers. last ( ) ,
883
+ _ => panic ! ( "selected_layers_reorder() must be given a non-zero value" ) ,
884
+ } ;
885
+
886
+ if let Some ( pivot_layer) = first_or_last_selected_layer {
887
+ let sibling_layer_paths: Vec < _ > = all_layer_paths
888
+ . iter ( )
889
+ . filter ( |layer| {
890
+ // Check if this is a sibling of the pivot layer
891
+ // TODO: Break this out into a reusable function `fn are_layers_siblings(layer_a, layer_b) -> bool`
892
+ let containing_folder_path = & pivot_layer[ 0 ..pivot_layer. len ( ) - 1 ] ;
893
+ layer. starts_with ( containing_folder_path) && pivot_layer. len ( ) == layer. len ( )
894
+ } )
895
+ . collect ( ) ;
896
+
897
+ // TODO: Break this out into a reusable function: `fn layer_index_in_containing_folder(layer_path) -> usize`
898
+ let pivot_index_among_siblings = sibling_layer_paths. iter ( ) . position ( |path| * path == pivot_layer) ;
899
+
900
+ if let Some ( pivot_index) = pivot_index_among_siblings {
901
+ let max = sibling_layer_paths. len ( ) as i64 - 1 ;
902
+ let insert_index = ( pivot_index as i64 + relative_index_offset as i64 ) . clamp ( 0 , max) as usize ;
903
+
904
+ let existing_layer_to_insert_beside = sibling_layer_paths. get ( insert_index) ;
905
+
906
+ // TODO: Break this block out into a call to a message called `MoveSelectedLayersNextToLayer { neighbor_path, above_or_below }`
907
+ if let Some ( neighbor_path) = existing_layer_to_insert_beside {
908
+ let ( neighbor_id, folder_path) = neighbor_path. split_last ( ) . expect ( "Can't move the root folder" ) ;
909
+
910
+ if let Some ( folder) = self . graphene_document . layer ( folder_path) . ok ( ) . and_then ( |layer| layer. as_folder ( ) . ok ( ) ) {
911
+ let neighbor_layer_index = folder. layer_ids . iter ( ) . position ( |id| id == neighbor_id) . unwrap ( ) as isize ;
912
+
913
+ // If moving down, insert below this layer. If moving up, insert above this layer.
914
+ let insert_index = if relative_index_offset < 0 { neighbor_layer_index } else { neighbor_layer_index + 1 } ;
915
+
916
+ responses. push_back (
917
+ DocumentMessage :: MoveSelectedLayersTo {
918
+ folder_path : folder_path. to_vec ( ) ,
919
+ insert_index,
920
+ reverse_index : false ,
921
+ }
922
+ . into ( ) ,
923
+ ) ;
924
+ }
925
+ }
926
+ }
927
+ }
928
+ }
867
929
}
868
930
869
931
impl MessageHandler < DocumentMessage , ( & InputPreprocessorMessageHandler , & FontCache ) > for DocumentMessageHandler {
@@ -1318,61 +1380,6 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
1318
1380
. into ( ) ,
1319
1381
) ;
1320
1382
}
1321
- ReorderSelectedLayers { relative_index_offset } => {
1322
- self . backup ( responses) ;
1323
-
1324
- let all_layer_paths = self . all_layers_sorted ( ) ;
1325
- let selected_layers = self . selected_layers_sorted ( ) ;
1326
-
1327
- let first_or_last_selected_layer = match relative_index_offset. signum ( ) {
1328
- -1 => selected_layers. first ( ) ,
1329
- 1 => selected_layers. last ( ) ,
1330
- _ => panic ! ( "ReorderSelectedLayers must be given a non-zero value" ) ,
1331
- } ;
1332
-
1333
- if let Some ( pivot_layer) = first_or_last_selected_layer {
1334
- let sibling_layer_paths: Vec < _ > = all_layer_paths
1335
- . iter ( )
1336
- . filter ( |layer| {
1337
- // Check if this is a sibling of the pivot layer
1338
- // TODO: Break this out into a reusable function `fn are_layers_siblings(layer_a, layer_b) -> bool`
1339
- let containing_folder_path = & pivot_layer[ 0 ..pivot_layer. len ( ) - 1 ] ;
1340
- layer. starts_with ( containing_folder_path) && pivot_layer. len ( ) == layer. len ( )
1341
- } )
1342
- . collect ( ) ;
1343
-
1344
- // TODO: Break this out into a reusable function: `fn layer_index_in_containing_folder(layer_path) -> usize`
1345
- let pivot_index_among_siblings = sibling_layer_paths. iter ( ) . position ( |path| * path == pivot_layer) ;
1346
-
1347
- if let Some ( pivot_index) = pivot_index_among_siblings {
1348
- let max = sibling_layer_paths. len ( ) as i64 - 1 ;
1349
- let insert_index = ( pivot_index as i64 + relative_index_offset as i64 ) . clamp ( 0 , max) as usize ;
1350
-
1351
- let existing_layer_to_insert_beside = sibling_layer_paths. get ( insert_index) ;
1352
-
1353
- // TODO: Break this block out into a call to a message called `MoveSelectedLayersNextToLayer { neighbor_path, above_or_below }`
1354
- if let Some ( neighbor_path) = existing_layer_to_insert_beside {
1355
- let ( neighbor_id, folder_path) = neighbor_path. split_last ( ) . expect ( "Can't move the root folder" ) ;
1356
-
1357
- if let Some ( folder) = self . graphene_document . layer ( folder_path) . ok ( ) . and_then ( |layer| layer. as_folder ( ) . ok ( ) ) {
1358
- let neighbor_layer_index = folder. layer_ids . iter ( ) . position ( |id| id == neighbor_id) . unwrap ( ) as isize ;
1359
-
1360
- // If moving down, insert below this layer. If moving up, insert above this layer.
1361
- let insert_index = if relative_index_offset < 0 { neighbor_layer_index } else { neighbor_layer_index + 1 } ;
1362
-
1363
- responses. push_back (
1364
- DocumentMessage :: MoveSelectedLayersTo {
1365
- folder_path : folder_path. to_vec ( ) ,
1366
- insert_index,
1367
- reverse_index : false ,
1368
- }
1369
- . into ( ) ,
1370
- ) ;
1371
- }
1372
- }
1373
- }
1374
- }
1375
- }
1376
1383
RollbackTransaction => {
1377
1384
self . rollback ( responses) . unwrap_or_else ( |e| log:: warn!( "{}" , e) ) ;
1378
1385
responses. extend ( [ RenderDocument . into ( ) , DocumentStructureChanged . into ( ) ] ) ;
@@ -1399,6 +1406,21 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
1399
1406
let all = self . all_layers ( ) . map ( |path| path. to_vec ( ) ) . collect ( ) ;
1400
1407
responses. push_front ( SetSelectedLayers { replacement_selected_layers : all } . into ( ) ) ;
1401
1408
}
1409
+ SelectedLayersLower => {
1410
+ responses. push_front ( DocumentMessage :: SelectedLayersReorder { relative_index_offset : -1 } . into ( ) ) ;
1411
+ }
1412
+ SelectedLayersLowerToBack => {
1413
+ responses. push_front ( DocumentMessage :: SelectedLayersReorder { relative_index_offset : isize:: MIN } . into ( ) ) ;
1414
+ }
1415
+ SelectedLayersRaise => {
1416
+ responses. push_front ( DocumentMessage :: SelectedLayersReorder { relative_index_offset : 1 } . into ( ) ) ;
1417
+ }
1418
+ SelectedLayersRaiseToFront => {
1419
+ responses. push_front ( DocumentMessage :: SelectedLayersReorder { relative_index_offset : isize:: MAX } . into ( ) ) ;
1420
+ }
1421
+ SelectedLayersReorder { relative_index_offset } => {
1422
+ self . selected_layers_reorder ( relative_index_offset, responses) ;
1423
+ }
1402
1424
SelectLayer { layer_path, ctrl, shift } => {
1403
1425
let mut paths = vec ! [ ] ;
1404
1426
let last_selection_exists = !self . layer_range_selection_reference . is_empty ( ) ;
@@ -1611,7 +1633,10 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
1611
1633
DeleteSelectedLayers ,
1612
1634
DuplicateSelectedLayers ,
1613
1635
NudgeSelectedLayers ,
1614
- ReorderSelectedLayers ,
1636
+ SelectedLayersLower ,
1637
+ SelectedLayersLowerToBack ,
1638
+ SelectedLayersRaise ,
1639
+ SelectedLayersRaiseToFront ,
1615
1640
GroupSelectedLayers ,
1616
1641
UngroupSelectedLayers ,
1617
1642
) ;
0 commit comments