@@ -6,7 +6,7 @@ use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BO
66use super :: utility_types:: network_interface:: { self , NodeNetworkInterface , TransactionStatus } ;
77use super :: utility_types:: nodes:: { CollapsedLayers , SelectedNodes } ;
88use crate :: application:: { GRAPHITE_GIT_COMMIT_HASH , generate_uuid} ;
9- use crate :: consts:: { ASYMPTOTIC_EFFECT , COLOR_OVERLAY_GRAY , DEFAULT_DOCUMENT_NAME , FILE_SAVE_SUFFIX , SCALE_EFFECT , SCROLLBAR_SPACING , VIEWPORT_ROTATE_SNAP_INTERVAL } ;
9+ use crate :: consts:: { ASYMPTOTIC_EFFECT , COLOR_OVERLAY_GRAY , DEFAULT_DOCUMENT_NAME , FILE_EXTENSION , SCALE_EFFECT , SCROLLBAR_SPACING , VIEWPORT_ROTATE_SNAP_INTERVAL } ;
1010use crate :: messages:: input_mapper:: utility_types:: macros:: action_keys;
1111use crate :: messages:: layout:: utility_types:: widget_prelude:: * ;
1212use crate :: messages:: portfolio:: document:: data_panel:: { DataPanelMessageContext , DataPanelMessageHandler } ;
@@ -85,8 +85,6 @@ pub struct DocumentMessageHandler {
8585 /// List of the [`LayerNodeIdentifier`]s that are currently collapsed by the user in the Layers panel.
8686 /// Collapsed means that the expansion arrow isn't set to show the children of these layers.
8787 pub collapsed : CollapsedLayers ,
88- /// The name of the document, which is displayed in the tab and title bar of the editor.
89- pub name : String ,
9088 /// The full Git commit hash of the Graphite repository that was used to build the editor.
9189 /// We save this to provide a hint about which version of the editor was used to create the document.
9290 pub commit_hash : String ,
@@ -113,6 +111,12 @@ pub struct DocumentMessageHandler {
113111 // Fields omitted from the saved document format
114112 // =============================================
115113 //
114+ /// The name of the document, which is displayed in the tab and title bar of the editor.
115+ #[ serde( skip) ]
116+ pub name : String ,
117+ /// The path of the to the document file.
118+ #[ serde( skip) ]
119+ pub ( crate ) path : Option < PathBuf > ,
116120 /// Path to network currently viewed in the node graph overlay. This will eventually be stored in each panel, so that multiple panels can refer to different networks
117121 #[ serde( skip) ]
118122 breadcrumb_network_path : Vec < NodeId > ,
@@ -125,9 +129,6 @@ pub struct DocumentMessageHandler {
125129 /// Stack of document network snapshots for future history states.
126130 #[ serde( skip) ]
127131 document_redo_history : VecDeque < NodeNetworkInterface > ,
128- /// The path of the to the document file.
129- #[ serde( skip) ]
130- path : Option < PathBuf > ,
131132 /// Hash of the document snapshot that was most recently saved to disk by the user.
132133 #[ serde( skip) ]
133134 saved_hash : Option < u64 > ,
@@ -159,7 +160,6 @@ impl Default for DocumentMessageHandler {
159160 // ============================================
160161 network_interface : default_document_network_interface ( ) ,
161162 collapsed : CollapsedLayers :: default ( ) ,
162- name : DEFAULT_DOCUMENT_NAME . to_string ( ) ,
163163 commit_hash : GRAPHITE_GIT_COMMIT_HASH . to_string ( ) ,
164164 document_ptz : PTZ :: default ( ) ,
165165 document_mode : DocumentMode :: DesignMode ,
@@ -172,11 +172,12 @@ impl Default for DocumentMessageHandler {
172172 // =============================================
173173 // Fields omitted from the saved document format
174174 // =============================================
175+ name : DEFAULT_DOCUMENT_NAME . to_string ( ) ,
176+ path : None ,
175177 breadcrumb_network_path : Vec :: new ( ) ,
176178 selection_network_path : Vec :: new ( ) ,
177179 document_undo_history : VecDeque :: new ( ) ,
178180 document_redo_history : VecDeque :: new ( ) ,
179- path : None ,
180181 saved_hash : None ,
181182 auto_saved_hash : None ,
182183 layer_range_selection_reference : None ,
@@ -947,7 +948,11 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
947948 responses. add ( OverlaysMessage :: Draw ) ;
948949 }
949950 DocumentMessage :: RenameDocument { new_name } => {
950- self . name = new_name;
951+ self . name = new_name. clone ( ) ;
952+
953+ self . path = None ;
954+ self . set_save_state ( false ) ;
955+
951956 responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
952957 responses. add ( NodeGraphMessage :: UpdateNewNodeGraph ) ;
953958 }
@@ -1020,25 +1025,40 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
10201025 multiplier : scrollbar_multiplier. into ( ) ,
10211026 } ) ;
10221027 }
1023- DocumentMessage :: SaveDocument => {
1028+ DocumentMessage :: SaveDocument | DocumentMessage :: SaveDocumentAs => {
1029+ if let DocumentMessage :: SaveDocumentAs = message {
1030+ self . path = None ;
1031+ }
1032+
10241033 self . set_save_state ( true ) ;
10251034 responses. add ( PortfolioMessage :: AutoSaveActiveDocument ) ;
10261035 // Update the save status of the just saved document
10271036 responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
10281037
1029- let name = match self . name . ends_with ( FILE_SAVE_SUFFIX ) {
1030- true => self . name . clone ( ) ,
1031- false => self . name . clone ( ) + FILE_SAVE_SUFFIX ,
1032- } ;
10331038 responses. add ( FrontendMessage :: TriggerSaveDocument {
10341039 document_id,
1035- name,
1040+ name : format ! ( "{}.{}" , self . name . clone ( ) , FILE_EXTENSION ) ,
10361041 path : self . path . clone ( ) ,
10371042 content : self . serialize_document ( ) . into_bytes ( ) ,
10381043 } )
10391044 }
10401045 DocumentMessage :: SavedDocument { path } => {
10411046 self . path = path;
1047+
1048+ // Update the name to match the file stem
1049+ let document_name_from_path = self . path . as_ref ( ) . and_then ( |path| {
1050+ if path. extension ( ) . is_some_and ( |e| e == FILE_EXTENSION ) {
1051+ path. file_stem ( ) . map ( |n| n. to_string_lossy ( ) . to_string ( ) )
1052+ } else {
1053+ None
1054+ }
1055+ } ) ;
1056+ if let Some ( name) = document_name_from_path {
1057+ self . name = name;
1058+
1059+ responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
1060+ responses. add ( NodeGraphMessage :: UpdateNewNodeGraph ) ;
1061+ }
10421062 }
10431063 DocumentMessage :: SelectParentLayer => {
10441064 let selected_nodes = self . network_interface . selected_nodes ( ) ;
@@ -1571,6 +1591,10 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
15711591 ZoomCanvasToFitAll ,
15721592 ) ;
15731593
1594+ // Additional actions available on desktop
1595+ #[ cfg( not( target_family = "wasm" ) ) ]
1596+ common. extend ( actions ! ( DocumentMessageDiscriminant :: SaveDocumentAs ) ) ;
1597+
15741598 // Additional actions if there are any selected layers
15751599 if self . network_interface . selected_nodes ( ) . selected_layers ( self . metadata ( ) ) . next ( ) . is_some ( ) {
15761600 let mut select = actions ! ( DocumentMessageDiscriminant ;
0 commit comments