mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 19:08:05 +08:00
Implement bounding box for selected layers (#349)
* Implement bounding box for selected layers * Add shift modifier for multi selection
This commit is contained in:
committed by
Keavon Chambers
parent
7c64e1a816
commit
68d8ae4804
@@ -66,8 +66,10 @@ pub enum DocumentMessage {
|
||||
#[child]
|
||||
Movement(MovementMessage),
|
||||
DispatchOperation(Box<DocumentOperation>),
|
||||
SelectLayers(Vec<Vec<LayerId>>),
|
||||
SetSelectedLayers(Vec<Vec<LayerId>>),
|
||||
AddSelectedLayers(Vec<Vec<LayerId>>),
|
||||
SelectAllLayers,
|
||||
SelectionChanged,
|
||||
DeselectAllLayers,
|
||||
DeleteLayer(Vec<LayerId>),
|
||||
DeleteSelectedLayers,
|
||||
@@ -125,9 +127,17 @@ impl DocumentMessageHandler {
|
||||
self.layer_data.values_mut().for_each(|layer_data| layer_data.selected = false);
|
||||
}
|
||||
fn select_layer(&mut self, path: &[LayerId]) -> Option<Message> {
|
||||
if self.document.layer(path).ok()?.overlay {
|
||||
return None;
|
||||
}
|
||||
self.layer_data(path).selected = true;
|
||||
let data = self.layer_panel_entry(path.to_vec()).ok()?;
|
||||
// TODO: Add deduplication
|
||||
(!path.is_empty()).then(|| self.handle_folder_changed(path[..path.len() - 1].to_vec())).flatten()
|
||||
(!path.is_empty()).then(|| FrontendMessage::UpdateLayer { path: path.to_vec(), data }.into())
|
||||
}
|
||||
pub fn selected_layers_bounding_box(&self) -> Option<[DVec2; 2]> {
|
||||
let paths = self.selected_layers().map(|vec| &vec[..]);
|
||||
self.document.combined_viewport_bounding_box(paths)
|
||||
}
|
||||
pub fn layerdata(&self, path: &[LayerId]) -> &LayerData {
|
||||
self.layer_data.get(path).expect("Layerdata does not exist")
|
||||
@@ -247,6 +257,7 @@ impl DocumentMessageHandler {
|
||||
.iter()
|
||||
.zip(paths.iter().zip(data))
|
||||
.rev()
|
||||
.filter(|(layer, _)| !layer.overlay)
|
||||
.map(|(layer, (path, data))| {
|
||||
layer_panel_entry(
|
||||
&data,
|
||||
@@ -332,34 +343,41 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
self.layer_data(&path).expanded ^= true;
|
||||
responses.extend(self.handle_folder_changed(path));
|
||||
}
|
||||
SelectionChanged => responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into()),
|
||||
DeleteSelectedLayers => {
|
||||
for path in self.selected_layers().cloned() {
|
||||
responses.push_back(DocumentOperation::DeleteLayer { path }.into())
|
||||
}
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
DuplicateSelectedLayers => {
|
||||
for path in self.selected_layers_sorted() {
|
||||
responses.push_back(DocumentOperation::DuplicateLayer { path }.into())
|
||||
}
|
||||
}
|
||||
SelectLayers(paths) => {
|
||||
SetSelectedLayers(paths) => {
|
||||
self.clear_selection();
|
||||
responses.push_front(AddSelectedLayers(paths).into());
|
||||
}
|
||||
AddSelectedLayers(paths) => {
|
||||
for path in paths {
|
||||
responses.extend(self.select_layer(&path));
|
||||
}
|
||||
// TODO: Correctly update layer panel in clear_selection instead of here
|
||||
responses.extend(self.handle_folder_changed(Vec::new()));
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
SelectAllLayers => {
|
||||
let all_layer_paths = self.layer_data.keys().filter(|path| !path.is_empty()).cloned().collect::<Vec<_>>();
|
||||
for path in all_layer_paths {
|
||||
responses.extend(self.select_layer(&path));
|
||||
}
|
||||
let all_layer_paths = self
|
||||
.layer_data
|
||||
.keys()
|
||||
.filter(|path| !path.is_empty() && !self.document.layer(path).unwrap().overlay)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
responses.push_back(SetSelectedLayers(all_layer_paths).into());
|
||||
}
|
||||
DeselectAllLayers => {
|
||||
self.clear_selection();
|
||||
let children = self.layer_panel(&[]).expect("The provided Path was not valid");
|
||||
responses.push_back(FrontendMessage::ExpandFolder { path: vec![], children }.into());
|
||||
responses.push_back(SetSelectedLayers(vec![]).into());
|
||||
}
|
||||
Undo => {
|
||||
// this is a temporary fix and will be addressed by #123
|
||||
@@ -378,7 +396,8 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
DocumentResponse::FolderChanged { path } => self.handle_folder_changed(path),
|
||||
DocumentResponse::DeletedLayer { path } => {
|
||||
self.layer_data.remove(&path);
|
||||
None
|
||||
|
||||
Some(SelectMessage::UpdateSelectionBoundingBox.into())
|
||||
}
|
||||
DocumentResponse::LayerChanged { path } => Some(
|
||||
FrontendMessage::UpdateLayer {
|
||||
@@ -387,7 +406,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
DocumentResponse::CreatedLayer { path } => self.select_layer(&path),
|
||||
DocumentResponse::CreatedLayer { path } => (!self.document.layer(&path).unwrap().overlay).then(|| SetSelectedLayers(vec![path]).into()),
|
||||
DocumentResponse::DocumentChanged => unreachable!(),
|
||||
})
|
||||
.flatten(),
|
||||
@@ -434,6 +453,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
};
|
||||
responses.push_back(operation.into());
|
||||
}
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
MoveSelectedLayersTo { path, insert_index } => {
|
||||
responses.push_back(DocumentsMessage::CopySelectedLayers.into());
|
||||
@@ -488,6 +508,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
}
|
||||
AlignSelectedLayers(axis, aggregate) => {
|
||||
@@ -520,6 +541,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
}
|
||||
RenameLayer(path, name) => responses.push_back(DocumentOperation::RenameLayer { path, name }.into()),
|
||||
|
||||
@@ -105,6 +105,7 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
|
||||
|
||||
layerdata.rotation += rotation;
|
||||
layerdata.snap_rotate = snapping;
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
responses.push_back(
|
||||
FrontendMessage::SetCanvasRotation {
|
||||
new_radians: layerdata.snapped_angle(),
|
||||
@@ -172,6 +173,7 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
|
||||
layerdata.rotation = new;
|
||||
self.create_document_transform_from_layerdata(layerdata, &ipp.viewport_bounds, responses);
|
||||
responses.push_back(FrontendMessage::SetCanvasRotation { new_radians: new }.into());
|
||||
responses.push_back(SelectMessage::UpdateSelectionBoundingBox.into());
|
||||
}
|
||||
ZoomCanvasToFitAll => {
|
||||
if let Some([pos1, pos2]) = document.visible_layers_bounding_box() {
|
||||
|
||||
Reference in New Issue
Block a user