Add a "Reverse" command to the "Order" menu (#2273)
* addded reverse for layer ordering * added reverse to layer odering * fixed indentation and spacing * added reverse for layer ordering * Added Reverse to layer ordering * Update document_message_handler.rs * Update document_message_handler.rs * Cleanup, fix compiling, fix history bug --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
ec8c8d6485
commit
bf3b05070c
|
|
@ -114,6 +114,7 @@ pub enum DocumentMessage {
|
|||
SelectedLayersLowerToBack,
|
||||
SelectedLayersRaise,
|
||||
SelectedLayersRaiseToFront,
|
||||
SelectedLayersReverse,
|
||||
SelectedLayersReorder {
|
||||
relative_index_offset: isize,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -2149,6 +2152,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());
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}],
|
||||
|
|
|
|||
Loading…
Reference in New Issue