@@ -372,8 +372,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
372372 responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ ] } ) ;
373373 self . layer_range_selection_reference = None ;
374374 }
375- DocumentMessage :: DocumentHistoryBackward => self . undo_with_history ( viewport, responses) ,
376- DocumentMessage :: DocumentHistoryForward => self . redo_with_history ( viewport, responses) ,
377375 DocumentMessage :: DocumentStructureChanged => {
378376 if layers_panel_open {
379377 self . network_interface . load_structure ( ) ;
@@ -953,15 +951,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
953951 responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ layer. to_node( ) ] } ) ;
954952 responses. add ( ToolMessage :: ActivateTool { tool_type : ToolType :: Select } ) ;
955953 }
956- DocumentMessage :: Redo => {
957- if self . network_interface . transaction_status ( ) != TransactionStatus :: Finished {
958- return ;
959- }
960- responses. add ( SelectToolMessage :: Abort ) ;
961- responses. add ( DocumentMessage :: DocumentHistoryForward ) ;
962- responses. add ( ToolMessage :: Redo ) ;
963- responses. add ( OverlaysMessage :: Draw ) ;
964- }
965954 DocumentMessage :: RenameDocument { new_name } => {
966955 self . name = new_name. clone ( ) ;
967956
@@ -1291,6 +1280,27 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
12911280 self . render_mode = render_mode;
12921281 responses. add_front ( NodeGraphMessage :: RunDocumentGraph ) ;
12931282 }
1283+ DocumentMessage :: Undo => {
1284+ if self . network_interface . transaction_status ( ) != TransactionStatus :: Finished {
1285+ return ;
1286+ }
1287+ responses. add ( ToolMessage :: PreUndo ) ;
1288+ responses. add ( DocumentMessage :: DocumentHistoryBackward ) ;
1289+ responses. add ( OverlaysMessage :: Draw ) ;
1290+ responses. add ( ToolMessage :: Undo ) ;
1291+ }
1292+ DocumentMessage :: Redo => {
1293+ if self . network_interface . transaction_status ( ) != TransactionStatus :: Finished {
1294+ return ;
1295+ }
1296+ responses. add ( SelectToolMessage :: Abort ) ;
1297+ responses. add ( DocumentMessage :: DocumentHistoryForward ) ;
1298+ responses. add ( ToolMessage :: Redo ) ;
1299+ responses. add ( OverlaysMessage :: Draw ) ;
1300+ }
1301+ DocumentMessage :: DocumentHistoryBackward => self . undo_with_history ( viewport, responses) ,
1302+ DocumentMessage :: DocumentHistoryForward => self . redo_with_history ( viewport, responses) ,
1303+ // Create a snapshot of the document at this point in time, by immediately starting and committing a transaction.
12941304 DocumentMessage :: AddTransaction => {
12951305 // Reverse order since they are added to the front
12961306 responses. add_front ( DocumentMessage :: CommitTransaction ) ;
@@ -1307,20 +1317,18 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
13071317 // Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents
13081318 responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
13091319 }
1310- // Commits the transaction if the network was mutated since the transaction started, otherwise it cancels the transaction
1320+ // Either commit (creating a new history step) or cancel (removing the last history step, as if it never happened) the last transaction started with `StartTransaction`.
13111321 DocumentMessage :: EndTransaction => match self . network_interface . transaction_status ( ) {
1312- TransactionStatus :: Started => {
1313- responses. add_front ( DocumentMessage :: CancelTransaction ) ;
1314- }
1315- TransactionStatus :: Modified => {
1316- responses. add_front ( DocumentMessage :: CommitTransaction ) ;
1317- }
1322+ // This is used if, between the start and end of the transaction, the changes were undone by the user.
1323+ // For example, dragging something around and then dropping it back at its exact original position.
1324+ // So we cancel the transaction to return to the point before the transaction was started.
1325+ TransactionStatus :: Started => responses. add_front ( DocumentMessage :: CancelTransaction ) ,
1326+ // This is used if, between the start and end of the transaction, actual changes did occur and we want to keep them as part of a history step that the user can undo/redo.
1327+ TransactionStatus :: Modified => responses. add_front ( DocumentMessage :: CommitTransaction ) ,
1328+ // This is an erroneous state indicating that a transaction is being ended without having ever been started.
13181329 TransactionStatus :: Finished => { }
13191330 } ,
1320- DocumentMessage :: CancelTransaction => {
1321- self . network_interface . finish_transaction ( ) ;
1322- self . document_undo_history . pop_back ( ) ;
1323- }
1331+ // Add a history step so the user can undo/redo to the point when the transaction was started.
13241332 DocumentMessage :: CommitTransaction => {
13251333 if self . network_interface . transaction_status ( ) == TransactionStatus :: Finished {
13261334 return ;
@@ -1329,25 +1337,38 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
13291337 self . document_redo_history . clear ( ) ;
13301338 responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
13311339 }
1340+ // Retroactively undoes the start of the transaction, as if the transaction was never started. This is useful, for example, if the user
1341+ // might have begun performing some action that ends up not changing anything, like dragging something back to its exact original position.
1342+ DocumentMessage :: CancelTransaction => {
1343+ self . network_interface . finish_transaction ( ) ;
1344+ self . document_undo_history . pop_back ( ) ;
1345+ }
1346+ // Cause the document to revert back to the state when the transaction was started. For example, the user may be dragging
1347+ // something around and hits Escape to abort the drag. This jumps the document back to the point before the drag began.
13321348 DocumentMessage :: AbortTransaction => match self . network_interface . transaction_status ( ) {
1333- TransactionStatus :: Started => {
1334- responses. add_front ( DocumentMessage :: CancelTransaction ) ;
1335- }
1336- TransactionStatus :: Modified => {
1337- responses. add ( DocumentMessage :: RepeatedAbortTransaction { undo_count : 1 } ) ;
1338- }
1349+ // If we abort a transaction without any changes having been made, we simply remove the transaction as if it never occurred.
1350+ TransactionStatus :: Started => responses. add_front ( DocumentMessage :: CancelTransaction ) ,
1351+ // If we abort a transaction after changes have been made, we need to undo those changes.
1352+ TransactionStatus :: Modified => responses. add ( DocumentMessage :: RepeatedAbortTransaction { undo_count : 1 } ) ,
1353+ // This is an erroneous state indicating that a transaction is being aborted without having ever been started.
13391354 TransactionStatus :: Finished => { }
13401355 } ,
1356+ // The same as `AbortTransaction` with one step back, but it can also be called with multiple steps back in the history of undos.
13411357 DocumentMessage :: RepeatedAbortTransaction { undo_count } => {
1358+ // This prevents us from aborting a transaction multiple times in a row, which would be erroneous.
13421359 if self . network_interface . transaction_status ( ) == TransactionStatus :: Finished {
13431360 return ;
13441361 }
13451362
1363+ // Sometimes (like successive G/R/S transformations) we may need to undo multiple steps to fully abort the transaction, before we finish.
13461364 for _ in 0 ..undo_count {
13471365 self . undo ( viewport, responses) ;
13481366 }
13491367
1368+ // Finally finish the transaction, ensuring that any future operations are not erroneously redone as part of this aborted transaction.
13501369 self . network_interface . finish_transaction ( ) ;
1370+
1371+ // Refresh state
13511372 responses. add ( OverlaysMessage :: Draw ) ;
13521373 responses. add ( PortfolioMessage :: UpdateOpenDocumentsList ) ;
13531374 }
@@ -1419,15 +1440,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
14191440 DocumentMessage :: UpdateClipTargets { clip_targets } => {
14201441 self . network_interface . update_clip_targets ( clip_targets) ;
14211442 }
1422- DocumentMessage :: Undo => {
1423- if self . network_interface . transaction_status ( ) != TransactionStatus :: Finished {
1424- return ;
1425- }
1426- responses. add ( ToolMessage :: PreUndo ) ;
1427- responses. add ( DocumentMessage :: DocumentHistoryBackward ) ;
1428- responses. add ( OverlaysMessage :: Draw ) ;
1429- responses. add ( ToolMessage :: Undo ) ;
1430- }
14311443 DocumentMessage :: UngroupSelectedLayers => {
14321444 if !self . selection_network_path . is_empty ( ) {
14331445 log:: error!( "Ungrouping selected layers is only supported for the Document Network" ) ;
0 commit comments