Event broadcasting system (#692)

* broadcast system implemented but not everywhere

* unused types

* code review with keavon

* - optional signal mappings
- tool.rs simplification

* Cleanup

* reduced code duplication in `tool.rs`

* ran cargo fmt

* code review changes

* fix merge error

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mfish33
2022-07-03 08:06:27 -06:00
committed by GitHub
co-authored by Keavon Chambers
parent 0ad6e41a59
commit 535b4fff85
35 changed files with 634 additions and 451 deletions
@@ -41,7 +41,7 @@ impl MessageHandler<ArtboardMessage, &FontCache> for ArtboardMessageHandler {
DocumentResponse::DocumentChanged => responses.push_back(ArtboardMessage::RenderArtboards.into()),
_ => {}
};
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}
Ok(None) => {}
-1
View File
@@ -102,7 +102,6 @@ pub enum DocumentMessage {
RollbackTransaction,
SaveDocument,
SelectAllLayers,
SelectionChanged,
SelectLayer {
layer_path: Vec<LayerId>,
ctrl: bool,
+15 -31
View File
@@ -1,8 +1,8 @@
use super::clipboards::Clipboard;
use super::layer_panel::{layer_panel_entry, LayerMetadata, LayerPanelEntry, RawBuffer};
use super::properties_panel_message_handler::PropertiesPanelMessageHandlerData;
use super::utility_types::DocumentMode;
use super::utility_types::{AlignAggregate, AlignAxis, DocumentSave, FlipAxis};
use super::utility_types::{DocumentMode, TargetDocument};
use super::{vectorize_layer_metadata, PropertiesPanelMessageHandler};
use super::{ArtboardMessageHandler, MovementMessageHandler, OverlaysMessageHandler, TransformLayerMessageHandler};
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};
@@ -864,7 +864,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
}
DocumentResponse::DocumentChanged => responses.push_back(RenderDocument.into()),
};
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}
Err(e) => log::error!("DocumentError: {:?}", e),
@@ -894,6 +894,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
PropertiesPanelMessageHandlerData {
artwork_document: &self.graphene_document,
artboard_document: &self.artboard_message_handler.artboards_graphene_document,
selected_layers: &mut self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then(|| path.as_slice())),
font_cache,
},
responses,
@@ -910,22 +911,9 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
responses.extend(self.select_layer(layer_path, font_cache));
}
let selected_paths: Vec<Vec<u64>> = self.selected_layers().map(|path| path.to_vec()).collect();
if selected_paths.is_empty() {
responses.push_back(PropertiesPanelMessage::ClearSelection.into())
} else {
responses.push_back(
PropertiesPanelMessage::SetActiveLayers {
paths: selected_paths,
document: TargetDocument::Artwork,
}
.into(),
)
}
// TODO: Correctly update layer panel in clear_selection instead of here
responses.push_back(FolderChanged { affected_folder_path: vec![] }.into());
responses.push_back(DocumentMessage::SelectionChanged.into());
responses.push_back(BroadcastSignal::SelectionChanged.into());
self.update_layer_tree_options_bar_widgets(responses, font_cache);
}
@@ -963,7 +951,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
.into(),
);
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}
BooleanOperation(op) => {
@@ -997,7 +985,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
}
DeleteLayer { layer_path } => {
responses.push_front(DocumentOperation::DeleteLayer { path: layer_path.clone() }.into());
responses.push_front(ToolMessage::AbortCurrentTool.into());
responses.push_front(BroadcastSignal::ToolAbort.into());
responses.push_back(PropertiesPanelMessage::CheckSelectedWasDeleted { path: layer_path }.into());
}
DeleteSelectedLayers => {
@@ -1007,7 +995,8 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
responses.push_front(DocumentMessage::DeleteLayer { layer_path: path.to_vec() }.into());
}
responses.push_front(DocumentMessage::SelectionChanged.into());
responses.push_front(BroadcastSignal::SelectionChanged.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
DeselectAllLayers => {
responses.push_front(SetSelectedLayers { replacement_selected_layers: vec![] }.into());
@@ -1106,7 +1095,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
.into(),
);
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}
FolderChanged { affected_folder_path } => {
@@ -1183,7 +1172,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
};
responses.push_back(operation.into());
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
PasteImage { mime, image_data, mouse } => {
let path = vec![generate_uuid()];
@@ -1221,7 +1210,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
Redo => {
responses.push_back(SelectToolMessage::Abort.into());
responses.push_back(DocumentHistoryForward.into());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(RenderDocument.into());
responses.push_back(FolderChanged { affected_folder_path: vec![] }.into());
}
@@ -1353,11 +1342,6 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
let all = self.all_layers().map(|path| path.to_vec()).collect();
responses.push_front(SetSelectedLayers { replacement_selected_layers: all }.into());
}
SelectionChanged => {
// TODO: Hoist this duplicated code into wider system
responses.push_back(ToolMessage::SelectionChanged.into());
responses.push_back(ToolMessage::DocumentIsDirty.into());
}
SelectLayer { layer_path, ctrl, shift } => {
let mut paths = vec![];
let last_selection_exists = !self.layer_range_selection_reference.is_empty();
@@ -1382,7 +1366,7 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
}
.into(),
);
responses.push_back(DocumentMessage::SelectionChanged.into());
responses.push_back(BroadcastSignal::SelectionChanged.into());
} else {
paths.push(layer_path.clone());
}
@@ -1476,12 +1460,12 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
}
ToggleLayerVisibility { layer_path } => {
responses.push_back(DocumentOperation::ToggleLayerVisibility { path: layer_path }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
Undo => {
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
responses.push_back(DocumentHistoryBackward.into());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(RenderDocument.into());
responses.push_back(FolderChanged { affected_folder_path: vec![] }.into());
}
@@ -153,7 +153,7 @@ impl MessageHandler<MovementMessage, (&Document, &InputPreprocessorMessageHandle
self.zoom = 1.
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
responses.push_back(PortfolioMessage::UpdateDocumentWidgets.into());
self.create_document_transform(&ipp.viewport_bounds, responses);
@@ -243,12 +243,12 @@ impl MessageHandler<MovementMessage, (&Document, &InputPreprocessorMessageHandle
SetCanvasRotation { angle_radians } => {
self.tilt = angle_radians;
self.create_document_transform(&ipp.viewport_bounds, responses);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(PortfolioMessage::UpdateDocumentWidgets.into());
}
SetCanvasZoom { zoom_factor } => {
self.zoom = zoom_factor.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
responses.push_back(PortfolioMessage::UpdateDocumentWidgets.into());
self.create_document_transform(&ipp.viewport_bounds, responses);
@@ -256,7 +256,7 @@ impl MessageHandler<MovementMessage, (&Document, &InputPreprocessorMessageHandle
TransformCanvasEnd => {
self.tilt = self.snapped_angle();
self.zoom = self.snapped_scale();
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(ToolMessage::UpdateCursor.into());
responses.push_back(ToolMessage::UpdateHints.into());
self.snap_tilt = false;
@@ -270,7 +270,7 @@ impl MessageHandler<MovementMessage, (&Document, &InputPreprocessorMessageHandle
let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
self.pan += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
self.create_document_transform(&ipp.viewport_bounds, responses);
}
TranslateCanvasBegin => {
@@ -284,7 +284,7 @@ impl MessageHandler<MovementMessage, (&Document, &InputPreprocessorMessageHandle
let transformed_delta = document.root.transform.inverse().transform_vector2(delta * ipp.viewport_bounds.size());
self.pan += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
self.create_document_transform(&ipp.viewport_bounds, responses);
}
WheelCanvasTranslate { use_y_as_x } => {
@@ -58,7 +58,7 @@ impl PortfolioMessageHandler {
fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque<Message>) {
// Special case when loading a document on an empty page
if replace_first_empty && self.active_document().is_unmodified_default() {
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
responses.push_back(PortfolioMessage::CloseDocument { document_id: self.active_document_id }.into());
let active_document_index = self
@@ -168,7 +168,7 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
self.document_ids.push(new_document_id);
self.active_document_id = new_document_id;
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
responses.push_back(PortfolioMessage::UpdateOpenDocumentsList.into());
responses.push_back(PortfolioMessage::SelectDocument { document_id: new_document_id }.into())
}
@@ -208,7 +208,7 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
CloseDocumentWithConfirmation { document_id } => {
let target_document = self.documents.get(&document_id).unwrap();
if target_document.is_saved() {
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
responses.push_back(PortfolioMessage::CloseDocument { document_id }.into());
} else {
let dialog = dialog::CloseDocument {
@@ -274,13 +274,13 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
let name = self.generate_new_document_name();
let new_document = DocumentMessageHandler::with_name(name, ipp);
let document_id = generate_uuid();
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
self.load_document(new_document, document_id, false, responses);
}
NewDocumentWithName { name } => {
let new_document = DocumentMessageHandler::with_name(name, ipp);
let document_id = generate_uuid();
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
self.load_document(new_document, document_id, false, responses);
}
NextDocument => {
@@ -431,7 +431,7 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
if !active_document.is_saved() {
responses.push_back(PortfolioMessage::AutoSaveDocument { document_id: self.active_document_id }.into());
}
responses.push_back(ToolMessage::AbortCurrentTool.into());
responses.push_back(BroadcastSignal::ToolAbort.into());
responses.push_back(SetActiveDocument { document_id }.into());
responses.push_back(FrontendMessage::UpdateActiveDocument { document_id }.into());
@@ -440,7 +440,8 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
for layer in self.documents.get(&document_id).unwrap().layer_metadata.keys() {
responses.push_back(DocumentMessage::LayerChanged { affected_layer_path: layer.clone() }.into());
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::SelectionChanged.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
responses.push_back(PortfolioMessage::UpdateDocumentWidgets.into());
}
SetActiveDocument { document_id } => {
@@ -12,6 +12,7 @@ pub enum PropertiesPanelMessage {
CheckSelectedWasDeleted { path: Vec<LayerId> },
CheckSelectedWasUpdated { path: Vec<LayerId> },
ClearSelection,
Init,
ModifyFill { fill: Fill },
ModifyFont { font_family: String, font_style: String, size: f64 },
ModifyName { name: String },
@@ -20,6 +21,7 @@ pub enum PropertiesPanelMessage {
ModifyTransform { value: f64, transform_op: TransformOp },
ResendActiveProperties,
SetActiveLayers { paths: Vec<Vec<LayerId>>, document: TargetDocument },
UpdateSelectedDocumentProperties,
}
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
@@ -110,6 +110,7 @@ impl PropertiesPanelMessageHandler {
pub struct PropertiesPanelMessageHandlerData<'a> {
pub artwork_document: &'a GrapheneDocument,
pub artboard_document: &'a GrapheneDocument,
pub selected_layers: &'a mut dyn Iterator<Item = &'a [LayerId]>,
pub font_cache: &'a FontCache,
}
@@ -119,6 +120,7 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
let PropertiesPanelMessageHandlerData {
artwork_document,
artboard_document,
selected_layers,
font_cache,
} = data;
let get_document = |document_selector: TargetDocument| match document_selector {
@@ -154,6 +156,13 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
);
self.active_selection = None;
}
Init => responses.push_back(
BroadcastMessage::SubscribeSignal {
on: BroadcastSignal::SelectionChanged,
send: Box::new(PropertiesPanelMessage::UpdateSelectedDocumentProperties.into()),
}
.into(),
),
ModifyFont { font_family, font_style, size } => {
let (path, _) = self.active_selection.clone().expect("Received update for properties panel with no active layer");
@@ -233,6 +242,13 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
}
}
}
UpdateSelectedDocumentProperties => responses.push_back(
PropertiesPanelMessage::SetActiveLayers {
paths: selected_layers.map(|path| path.to_vec()).collect(),
document: TargetDocument::Artwork,
}
.into(),
),
}
}
@@ -55,7 +55,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::None;
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
BeginGrab => {
if let TransformOperation::Grabbing(_) = self.transform_operation {
@@ -66,7 +66,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::Grabbing(Default::default());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
BeginRotate => {
if let TransformOperation::Rotating(_) = self.transform_operation {
@@ -77,7 +77,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::Rotating(Default::default());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
BeginScale => {
if let TransformOperation::Scaling(_) = self.transform_operation {
@@ -89,7 +89,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::Scaling(Default::default());
self.transform_operation.apply_transform_operation(&mut selected, self.snap);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
CancelTransformOperation => {
selected.revert_operation();
@@ -99,7 +99,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::None;
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
ConstrainX => self.transform_operation.constrain_axis(Axis::X, &mut selected, self.snap),
ConstrainY => self.transform_operation.constrain_axis(Axis::Y, &mut selected, self.snap),
+1 -1
View File
@@ -258,7 +258,7 @@ impl<'a> Selected<'a> {
);
}
self.responses.push_back(ToolMessage::DocumentIsDirty.into());
self.responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}