changeset 1908:1d60e0ac3b97

undo transactions
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 15 Apr 2025 21:51:41 -0600
parents cbd2f1b8ff2c
children 474f7ab2d1c2
files src/luan/modules/swing/Document.luan src/luan/modules/swing/TextAreaLuan.java src/luan/modules/swing/Text_area.luan src/luan/modules/swing/Text_component.luan src/luan/modules/swing/UndoManagerLuan.java
diffstat 5 files changed, 81 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/modules/swing/Document.luan	Tue Apr 15 20:08:46 2025 -0600
+++ b/src/luan/modules/swing/Document.luan	Tue Apr 15 21:51:41 2025 -0600
@@ -21,6 +21,14 @@
 	document.is_unedited = undo.isUnedited
 	document.set_unedited = undo.setUnedited
 	document.clear_unedited = undo.clearUnedited
+	function document.run_in_transaction(fn)
+		undo.beginTransaction()
+		try
+			return fn()
+		finally
+			undo.endTransaction()
+		end
+	end
 	return document
 end
 
--- a/src/luan/modules/swing/TextAreaLuan.java	Tue Apr 15 20:08:46 2025 -0600
+++ b/src/luan/modules/swing/TextAreaLuan.java	Tue Apr 15 21:51:41 2025 -0600
@@ -11,6 +11,7 @@
 import javax.swing.UIManager;
 import javax.swing.Timer;
 import javax.swing.text.DefaultCaret;
+import javax.swing.text.AbstractDocument;
 import javax.swing.text.BadLocationException;
 import goodjava.logging.Logger;
 import goodjava.logging.LoggerFactory;
@@ -95,4 +96,38 @@
 				g.drawString( symbol, r.x, r.y + ascent );
 		}
 	}
+
+	private UndoManagerLuan getUndoManagerLuan() {
+		return (UndoManagerLuan)getDocument().getProperty("undo");
+	}
+
+	@Override public void paste() {
+		UndoManagerLuan undo = getUndoManagerLuan();
+		undo.beginTransaction();
+		try {
+			super.paste();
+		} finally {
+			undo.endTransaction();
+		}
+	}
+
+	@Override public void setText(String t) {
+		UndoManagerLuan undo = getUndoManagerLuan();
+		undo.beginTransaction();
+		try {
+			super.setText(t);
+		} finally {
+			undo.endTransaction();
+		}
+	}
+
+	public void replace(int offset, int length, String text) throws BadLocationException {
+		UndoManagerLuan undo = getUndoManagerLuan();
+		undo.beginTransaction();
+		try {
+			((AbstractDocument)getDocument()).replace(offset,length,text,null);
+		} finally {
+			undo.endTransaction();
+		}
+	}
 }
--- a/src/luan/modules/swing/Text_area.luan	Tue Apr 15 20:08:46 2025 -0600
+++ b/src/luan/modules/swing/Text_area.luan	Tue Apr 15 21:51:41 2025 -0600
@@ -99,7 +99,7 @@
 		return jtext_area.insert(text,pos-1)
 	end
 	function text_area.replace(start_pos,length,text)
-		return jtext_area.getDocument().replace(start_pos-1,length,text)
+		return jtext_area.replace(start_pos-1,length,text)
 	end
 	set_metatable(text_area,mt)
 	return text_area
--- a/src/luan/modules/swing/Text_component.luan	Tue Apr 15 20:08:46 2025 -0600
+++ b/src/luan/modules/swing/Text_component.luan	Tue Apr 15 21:51:41 2025 -0600
@@ -52,12 +52,14 @@
 		local document = jcomponent.getDocument()
 		local start = jcomponent.getSelectionStart()
 		local end_ = jcomponent.getSelectionEnd()
-		if end_ > start then
-			document.remove( start, end_ - start )
-		end
-		if #value > 0 then
-			document.insertString( start, value, nil )
-		end
+		component._document.run_in_transaction(function()
+			if end_ > start then
+				document.remove( start, end_ - start )
+			end
+			if #value > 0 then
+				document.insertString( start, value, nil )
+			end
+		end)
 		jcomponent.select( start, start + #value )
 		return
 	end
--- a/src/luan/modules/swing/UndoManagerLuan.java	Tue Apr 15 20:08:46 2025 -0600
+++ b/src/luan/modules/swing/UndoManagerLuan.java	Tue Apr 15 21:51:41 2025 -0600
@@ -1,10 +1,13 @@
 package luan.modules.swing;
 
 import java.util.WeakHashMap;
+import java.util.List;
+import java.util.ArrayList;
 import javax.swing.event.UndoableEditListener;
 import javax.swing.event.UndoableEditEvent;
 import javax.swing.undo.UndoManager;
 import javax.swing.undo.UndoableEdit;
+import javax.swing.undo.CompoundEdit;
 import javax.swing.undo.CannotUndoException;
 import javax.swing.undo.CannotRedoException;
 import goodjava.util.GoodUtils;
@@ -22,6 +25,7 @@
 	private final WeakHashMap<LuanFunction,Boolean> map = new WeakHashMap<LuanFunction,Boolean>();
 	private final Luan luan;
 	private UndoableEdit unedited = null;
+	private final List<CompoundEdit> transactions = new ArrayList<CompoundEdit>();
 
 	public UndoManagerLuan(Luan luan) {
 		this.luan = luan;
@@ -38,8 +42,13 @@
 	}
 
 	@Override public void undoableEditHappened(UndoableEditEvent event) {
-		super.undoableEditHappened(event);
-		notifyListeners();
+		int n = transactions.size();
+		if( n == 0 ) {
+			super.undoableEditHappened(event);
+			notifyListeners();
+		} else {
+			if( !transactions.get(n-1).addEdit( event.getEdit() ) )  throw new RuntimeException();
+		}
 	}
 
 	@Override public void undo() throws CannotUndoException {
@@ -70,4 +79,22 @@
 		unedited = null;
 		notifyListeners();
 	}
+
+	public void beginTransaction() {
+		//logger.info("beginTransaction");
+		transactions.add(new CompoundEdit());
+	}
+
+	public void endTransaction() {
+		//logger.info("endTransaction");
+		int n = transactions.size();
+		CompoundEdit ce = transactions.remove(n-1);
+		ce.end();
+		if( n == 1 ) {
+			if( !addEdit(ce) )  throw new RuntimeException();
+		} else {
+			if( !transactions.get(n-2).addEdit(ce) )  throw new RuntimeException();
+		}
+		notifyListeners();
+	}
 }