@@ -3,9 +3,8 @@ use crate::message_prelude::*;
33use graphene:: layers:: Layer ;
44use graphene:: { LayerId , Operation as DocumentOperation } ;
55use log:: warn;
6-
76use serde:: { Deserialize , Serialize } ;
8- use std:: collections:: VecDeque ;
7+ use std:: collections:: { HashMap , VecDeque } ;
98
109use super :: DocumentMessageHandler ;
1110use crate :: consts:: DEFAULT_DOCUMENT_NAME ;
@@ -36,28 +35,37 @@ pub enum DocumentsMessage {
3635
3736#[ derive( Debug , Clone ) ]
3837pub struct DocumentsMessageHandler {
39- documents : Vec < DocumentMessageHandler > ,
38+ documents : HashMap < u64 , DocumentMessageHandler > ,
39+ document_ids : Vec < u64 > ,
40+ document_id_counter : u64 ,
4041 active_document_index : usize ,
4142 copy_buffer : Vec < Layer > ,
4243}
4344
4445impl DocumentsMessageHandler {
4546 pub fn active_document ( & self ) -> & DocumentMessageHandler {
46- & self . documents [ self . active_document_index ]
47+ let id = self . document_ids [ self . active_document_index ] ;
48+ self . documents . get ( & id) . unwrap ( )
4749 }
50+
4851 pub fn active_document_mut ( & mut self ) -> & mut DocumentMessageHandler {
49- & mut self . documents [ self . active_document_index ]
52+ let id = self . document_ids [ self . active_document_index ] ;
53+ self . documents . get_mut ( & id) . unwrap ( )
5054 }
55+
5156 fn generate_new_document_name ( & self ) -> String {
5257 let mut doc_title_numbers = self
53- . documents
58+ . document_ids
5459 . iter ( )
55- . filter_map ( |d| {
56- d. name
60+ . filter_map ( |id| self . documents . get ( & id) )
61+ . map ( |doc| {
62+ doc. name
5763 . rsplit_once ( DEFAULT_DOCUMENT_NAME )
5864 . map ( |( prefix, number) | ( prefix. is_empty ( ) ) . then ( || number. trim ( ) . parse :: < isize > ( ) . ok ( ) ) . flatten ( ) . unwrap_or ( 1 ) )
65+ . unwrap ( )
5966 } )
6067 . collect :: < Vec < isize > > ( ) ;
68+
6169 doc_title_numbers. sort_unstable ( ) ;
6270 doc_title_numbers. iter_mut ( ) . enumerate ( ) . for_each ( |( i, number) | * number = * number - i as isize - 2 ) ;
6371 // Uses binary search to find the index of the element where number is bigger than i
@@ -71,11 +79,14 @@ impl DocumentsMessageHandler {
7179 }
7280
7381 fn load_document ( & mut self , new_document : DocumentMessageHandler , responses : & mut VecDeque < Message > ) {
74- self . active_document_index = self . documents . len ( ) ;
75- self . documents . push ( new_document) ;
82+ self . document_id_counter += 1 ;
83+ self . active_document_index = self . document_ids . len ( ) ;
84+ self . document_ids . push ( self . document_id_counter ) ;
85+ self . documents . insert ( self . document_id_counter , new_document) ;
7686
7787 // Send the new list of document tab names
78- let open_documents = self . documents . iter ( ) . map ( |doc| doc. name . clone ( ) ) . collect ( ) ;
88+ let open_documents = self . document_ids . iter ( ) . filter_map ( |id| self . documents . get ( & id) . map ( |doc| doc. name . clone ( ) ) ) . collect :: < Vec < String > > ( ) ;
89+
7990 responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
8091
8192 responses. push_back ( DocumentsMessage :: SelectDocument ( self . active_document_index ) . into ( ) ) ;
@@ -89,10 +100,14 @@ impl DocumentsMessageHandler {
89100
90101impl Default for DocumentsMessageHandler {
91102 fn default ( ) -> Self {
103+ let mut documents_map: HashMap < u64 , DocumentMessageHandler > = HashMap :: with_capacity ( 1 ) ;
104+ documents_map. insert ( 0 , DocumentMessageHandler :: default ( ) ) ;
92105 Self {
93- documents : vec ! [ DocumentMessageHandler :: default ( ) ] ,
94- active_document_index : 0 ,
106+ documents : documents_map ,
107+ document_ids : vec ! [ 0 ] ,
95108 copy_buffer : vec ! [ ] ,
109+ active_document_index : 0 ,
110+ document_id_counter : 0 ,
96111 }
97112 }
98113}
@@ -103,15 +118,11 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
103118 use DocumentsMessage :: * ;
104119 match message {
105120 Document ( message) => self . active_document_mut ( ) . process_action ( message, ipp, responses) ,
106- SelectDocument ( id) => {
107- assert ! ( id < self . documents. len( ) , "Tried to select a document that was not initialized" ) ;
108- self . active_document_index = id;
109- responses. push_back (
110- FrontendMessage :: SetActiveDocument {
111- document_index : self . active_document_index ,
112- }
113- . into ( ) ,
114- ) ;
121+ SelectDocument ( index) => {
122+ // NOTE: Potentially this will break if we ever exceed 56 bit values due to how the message parsing system works.
123+ assert ! ( index < self . documents. len( ) , "Tried to select a document that was not initialized" ) ;
124+ self . active_document_index = index;
125+ responses. push_back ( FrontendMessage :: SetActiveDocument { document_index : index } . into ( ) ) ;
115126 responses. push_back ( RenderDocument . into ( ) ) ;
116127 responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
117128 for layer in self . active_document ( ) . layer_data . keys ( ) {
@@ -132,54 +143,47 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
132143 CloseAllDocuments => {
133144 // Empty the list of internal document data
134145 self . documents . clear ( ) ;
146+ self . document_ids . clear ( ) ;
135147
136148 // Create a new blank document
137149 responses. push_back ( NewDocument . into ( ) ) ;
138150 }
139- CloseDocument ( id) => {
140- assert ! ( id < self . documents. len( ) , "Tried to select a document that was not initialized" ) ;
141- // Remove doc from the backend store; use `id` as client tabs and backend documents will be in sync
142- self . documents . remove ( id) ;
143-
144- // Send the new list of document tab names
145- let open_documents = self . documents . iter ( ) . map ( |doc| doc. name . clone ( ) ) . collect ( ) ;
146- responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
151+ CloseDocument ( index) => {
152+ assert ! ( index < self . documents. len( ) , "Tried to close a document that was not initialized" ) ;
153+ // Get the ID based on the current collection of the documents.
154+ let id = self . document_ids [ index] ;
155+ // Map the ID to an index and remove the document
156+ self . documents . remove ( & id) ;
157+ self . document_ids . remove ( index) ;
147158
148159 // Last tab was closed, so create a new blank tab
149- if self . documents . is_empty ( ) {
150- self . active_document_index = 0 ;
151- responses. push_back ( NewDocument . into ( ) ) ;
160+ if self . document_ids . is_empty ( ) {
161+ self . document_id_counter += 1 ;
162+ self . document_ids . push ( self . document_id_counter ) ;
163+ self . documents . insert ( self . document_id_counter , DocumentMessageHandler :: default ( ) ) ;
152164 }
153- // The currently selected doc is being closed
154- else if id == self . active_document_index {
155- // The currently selected tab was the rightmost tab
156- if id == self . documents . len ( ) {
157- self . active_document_index -= 1 ;
158- }
159165
160- responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
161- responses. push_back (
162- FrontendMessage :: SetActiveDocument {
163- document_index : self . active_document_index ,
164- }
165- . into ( ) ,
166- ) ;
167- responses. push_back (
168- FrontendMessage :: UpdateCanvas {
169- document : self . active_document_mut ( ) . graphene_document . render_root ( ) ,
170- }
171- . into ( ) ,
172- ) ;
173- }
174- // Active doc will move one space to the left
175- else if id < self . active_document_index {
176- self . active_document_index -= 1 ;
177- responses. push_back (
178- FrontendMessage :: SetActiveDocument {
179- document_index : self . active_document_index ,
180- }
181- . into ( ) ,
182- ) ;
166+ self . active_document_index = if self . active_document_index >= self . document_ids . len ( ) {
167+ self . document_ids . len ( ) - 1
168+ } else {
169+ index
170+ } ;
171+
172+ // Send the new list of document tab names
173+ let open_documents = self . document_ids . iter ( ) . filter_map ( |id| self . documents . get ( & id) . map ( |doc| doc. name . clone ( ) ) ) . collect ( ) ;
174+
175+ // Update the list of new documents on the front end, active tab, and ensure that document renders
176+ responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
177+ responses. push_back (
178+ FrontendMessage :: SetActiveDocument {
179+ document_index : self . active_document_index ,
180+ }
181+ . into ( ) ,
182+ ) ;
183+ responses. push_back ( RenderDocument . into ( ) ) ;
184+ responses. push_back ( DocumentMessage :: DocumentStructureChanged . into ( ) ) ;
185+ for layer in self . active_document ( ) . layer_data . keys ( ) {
186+ responses. push_back ( DocumentMessage :: LayerChanged ( layer. clone ( ) ) . into ( ) ) ;
183187 }
184188 }
185189 NewDocument => {
@@ -207,16 +211,17 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
207211 }
208212 GetOpenDocumentsList => {
209213 // Send the list of document tab names
210- let open_documents = self . documents . iter ( ) . map ( |doc| doc. name . clone ( ) ) . collect ( ) ;
214+ let open_documents = self . documents . values ( ) . map ( |doc| doc. name . clone ( ) ) . collect ( ) ;
211215 responses. push_back ( FrontendMessage :: UpdateOpenDocumentsList { open_documents } . into ( ) ) ;
212216 }
213217 NextDocument => {
214- let id = ( self . active_document_index + 1 ) % self . documents . len ( ) ;
215- responses. push_back ( SelectDocument ( id ) . into ( ) ) ;
218+ let next = ( self . active_document_index + 1 ) % self . document_ids . len ( ) ;
219+ responses. push_back ( SelectDocument ( next ) . into ( ) ) ;
216220 }
217221 PrevDocument => {
218- let id = ( self . active_document_index + self . documents . len ( ) - 1 ) % self . documents . len ( ) ;
219- responses. push_back ( SelectDocument ( id) . into ( ) ) ;
222+ let len = self . document_ids . len ( ) ;
223+ let prev = ( self . active_document_index + len - 1 ) % len;
224+ responses. push_back ( SelectDocument ( prev) . into ( ) ) ;
220225 }
221226 Copy => {
222227 let paths = self . active_document ( ) . selected_layers_sorted ( ) ;
0 commit comments