changeset 1872:29a1e9bde185

swing
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 03 Apr 2025 14:33:37 -0600
parents 299331f3fcba
children cf38353d77bd
files src/luan/modules/swing/Component.luan src/luan/modules/swing/List.luan src/luan/modules/swing/Menu.luan src/luan/modules/swing/TextAreaLineNumbers.java src/luan/modules/swing/Utils.luan src/luan/modules/swing/WeakDocumentListener.java
diffstat 6 files changed, 122 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/modules/swing/Component.luan	Thu Apr 03 08:46:30 2025 -0600
+++ b/src/luan/modules/swing/Component.luan	Thu Apr 03 14:33:37 2025 -0600
@@ -17,6 +17,10 @@
 		end
 		jcomponent.setFont(font)
 	end
+	component._dont_gc = {}
+	function component.dont_gc(obj)
+		component._dont_gc[obj] = true
+	end
 	return component
 end
 
--- a/src/luan/modules/swing/List.luan	Thu Apr 03 08:46:30 2025 -0600
+++ b/src/luan/modules/swing/List.luan	Thu Apr 03 14:33:37 2025 -0600
@@ -1,37 +1,55 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local set_metatable = Luan.set_metatable or error()
+local Utils = require "luan:swing/Utils.luan"
+local fail = Utils.fail or error()
+local make_metatable = Utils.make_metatable or error()
+local Component = require "luan:swing/Component.luan"
+local super = Component.new or error()
 require "java"
 local JList = require "java:javax.swing.JList"
 local DefaultListModel = require "java:javax.swing.DefaultListModel"
+local TextAreaLineNumbers = require "java:luan.modules.swing.TextAreaLineNumbers"
 
 
 local List = {}
 
-local mt = {}
-
-function mt.__index(list,key)
+function List.__index(list,key)
 	if key == "size" then
 		return list.model.getSize()
 	end
-	error("'"..key.."' not defined")
+	return fail
 end
 
-function mt.__new_index(list,key,value)
-	if key == "size" then
-		list.model.setSize(value)
-		return
+function List.__new_index(list,key,value)
+	local model = list.model
+	if model.instanceof(DefaultListModel) then
+		if key == "size" then
+			list.model.setSize(value)
+			return
+		end
 	end
-	error("'"..key.."' not defined")
+	return fail
 end
 
-function List.new()
-	local model = DefaultListModel.new()
+local mt = make_metatable(List)
+
+local function new(model)
 	local jlist = JList.new(model)
-	local list = { java=jlist, model=model }
-	list.add_element = model.addElement
+	local list = { java = jlist, model = model }
+	if model.instanceof(DefaultListModel) then
+		list.add_element = model.addElement
+	end
 	set_metatable(list,mt)
 	return list
 end
 
+function List.new_default_list()
+	return new(DefaultListModel.new())
+end
+
+function List.new_text_area_line_numbers(text_area)
+	return new(TextAreaLineNumbers.new(text_area.java))
+end
+
 return List
--- a/src/luan/modules/swing/Menu.luan	Thu Apr 03 08:46:30 2025 -0600
+++ b/src/luan/modules/swing/Menu.luan	Thu Apr 03 14:33:37 2025 -0600
@@ -20,11 +20,11 @@
 function Menu.new()
 	local jmenu = JMenu.new()
 	local menu = { java = jmenu }
-	super(menu)
 	menu.add_separator = jmenu.addSeparator
 	function menu.add(menu_item)
 		jmenu.add(menu_item.java)
 	end
+	super(menu)
 	set_metatable(menu,mt)
 	return menu
 end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/modules/swing/TextAreaLineNumbers.java	Thu Apr 03 14:33:37 2025 -0600
@@ -0,0 +1,46 @@
+package luan.modules.swing;
+
+import javax.swing.AbstractListModel;
+import javax.swing.JTextArea;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.DocumentEvent;
+
+
+public final class TextAreaLineNumbers extends AbstractListModel<Integer> implements DocumentListener {
+	private final JTextArea textArea;
+	private int lines;
+
+	public TextAreaLineNumbers(JTextArea textArea) {
+		this.textArea = textArea;
+		this.lines = textArea.getLineCount();
+		textArea.getDocument().addDocumentListener(new WeakDocumentListener(this));
+	}
+
+	@Override public Integer getElementAt(int index) {
+		return index + 1;
+	}
+
+	@Override public int getSize() {
+		return lines;
+	}
+
+	@Override public void changedUpdate(DocumentEvent e) {
+		int n = textArea.getLineCount();
+		if( lines < n ) {
+			fireIntervalAdded(e.getDocument(),lines,n-1);
+			lines = n;
+		} else if( lines > n ) {
+			fireIntervalRemoved(e.getDocument(),n,lines-1);
+			lines = n;
+		}
+	}
+
+	@Override public void removeUpdate(DocumentEvent e) {
+		changedUpdate(e);
+	}
+
+	@Override public void insertUpdate(DocumentEvent e) {
+		changedUpdate(e);
+	}
+
+}
--- a/src/luan/modules/swing/Utils.luan	Thu Apr 03 08:46:30 2025 -0600
+++ b/src/luan/modules/swing/Utils.luan	Thu Apr 03 14:33:37 2025 -0600
@@ -22,10 +22,7 @@
 
 	function mt.__new_index(t,key,value)
 		local rtn = __new_index(t,key,value)
-		-- rtn ~= fail or error("'"..key.."' not defined")
-		if rtn == fail then
-			raw_set(t,key,value)
-		end
+		rtn ~= fail or error("'"..key.."' not defined")
 	end
 
 	return mt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/modules/swing/WeakDocumentListener.java	Thu Apr 03 14:33:37 2025 -0600
@@ -0,0 +1,39 @@
+package luan.modules.swing;
+
+import java.lang.ref.WeakReference;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.DocumentEvent;
+
+
+public final class WeakDocumentListener implements DocumentListener {
+	private final WeakReference<DocumentListener> ref;
+
+	public WeakDocumentListener(DocumentListener dl) {
+		ref = new WeakReference<DocumentListener>(dl);
+	}
+
+	private DocumentListener get(DocumentEvent e) {
+		DocumentListener dl = ref.get();
+		if( dl==null )
+			e.getDocument().removeDocumentListener(this);
+		return dl;
+	}
+
+	@Override public void changedUpdate(DocumentEvent e) {
+		DocumentListener dl = get(e);
+		if( dl != null )
+			dl.changedUpdate(e);
+	}
+
+	@Override public void removeUpdate(DocumentEvent e) {
+		DocumentListener dl = get(e);
+		if( dl != null )
+			dl.removeUpdate(e);
+	}
+
+	@Override public void insertUpdate(DocumentEvent e) {
+		DocumentListener dl = get(e);
+		if( dl != null )
+			dl.insertUpdate(e);
+	}
+}