Skip to content

Commit 04c1b2e

Browse files
mfish33Keavon
andcommitted
Remove all use of document indices (#406)
* removed all use of document indicies * -add u64 support for wasm bridge * fixed rust formating * Cleaned up FrontendDocumentState in js-messages * Tiny tweaks from code review * - moved more of closeDocumentWithConfirmation to rust - updated serde_wasm_bindgen to add feature flag * changed to upsteam version of serde_wasm_bindgen * cargo fmt * -fix event propigation on delete - Js message change class extention to typedef * changed another typedef * cargo fmt Co-authored-by: Keavon Chambers <[email protected]>
1 parent 1594b9c commit 04c1b2e

File tree

13 files changed

+212
-183
lines changed

13 files changed

+212
-183
lines changed

Cargo.lock

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/communication/dispatcher.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@ pub struct Dispatcher {
1717
pub responses: Vec<FrontendMessage>,
1818
}
1919

20-
const GROUP_MESSAGES: &[MessageDiscriminant] = &[
20+
// For optimization, these are messages guaranteed to be redundant when repeated
21+
// The last occurrence of the message in the message queue is sufficient to ensure correctness
22+
// In addition, these messages do not change any state in the backend (aside from caches)
23+
const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
2124
MessageDiscriminant::Documents(DocumentsMessageDiscriminant::Document(DocumentMessageDiscriminant::RenderDocument)),
2225
MessageDiscriminant::Documents(DocumentsMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
2326
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateLayer),
2427
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::DisplayFolderTreeStructure),
28+
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateOpenDocumentsList),
2529
MessageDiscriminant::Tool(ToolMessageDiscriminant::SelectedLayersChanged),
2630
];
2731

