Skip to content

Commit

Permalink
Merge branch 'GraphiteEditor:master' into tab
Browse files Browse the repository at this point in the history
  • Loading branch information
0SlowPoke0 authored Feb 11, 2025
2 parents 6dfa839 + f410efb commit bd3ae67
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 5 deletions.
1 change: 1 addition & 0 deletions editor/src/messages/portfolio/document/document_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pub enum DocumentMessage {
SelectedLayersLowerToBack,
SelectedLayersRaise,
SelectedLayersRaiseToFront,
SelectedLayersReverse,
SelectedLayersReorder {
relative_index_offset: isize,
},
Expand Down
107 changes: 104 additions & 3 deletions editor/src/messages/portfolio/document/document_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,9 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
DocumentMessage::SelectedLayersRaiseToFront => {
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: isize::MIN });
}
DocumentMessage::SelectedLayersReverse => {
self.selected_layers_reverse(responses);
}
DocumentMessage::SelectedLayersReorder { relative_index_offset } => {
self.selected_layers_reorder(relative_index_offset, responses);
}
Expand Down Expand Up @@ -1205,9 +1208,15 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
insert_index: folder_index,
});

let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(child);
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
let transform = undo_transform * layer_local_transform;
let metadata = self.network_interface.document_metadata();
let layer_local_transform = metadata.transform_to_viewport(child);
let undo_parent_transform = if parent == LayerNodeIdentifier::ROOT_PARENT {
// This is functionally the same as transform_to_viewport for the root, however to_node cannot run on the root in debug mode.
metadata.document_to_viewport.inverse()
} else {
metadata.transform_to_viewport(parent).inverse()
};
let transform = undo_parent_transform * layer_local_transform;
responses.add(GraphOperationMessage::TransformSet {
layer: child,
transform,
Expand Down Expand Up @@ -2149,6 +2158,98 @@ impl DocumentMessageHandler {
});
}

pub fn selected_layers_reverse(&mut self, responses: &mut VecDeque<Message>) {
let selected_layers = self.network_interface.selected_nodes(&[]).unwrap();
let metadata = self.metadata();
let selected_layer_set = selected_layers.selected_layers(metadata).collect::<HashSet<_>>();

// Ignore those with selected ancestors
let mut top_level_layers = Vec::new();
for &layer in &selected_layer_set {
let mut is_top_level = true;
let mut current_layer = layer;

while let Some(parent) = current_layer.parent(metadata) {
if selected_layer_set.contains(&parent) {
is_top_level = false;
break;
}
current_layer = parent;
}

if is_top_level {
top_level_layers.push(layer);
}
}

// Group selected layers by their parent
let mut grouped_layers: HashMap<LayerNodeIdentifier, Vec<(usize, LayerNodeIdentifier)>> = HashMap::new();
for &layer in &top_level_layers {
if let Some(parent) = layer.parent(metadata) {
let index = parent.children(metadata).position(|child| child == layer).unwrap_or(usize::MAX);

grouped_layers.entry(parent).or_default().push((index, layer));
}
}

let mut modified = false;

// Process each group separately
for (parent, mut layers) in grouped_layers {
// Retrieve all children under the parent
let all_children = parent.children(metadata).collect::<Vec<_>>();

// Separate unselected layers with their original indices
let unselected_layers = all_children
.iter()
.enumerate()
.filter_map(|(index, &layer)| if !selected_layer_set.contains(&layer) { Some((index, layer)) } else { None })
.collect::<Vec<_>>();

layers.sort_by_key(|(index, _)| *index);

let reversed_layers = layers.iter().rev().map(|(_, layer)| *layer).collect::<Vec<_>>();
let selected_positions = layers.iter().map(|(index, _)| *index).collect::<Vec<_>>();
let selected_iter = reversed_layers.into_iter();
let mut merged_layers = vec![None; all_children.len()];

for (&original_index, new_layer) in selected_positions.iter().zip(selected_iter) {
merged_layers[original_index] = Some(new_layer);
}

// Place unselected layers at their original positions
for (index, layer) in unselected_layers {
if merged_layers[index].is_none() {
merged_layers[index] = Some(layer);
}
}

let final_layers = merged_layers.into_iter().flatten().collect::<Vec<_>>();
if final_layers.is_empty() {
continue;
}

if !modified {
responses.add(DocumentMessage::AddTransaction);
}

for (index, layer) in final_layers.iter().enumerate() {
responses.add(NodeGraphMessage::MoveLayerToStack {
layer: *layer,
parent,
insert_index: index,
});
}

modified = true;
}

if modified {
responses.add(NodeGraphMessage::RunDocumentGraph);
responses.add(NodeGraphMessage::SendGraph);
}
}

pub fn selected_layers_reorder(&mut self, relative_index_offset: isize, responses: &mut VecDeque<Message>) {
let selected_nodes = self.network_interface.selected_nodes(&[]).unwrap();
let mut selected_layers = selected_nodes.selected_layers(self.metadata());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,7 @@ impl LayoutHolder for MenuBarMessageHandler {
vec![MenuBarEntry {
label: "Reverse".into(),
icon: Some("StackReverse".into()),
// shortcut: action_keys!(DocumentMessageDiscriminant::SelectedLayersReverse),
action: MenuBarEntry::create_action(|_| DialogMessage::RequestComingSoonDialog { issue: Some(2271) }.into()),
action: MenuBarEntry::create_action(|_| DocumentMessage::SelectedLayersReverse.into()),
disabled: no_active_document || !has_selected_layers,
..MenuBarEntry::default()
}],
Expand Down

0 comments on commit bd3ae67

Please sign in to comment.