1
+ use crate :: frontend:: frontend_message_handler:: FrontendDocumentDetails ;
1
2
use crate :: input:: InputPreprocessor ;
2
3
use crate :: message_prelude:: * ;
3
4
use graphene:: layers:: Layer ;
@@ -18,11 +19,12 @@ pub enum DocumentsMessage {
18
19
insert_index : isize ,
19
20
} ,
20
21
Paste ,
21
- SelectDocument ( usize ) ,
22
- CloseDocument ( usize ) ,
22
+ SelectDocument ( u64 ) ,
23
+ CloseDocument ( u64 ) ,
23
24
#[ child]
24
25
Document ( DocumentMessage ) ,
25
26
CloseActiveDocumentWithConfirmation ,
27
+ CloseDocumentWithConfirmation ( u64 ) ,
26
28
CloseAllDocumentsWithConfirmation ,
27
29
CloseAllDocuments ,
28
30
RequestAboutGraphiteDialog ,
@@ -38,20 +40,17 @@ pub enum DocumentsMessage {
38
40
pub struct DocumentsMessageHandler {
39
41
documents : HashMap < u64 , DocumentMessageHandler > ,
40
42
document_ids : Vec < u64 > ,
41
- document_id_counter : u64 ,
42
- active_document_index : usize ,
43
+ active_document_id : u64 ,
43
44
copy_buffer : Vec < Layer > ,
44
45
}
45
46
46
47
impl DocumentsMessageHandler {
47
48
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 ( )
50
50
}
51
51
52
52
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 ( )
55
54
}
56
55
57
56
fn generate_new_document_name ( & self ) -> String {
@@ -78,21 +77,27 @@ impl DocumentsMessageHandler {
78
77
}
79
78
80
79
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) ;
85
84
86
85
// Send the new list of document tab names
87
86
let open_documents = self
88
87
. document_ids
89
88
. 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
+ } )
91
96
. collect :: < Vec < _ > > ( ) ;
92
97
93
98
responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
94
99
95
- responses. push_back ( DocumentsMessage :: SelectDocument ( self . active_document_index ) . into ( ) ) ;
100
+ responses. push_back ( DocumentsMessage :: SelectDocument ( self . active_document_id ) . into ( ) ) ;
96
101
responses. push_back ( DocumentMessage :: RenderDocument . into ( ) ) ;
97
102
responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
98
103
for layer in self . active_document ( ) . layer_data . keys ( ) {
@@ -104,18 +109,23 @@ impl DocumentsMessageHandler {
104
109
pub fn ordered_document_iterator ( & self ) -> impl Iterator < Item = & DocumentMessageHandler > {
105
110
self . document_ids . iter ( ) . map ( |id| self . documents . get ( id) . expect ( "document id was not found in the document hashmap" ) )
106
111
}
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
+ }
107
116
}
108
117
109
118
impl Default for DocumentsMessageHandler {
110
119
fn default ( ) -> Self {
111
120
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
+
113
124
Self {
114
125
documents : documents_map,
115
- document_ids : vec ! [ 0 ] ,
126
+ document_ids : vec ! [ starting_key ] ,
116
127
copy_buffer : vec ! [ ] ,
117
- active_document_index : 0 ,
118
- document_id_counter : 0 ,
128
+ active_document_id : starting_key,
119
129
}
120
130
}
121
131
}
@@ -129,24 +139,27 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
129
139
responses. push_back ( FrontendMessage :: DisplayAboutGraphiteDialog . into ( ) ) ;
130
140
}
131
141
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 ( ) ) ;
137
145
responses. push_back ( RenderDocument . into ( ) ) ;
138
146
responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
139
147
for layer in self . active_document ( ) . layer_data . keys ( ) {
140
148
responses. push_back ( DocumentMessage :: LayerChanged ( layer. clone ( ) ) . into ( ) ) ;
141
149
}
142
150
}
143
151
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
+ }
150
163
}
151
164
CloseAllDocumentsWithConfirmation => {
152
165
responses. push_back ( FrontendMessage :: DisplayConfirmationToCloseAllDocuments . into ( ) ) ;
@@ -159,38 +172,44 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
159
172
// Create a new blank document
160
173
responses. push_back ( NewDocument . into ( ) ) ;
161
174
}
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) ;
167
177
self . documents . remove ( & id) ;
168
- self . document_ids . remove ( index ) ;
178
+ self . document_ids . remove ( document_index ) ;
169
179
170
180
// Last tab was closed, so create a new blank tab
171
181
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 ( ) ) ;
175
185
}
176
186
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 ( )
179
193
} else {
180
- index
194
+ // Move to the next tab
195
+ self . document_ids [ document_index]
181
196
} ;
182
197
183
198
// 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 < _ > > ( ) ;
186
210
// Update the list of new documents on the front end, active tab, and ensure that document renders
187
211
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 ( ) ) ;
194
213
responses. push_back ( RenderDocument . into ( ) ) ;
195
214
responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
196
215
for layer in self . active_document ( ) . layer_data . keys ( ) {
@@ -222,17 +241,31 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
222
241
}
223
242
UpdateOpenDocumentsList => {
224
243
// 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 < _ > > ( ) ;
226
255
responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
227
256
}
228
257
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 ( ) ) ;
231
262
}
232
263
PrevDocument => {
233
264
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 ( ) ) ;
236
269
}
237
270
Copy => {
238
271
let paths = self . active_document ( ) . selected_layers_sorted ( ) ;
0 commit comments