@@ -31,7 +35,8 @@ impl Dispatcher {
3135

3236
use Message::*;
3337
while let Some(message) = self.messages.pop_front() {
34-
if GROUP_MESSAGES.contains(&message.to_discriminant()) && self.messages.contains(&message) {
38+
// Skip processing of this message if it will be processed later
39+
if SIDE_EFFECT_FREE_MESSAGES.contains(&message.to_discriminant()) && self.messages.contains(&message) {
3540
continue;
3641
}
3742
self.log_message(&message);

editor/src/document/document_message_handler.rs

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::frontend::frontend_message_handler::FrontendDocumentDetails;
12
use crate::input::InputPreprocessor;
23
use crate::message_prelude::*;
34
use graphene::layers::Layer;
@@ -18,11 +19,12 @@ pub enum DocumentsMessage {
1819
insert_index: isize,
1920
},
2021
Paste,
21-
SelectDocument(usize),
22-
CloseDocument(usize),
22+
SelectDocument(u64),
23+
CloseDocument(u64),
2324
#[child]
2425
Document(DocumentMessage),
2526
CloseActiveDocumentWithConfirmation,
27+
CloseDocumentWithConfirmation(u64),
2628
CloseAllDocumentsWithConfirmation,
2729
CloseAllDocuments,
2830
RequestAboutGraphiteDialog,
@@ -38,20 +40,17 @@ pub enum DocumentsMessage {
3840
pub struct DocumentsMessageHandler {
3941
documents: HashMap<u64, DocumentMessageHandler>,
4042
document_ids: Vec<u64>,
41-
document_id_counter: u64,
42-
active_document_index: usize,
43+
active_document_id: u64,
4344
copy_buffer: Vec<Layer>,
4445
}
4546

4647
impl DocumentsMessageHandler {
4748
pub fn active_document(&self) -> &DocumentMessageHandler {
48-
let id = self.document_ids[self.active_document_index];
49-
self.documents.get(&id).unwrap()
49+
self.documents.get(&self.active_document_id).unwrap()
5050
}
5151

5252
pub fn active_document_mut(&mut self) -> &mut DocumentMessageHandler {
53-
let id = self.document_ids[self.active_document_index];
54-
self.documents.get_mut(&id).unwrap()
53+
self.documents.get_mut(&self.active_document_id).unwrap()
5554
}
5655

5756
fn generate_new_document_name(&self) -> String {
@@ -78,21 +77,27 @@ impl DocumentsMessageHandler {
7877
}
7978

8079
fn load_document(&mut self, new_document: DocumentMessageHandler, responses: &mut VecDeque<Message>) {
81-
self.document_id_counter += 1;
82-
self.active_document_index = self.document_ids.len();
83-
self.document_ids.push(self.document_id_counter);
84-
self.documents.insert(self.document_id_counter, new_document);
80+
let new_id = generate_uuid();
81+
self.active_document_id = new_id;
82+
self.document_ids.push(new_id);
83+
self.documents.insert(new_id, new_document);
8584

8685
// Send the new list of document tab names
8786
let open_documents = self
8887
.document_ids
8988
.iter()
90-
.filter_map(|id| self.documents.get(&id).map(|doc| (doc.name.clone(), doc.is_saved())))
89+
.filter_map(|id| {
90+
self.documents.get(&id).map(|doc| FrontendDocumentDetails {
91+
is_saved: doc.is_saved(),
92+
id: *id,
93+
name: doc.name.clone(),
94+
})
95+
})
9196
.collect::<Vec<_>>();
9297

9398
responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into());
9499

95-
responses.push_back(DocumentsMessage::SelectDocument(self.active_document_index).into());
100+
responses.push_back(DocumentsMessage::SelectDocument(self.active_document_id).into());
96101
responses.push_back(DocumentMessage::RenderDocument.into());
97102
responses.push_back(DocumentMessage::DocumentStructureChanged.into());
98103
for layer in self.active_document().layer_data.keys() {
@@ -104,18 +109,23 @@ impl DocumentsMessageHandler {
104109
pub fn ordered_document_iterator(&self) -> impl Iterator<Item = &DocumentMessageHandler> {
105110
self.document_ids.iter().map(|id| self.documents.get(id).expect("document id was not found in the document hashmap"))
106111
}
112+
113+
fn document_index(&self, document_id: u64) -> usize {
114+
self.document_ids.iter().position(|id| id == &document_id).expect("Active document is missing from document ids")
115+
}
107116
}
108117

109118
impl Default for DocumentsMessageHandler {
110119
fn default() -> Self {
111120
let mut documents_map: HashMap<u64, DocumentMessageHandler> = HashMap::with_capacity(1);
112-
documents_map.insert(0, DocumentMessageHandler::default());
121+
let starting_key = generate_uuid();
122+
documents_map.insert(starting_key, DocumentMessageHandler::default());
123+
113124
Self {
114125
documents: documents_map,
115-
document_ids: vec![0],
126+
document_ids: vec![starting_key],
116127
copy_buffer: vec![],
117-
active_document_index: 0,
118-
document_id_counter: 0,
128+
active_document_id: starting_key,
119129
}
120130
}
121131
}
@@ -129,24 +139,27 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
129139
responses.push_back(FrontendMessage::DisplayAboutGraphiteDialog.into());
130140
}
131141
Document(message) => self.active_document_mut().process_action(message, ipp, responses),
132-
SelectDocument(index) => {
133-
// NOTE: Potentially this will break if we ever exceed 56 bit values due to how the message parsing system works.
134-
assert!(index < self.documents.len(), "Tried to select a document that was not initialized");
135-
self.active_document_index = index;
136-
responses.push_back(FrontendMessage::SetActiveDocument { document_index: index }.into());
142+
SelectDocument(id) => {
143+
self.active_document_id = id;
144+
responses.push_back(FrontendMessage::SetActiveDocument { document_id: id }.into());
137145
responses.push_back(RenderDocument.into());
138146
responses.push_back(DocumentMessage::DocumentStructureChanged.into());
139147
for layer in self.active_document().layer_data.keys() {
140148
responses.push_back(DocumentMessage::LayerChanged(layer.clone()).into());
141149
}
142150
}
143151
CloseActiveDocumentWithConfirmation => {
144-
responses.push_back(
145-
FrontendMessage::DisplayConfirmationToCloseDocument {
146-
document_index: self.active_document_index,
147-
}
148-
.into(),
149-
);
152+
responses.push_back(DocumentsMessage::CloseDocumentWithConfirmation(self.active_document_id).into());
153+
}
154+
CloseDocumentWithConfirmation(id) => {
155+
let target_document = self.documents.get(&id).unwrap();
156+
if target_document.is_saved() {
157+
responses.push_back(DocumentsMessage::CloseDocument(id).into());
158+
} else {
159+
responses.push_back(FrontendMessage::DisplayConfirmationToCloseDocument { document_id: id }.into());
160+
// Select the document being closed
161+
responses.push_back(DocumentsMessage::SelectDocument(id).into());
162+
}
150163
}
151164
CloseAllDocumentsWithConfirmation => {
152165
responses.push_back(FrontendMessage::DisplayConfirmationToCloseAllDocuments.into());
@@ -159,38 +172,44 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
159172
// Create a new blank document
160173
responses.push_back(NewDocument.into());
161174
}
162-
CloseDocument(index) => {
163-
assert!(index < self.documents.len(), "Tried to close a document that was not initialized");
164-
// Get the ID based on the current collection of the documents.
165-
let id = self.document_ids[index];
166-
// Map the ID to an index and remove the document
175+
CloseDocument(id) => {
176+
let document_index = self.document_index(id);
167177
self.documents.remove(&id);
168-
self.document_ids.remove(index);
178+
self.document_ids.remove(document_index);
169179

170180
// Last tab was closed, so create a new blank tab
171181
if self.document_ids.is_empty() {
172-
self.document_id_counter += 1;
173-
self.document_ids.push(self.document_id_counter);
174-
self.documents.insert(self.document_id_counter, DocumentMessageHandler::default());
182+
let new_id = generate_uuid();
183+
self.document_ids.push(new_id);
184+
self.documents.insert(new_id, DocumentMessageHandler::default());
175185
}
176186

177-
self.active_document_index = if self.active_document_index >= self.document_ids.len() {
178-
self.document_ids.len() - 1
187+
self.active_document_id = if id != self.active_document_id {
188+
// If we are not closing the active document, stay on it
189+
self.active_document_id
190+
} else if document_index >= self.document_ids.len() {
191+
// If we closed the last document take the one previous (same as last)
192+
*self.document_ids.last().unwrap()
179193
} else {
180-
index
194+
// Move to the next tab
195+
self.document_ids[document_index]
181196
};
182197

183198
// Send the new list of document tab names
184-
let open_documents = self.ordered_document_iterator().map(|doc| (doc.name.clone(), doc.is_saved())).collect();
185-
199+
let open_documents = self
200+
.document_ids
201+
.iter()
202+
.filter_map(|id| {
203+
self.documents.get(&id).map(|doc| FrontendDocumentDetails {
204+
is_saved: doc.is_saved(),
205+
id: *id,
206+
name: doc.name.clone(),
207+
})
208+
})
209+
.collect::<Vec<_>>();
186210
// Update the list of new documents on the front end, active tab, and ensure that document renders
187211
responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into());
188-
responses.push_back(
189-
FrontendMessage::SetActiveDocument {
190-
document_index: self.active_document_index,
191-
}
192-
.into(),
193-
);
212+
responses.push_back(FrontendMessage::SetActiveDocument { document_id: self.active_document_id }.into());
194213
responses.push_back(RenderDocument.into());
195214
responses.push_back(DocumentMessage::DocumentStructureChanged.into());
196215
for layer in self.active_document().layer_data.keys() {
@@ -222,17 +241,31 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
222241
}
223242
UpdateOpenDocumentsList => {
224243
// Send the list of document tab names
225-
let open_documents = self.ordered_document_iterator().map(|doc| (doc.name.clone(), doc.is_saved())).collect();
244+
let open_documents = self
245+
.document_ids
246+
.iter()
247+
.filter_map(|id| {
248+
self.documents.get(&id).map(|doc| FrontendDocumentDetails {
249+
is_saved: doc.is_saved(),
250+
id: *id,
251+
name: doc.name.clone(),
252+
})
253+
})
254+
.collect::<Vec<_>>();
226255
responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into());
227256
}
228257
NextDocument => {
229-
let next = (self.active_document_index + 1) % self.document_ids.len();
230-
responses.push_back(SelectDocument(next).into());
258+
let current_index = self.document_index(self.active_document_id);
259+
let next_index = (current_index + 1) % self.document_ids.len();
260+
let next_id = self.document_ids[next_index];
261+
responses.push_back(SelectDocument(next_id).into());
231262
}
232263
PrevDocument => {
233264
let len = self.document_ids.len();
234-
let prev = (self.active_document_index + len - 1) % len;
235-
responses.push_back(SelectDocument(prev).into());
265+
let current_index = self.document_index(self.active_document_id);
266+
let prev_index = (current_index + len - 1) % len;
267+
let prev_id = self.document_ids[prev_index];
268+
responses.push_back(SelectDocument(prev_id).into());
236269
}
237270
Copy => {
238271
let paths = self.active_document().selected_layers_sorted();

editor/src/document/layer_panel.rs

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ use crate::consts::VIEWPORT_ROTATE_SNAP_INTERVAL;
22
use glam::{DAffine2, DVec2};
33
use graphene::layers::{style::ViewMode, BlendMode, Layer, LayerData as DocumentLayerData, LayerDataType};
44
use graphene::LayerId;
5-
use serde::{
6-
ser::{SerializeSeq, SerializeStruct},
7-
Deserialize, Serialize,
8-
};
5+
use serde::{ser::SerializeStruct, Deserialize, Serialize};
96
use std::collections::HashMap;
107
use std::fmt;
118

@@ -84,39 +81,11 @@ pub fn layer_panel_entry(layer_data: &LayerData, transform: DAffine2, layer: &La
8481
opacity: layer.opacity,
8582
layer_type: (&layer.data).into(),
8683
layer_data: *layer_data,
87-
path: path.into(),
84+
path,
8885
thumbnail,
8986
}
9087
}
9188

92-
#[derive(Debug, Clone, Deserialize, PartialEq)]
93-
pub struct Path(Vec<LayerId>);
94-
95-
impl From<Vec<LayerId>> for Path {
96-
fn from(iter: Vec<LayerId>) -> Self {
97-
Self(iter)
98-
}
99-
}
100-
impl Serialize for Path {
101-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102-
where
103-
S: serde::Serializer,
104-
{
105-
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
106-
for e in self.0.iter() {
107-
#[cfg(target_arch = "wasm32")]
108-
{
109-
// LayerIds are sent as (u32, u32) because json does not support u64s
110-
let id = ((e >> 32) as u32, (e << 32 >> 32) as u32);
111-
seq.serialize_element(&id)?;
112-
}
113-
#[cfg(not(target_arch = "wasm32"))]
114-
seq.serialize_element(e)?;
115-
}
116-
seq.end()
117-
}
118-
}
119-
12089
#[derive(Debug, Clone, Deserialize, PartialEq)]
12190
pub struct RawBuffer(Vec<u8>);
12291

@@ -152,7 +121,7 @@ pub struct LayerPanelEntry {
152121
pub opacity: f64,
153122
pub layer_type: LayerType,
154123
pub layer_data: LayerData,
155-
pub path: crate::document::layer_panel::Path,
124+
pub path: Vec<LayerId>,
156125
pub thumbnail: String,
157126
}
158127

0 commit comments

Comments
 (0)