Some test text!

Discord Logo

Chat with us

PDFTron is now Apryse, learn more here.

Undo / redo edits to a PDF file using Java

More languages

More languages
Java (Android)
C# (.NET Core)
JS (Node.js)
C# (UWP)
C# (Xamarin)

The PDFTron SDK has a low-level facility for undo and redo operations. It is a API that applies to any edits made to a particular document (not just annotations). This sample Java code shows how to use PDFTron SDK to walk back and forth on a fully general, bit-exact list of document states. Saving changes in a mode that is not 'incremental' will wipe out the undo-redo state list; the API will not be able to access old snapshots anymore. See the undoing and redoing guide for more information. Learn more about our Java PDF Library.

Get Started Samples Download

To run this sample, get started with a free trial of Apryse SDK.

// Copyright (c) 2001-2023 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.

import com.pdftron.pdf.*;
import com.pdftron.sdf.Obj;
import com.pdftron.common.Matrix2D;
import com.pdftron.common.PDFNetException;
import com.pdftron.sdf.UndoManager;
import com.pdftron.sdf.ResultSnapshot;
import com.pdftron.sdf.DocSnapshot;
import com.pdftron.sdf.SDFDoc;


// The following sample illustrates how to use the UndoRedo API.
public class UndoRedoTest 
	public static void main(String[] args) 
			// The first step in every application using PDFNet is to initialize the
			// library and set the path to common PDF resources. The library is usually
			// initialized only once, but calling Initialize() multiple times is also fine.

			// Relative path to the folder containing test files.
			String input_path = "../../TestFiles/";
			String output_path = "../../TestFiles/Output/";

			// Open the PDF document.
			PDFDoc doc = new PDFDoc(input_path + "newsletter.pdf");

			UndoManager undo_manager = doc.getUndoManager();

			// Take a snapshot to which we can undo after making changes.
			ResultSnapshot snap0 = undo_manager.takeSnapshot();

			DocSnapshot snap0_state = snap0.currentState();
			Page page = doc.pageCreate();	// Start a new page

			ElementBuilder bld = new ElementBuilder();		// Used to build new Element objects
			ElementWriter writer = new ElementWriter();		// Used to write Elements to the page	
			writer.begin(page);		// Begin writing to this page

			// ----------------------------------------------------------
			// Add JPEG image to the file
			Image img = Image.create(doc, input_path + "peppers.jpg");
			Element element = bld.createImage(img, new Matrix2D(200, 0, 0, 250, 50, 500));

			writer.end();	// Finish writing to the page

			// Take a snapshot after making changes, so that we can redo later (after undoing first).
			ResultSnapshot snap1 = undo_manager.takeSnapshot();

			if (snap1.previousState().equals(snap0_state))
				System.out.println("snap1 previous state equals snap0_state; previous state is correct");
			DocSnapshot snap1_state = snap1.currentState(); + "addimage.pdf", SDFDoc.SaveMode.INCREMENTAL, null);

			if (undo_manager.canUndo())
				ResultSnapshot undo_snap;
				undo_snap = undo_manager.undo(); + "addimage_undone.pdf", SDFDoc.SaveMode.INCREMENTAL, null);

				DocSnapshot undo_snap_state = undo_snap.currentState();

				if (undo_snap_state.equals(snap0_state))
					System.out.println("undo_snap_state equals snap0_state; undo was successful");
				if (undo_manager.canRedo())
					ResultSnapshot redo_snap = undo_manager.redo(); + "addimage_redone.pdf", SDFDoc.SaveMode.INCREMENTAL, null);

					if (redo_snap.previousState().equals(undo_snap_state))
						System.out.println("redo_snap previous state equals undo_snap_state; previous state is correct");
					DocSnapshot redo_snap_state = redo_snap.currentState();
					if (redo_snap_state.equals(snap1_state))
						System.out.println("Snap1 and redo_snap are equal; redo was successful");
					System.out.println("Problem encountered - cannot redo.");
				System.out.println("Problem encountered - cannot undo.");

			// Calling Terminate when PDFNet is no longer in use is a good practice, but
			// is not required.
		catch (Exception e)