Move layer selection logic from vue to editor (#410)

* Add vue selectLayer(layer, ctrl, shift)

* Individual selection working, range fill next

* Frontend package-lock.json seems apparently needs to be pushed. Weird.

* Selection working with ctrl, shift from editor. Still some bugs to sqaush with folder nesting.

* WIP resolving nesting folders issues

* Changed comparison approach, handling corner cases now

* Fully working selection.

* Reverted changes to package-lock.json

* Removed unused code

* Resolved ctrl click not behaving similar to windows

* Slight comment clarification

* Double checked a windows behavior and corrected. Changed last_selected name.

* Simplified if statement slightly.

* Made the naming clearer regarding UUIDs versus indices

* Clarified comments further

* Minor comment fixup

* Implemented suggestions, clarified comments

* Resolved todo regarding clearing selection when ctrl not pressed

* Ensure we only push responses when needed

Co-authored-by: Keavon Chambers <keavon@keavon.com>
Reviewed by: @TrueDoctor <3
This commit is contained in:
Oliver Davies
2021-12-22 17:45:14 -08:00
committed by Keavon Chambers
parent 30418c51f8
commit e54fedc6a5
7 changed files with 122 additions and 75 deletions

View File

@@ -64,6 +64,7 @@ pub struct DocumentMessageHandler {
pub saved_document_identifier: u64,
pub name: String,
pub layer_data: HashMap<Vec<LayerId>, LayerData>,
layer_range_selection_reference: Vec<LayerId>,
movement_handler: MovementMessageHandler,
transform_layer_handler: TransformLayerMessageHandler,
pub snapping_enabled: bool,
@@ -78,6 +79,7 @@ impl Default for DocumentMessageHandler {
name: String::from("Untitled Document"),
saved_document_identifier: 0,
layer_data: vec![(vec![], LayerData::new(true))].into_iter().collect(),
layer_range_selection_reference: Vec::new(),
movement_handler: MovementMessageHandler::default(),
transform_layer_handler: TransformLayerMessageHandler::default(),
snapping_enabled: true,
@@ -96,12 +98,13 @@ pub enum DocumentMessage {
SetSelectedLayers(Vec<Vec<LayerId>>),
AddSelectedLayers(Vec<Vec<LayerId>>),
SelectAllLayers,
SelectLayer(Vec<LayerId>, bool, bool),
SelectionChanged,
DeselectAllLayers,
DeleteLayer(Vec<LayerId>),
DeleteSelectedLayers,
DuplicateSelectedLayers,
CreateFolder(Vec<LayerId>),
CreateEmptyFolder(Vec<LayerId>),
SetBlendModeForSelectedLayers(BlendMode),
SetOpacityForSelectedLayers(f64),
RenameLayer(Vec<LayerId>, String),
@@ -312,6 +315,7 @@ impl DocumentMessageHandler {
saved_document_identifier: 0,
name,
layer_data: vec![(vec![], LayerData::new(true))].into_iter().collect(),
layer_range_selection_reference: Vec::new(),
movement_handler: MovementMessageHandler::default(),
transform_layer_handler: TransformLayerMessageHandler::default(),
snapping_enabled: true,
@@ -497,14 +501,16 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
.into(),
)
}
CreateFolder(mut path) => {
CreateEmptyFolder(mut path) => {
let id = generate_uuid();
path.push(id);
self.layerdata_mut(&path).expanded = true;
responses.push_back(DocumentOperation::CreateFolder { path }.into())
}
GroupSelectedLayers => {
let common_prefix = self.graphene_document.common_prefix(self.selected_layers());
let selected_layers = self.selected_layers();
let common_prefix = self.graphene_document.common_layer_path_prefix(selected_layers);
let (_id, common_prefix) = common_prefix.split_last().unwrap_or((&0, &[]));
let mut new_folder_path = common_prefix.to_vec();
@@ -568,6 +574,43 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
responses.push_back(DocumentOperation::DuplicateLayer { path }.into());
}
}
SelectLayer(selected, ctrl, shift) => {
let mut paths = vec![];
let last_selection_exists = !self.layer_range_selection_reference.is_empty();
// If we have shift pressed and a layer already selected then fill the range
if shift && last_selection_exists {
// Fill the selection range
self.layer_data
.iter()
.filter(|(target, _)| self.graphene_document.layer_is_between(&target, &selected, &self.layer_range_selection_reference))
.for_each(|(layer_path, _)| {
paths.push(layer_path.clone());
});
} else {
if ctrl {
// Toggle selection when holding ctrl
let layer = self.layerdata_mut(&selected);
layer.selected = !layer.selected;
responses.push_back(LayerChanged(selected.clone()).into());
} else {
paths.push(selected.clone());
}
// Set our last selection reference
self.layer_range_selection_reference = selected;
}
// Don't create messages for empty operations
if paths.len() > 0 {
// Add or set our selected layers
if ctrl {
responses.push_front(AddSelectedLayers(paths).into());
} else {
responses.push_front(SetSelectedLayers(paths).into());
}
}
}
SetSelectedLayers(paths) => {
self.layer_data.iter_mut().filter(|(_, layer_data)| layer_data.selected).for_each(|(path, layer_data)| {
layer_data.selected = false;
@@ -593,7 +636,10 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
.collect::<Vec<_>>();
responses.push_front(SetSelectedLayers(all_layer_paths).into());
}
DeselectAllLayers => responses.push_front(SetSelectedLayers(vec![]).into()),
DeselectAllLayers => {
responses.push_front(SetSelectedLayers(vec![]).into());
self.layer_range_selection_reference.clear();
}
DocumentHistoryBackward => self.undo(responses).unwrap_or_else(|e| log::warn!("{}", e)),
DocumentHistoryForward => self.redo(responses).unwrap_or_else(|e| log::warn!("{}", e)),
Undo => {
@@ -639,7 +685,8 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
self.layer_data.insert(path.clone(), LayerData::new(false));
responses.push_back(LayerChanged(path.clone()).into());
if !self.graphene_document.layer(&path).unwrap().overlay {
responses.push_back(SetSelectedLayers(vec![path]).into())
self.layer_range_selection_reference = path.clone();
responses.push_back(SetSelectedLayers(vec![path]).into());
}
}
DocumentResponse::DocumentChanged => responses.push_back(RenderDocument.into()),