Mercurial Hosting > luan
changeset 1874:54e65b36947b default tip
swing
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 05 Apr 2025 08:20:43 -0600 |
parents | cf38353d77bd |
children | |
files | src/luan/modules/swing/Border.luan src/luan/modules/swing/Component.luan src/luan/modules/swing/List.luan src/luan/modules/swing/Scroll_pane.luan src/luan/modules/swing/SwingLuan.java src/luan/modules/swing/TextAreaLineNumbers.java src/luan/modules/swing/TextAreaLineNumbers.luan src/luan/modules/swing/TextAreaLineNumbersLuan.java src/luan/modules/swing/TextAreaLuan.java src/luan/modules/swing/Text_area.luan src/luan/modules/swing/UndoManagerLuan.java src/luan/modules/swing/WeakDocumentListener.java |
diffstat | 12 files changed, 222 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/swing/Border.luan Sat Apr 05 08:20:43 2025 -0600 @@ -0,0 +1,15 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local Number = require "luan:Number.luan" +local integer = Number.integer or error() +require "java" +local BorderFactory = require "java:javax.swing.BorderFactory" + + +local Border = {} + +function Border.create_empty_border(top,left,bottom,right) + return BorderFactory.createEmptyBorder(top,left,bottom,right) +end + +return Border
--- a/src/luan/modules/swing/Component.luan Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/Component.luan Sat Apr 05 08:20:43 2025 -0600 @@ -13,6 +13,9 @@ if key == "foreground_color" then return component.java.getForeground() end + if key == "border" then + return component.java.getBorder() + end return fail end @@ -21,6 +24,10 @@ component.java.setForeground(value) return end + if key == "border" then + component.java.setBorder(value) + return + end return fail end
--- a/src/luan/modules/swing/List.luan Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/List.luan Sat Apr 05 08:20:43 2025 -0600 @@ -11,7 +11,8 @@ 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 Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "swing/List" local List = {} @@ -54,8 +55,4 @@ 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/Scroll_pane.luan Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/Scroll_pane.luan Sat Apr 05 08:20:43 2025 -0600 @@ -1,9 +1,9 @@ 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 make_metatable = Utils.make_metatable or error() local Component = require "luan:swing/Component.luan" -local super__index = Component.__index or error() -local super__new_index = Component.__new_index or error() local super = Component.new or error() require "java" local JScrollPane = require "java:javax.swing.JScrollPane" @@ -11,15 +11,7 @@ local Scroll_pane = {} -local mt = {} - -function mt.__index(scroll_pane,key) - error("'"..key.."' not defined") -end - -function mt.__new_index(scroll_pane,key,value) - error("'"..key.."' not defined") -end +local mt = make_metatable(Component) function Scroll_pane.new(view) local jscroll_pane = JScrollPane.new(view.java)
--- a/src/luan/modules/swing/SwingLuan.java Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/SwingLuan.java Sat Apr 05 08:20:43 2025 -0600 @@ -21,7 +21,7 @@ import luan.LuanRuntimeException; -public final class SwingLuan { +public class SwingLuan { static { //System.setProperty("apple.awt.application.name", "MyApplication");
--- a/src/luan/modules/swing/TextAreaLineNumbers.java Thu Apr 03 16:17:56 2025 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -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); - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/swing/TextAreaLineNumbers.luan Sat Apr 05 08:20:43 2025 -0600 @@ -0,0 +1,24 @@ +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 make_metatable = Utils.make_metatable or error() +local Component = require "luan:swing/Component.luan" +local super = Component.new or error() +require "java" +local TextAreaLineNumbersLuan = require "java:luan.modules.swing.TextAreaLineNumbersLuan" + + +local TextAreaLineNumbers = {} + +local mt = make_metatable(Component) + +function TextAreaLineNumbers.new(text_area) + local jtaln = TextAreaLineNumbersLuan.new(text_area.java) + local taln = { java = jtaln } + super(taln) + set_metatable(taln,mt) + return taln +end + +return TextAreaLineNumbers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/swing/TextAreaLineNumbersLuan.java Sat Apr 05 08:20:43 2025 -0600 @@ -0,0 +1,139 @@ +package luan.modules.swing; + +import java.awt.Font; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Color; +import javax.swing.JPanel; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentListener; +import javax.swing.event.DocumentEvent; +import javax.swing.text.BadLocationException; +import goodjava.logging.Logger; +import goodjava.logging.LoggerFactory; + + +public class TextAreaLineNumbersLuan extends JPanel implements DocumentListener { + private static final Logger logger = LoggerFactory.getLogger(TextAreaLineNumbersLuan.class); + + private final TextAreaLuan textArea; + private int width; + private int lines; + + public TextAreaLineNumbersLuan(TextAreaLuan textArea) { + this.textArea = textArea; + this.lines = textArea.getLineCount(); + //logger.info("lines "+lines); + setFont(textArea.getFont()); + setLayout( new BoxLayout(this, BoxLayout.Y_AXIS) ); + for( int i=1; i<=lines; i++ ) { + JLabel label = newJLabel(i); + add(label); + } + fixWidth(); + fixHeights(); + textArea.getDocument().addDocumentListener(new WeakDocumentListener(this)); + } + + private JLabel newJLabel(int i) { + String text = String.valueOf(i); + JLabel label = new JLabel(text,JLabel.RIGHT); + label.setVerticalAlignment(JLabel.TOP); + label.setFont(getFont()); + label.setForeground(getForeground()); + return label; + } + + private void fixWidth() { + Component last = getComponent(getComponentCount()-1); + int lastWidth = last.getPreferredSize().width; + //logger.info("lastWidth "+lastWidth); + if( width != lastWidth ) { + width = lastWidth; + for( Component label : getComponents() ) { + Dimension size = label.getPreferredSize(); + Dimension newSize = new Dimension( width, size.height ); + label.setPreferredSize(newSize); + label.setMaximumSize(newSize); + //label.revalidate(); + //logger.info("setPreferredSize "+label.getPreferredSize().width); + } + //revalidate(); + //repaint(); + //logger.info("firstWidth0 "+getComponent(0).getSize().width); + } + } + + private void doFixHeights() { + Component[] a = getComponents(); + for( int i=0; i<a.length; i++ ) { + Component label = a[i]; + Dimension size = label.getPreferredSize(); + int height; + try { + height = textArea.getLineHeight(i); + } catch(BadLocationException e) { + throw new RuntimeException(e); + } + //logger.info("height "+i+" "+height); + if( height != size.height ) { + Dimension newSize = new Dimension( size.width, height ); + label.setPreferredSize(newSize); + label.setMaximumSize(newSize); + } + } + revalidate(); + //repaint(); + } + + private final Runnable fixHeightsRunnable = new Runnable() { + public void run() { + doFixHeights(); + } + }; + + private void fixHeights() { + SwingUtilities.invokeLater(fixHeightsRunnable); + } + + @Override public void setForeground(Color fg) { + super.setForeground(fg); + for( Component label : getComponents() ) { + label.setForeground(fg); + } + } + + @Override public void changedUpdate(DocumentEvent e) { + //logger.info(e.getType().toString()); + int n = textArea.getLineCount(); + if( lines < n ) { + for( int i=lines+1; i<=n; i++ ) { + JLabel label = newJLabel(i); + add(label); + } + lines = n; + } else if( lines > n ) { + for( int i=n; i<lines; i++ ) { + //logger.info("getComponentCount "+getComponentCount()); + //logger.info("remove "+n); + remove(n); + //logger.info("getComponentCount "+getComponentCount()); + } + lines = n; + //revalidate(); + repaint(); + } + fixHeights(); + } + + @Override public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + + @Override public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/swing/TextAreaLuan.java Sat Apr 05 08:20:43 2025 -0600 @@ -0,0 +1,27 @@ +package luan.modules.swing; + +import java.awt.Rectangle; +import javax.swing.JTextArea; +import javax.swing.text.BadLocationException; +import goodjava.logging.Logger; +import goodjava.logging.LoggerFactory; + + +public class TextAreaLuan extends JTextArea { + private static final Logger logger = LoggerFactory.getLogger(TextAreaLuan.class); + + public int getLineHeight(int line) throws BadLocationException { + Rectangle r1 = modelToView(getLineStartOffset(line)); +// if( r1 == null ) return 0; // hack + int startOffset = r1.y; + int endOffset = modelToView(getLineEndOffset(line)).y; + int height = endOffset - startOffset; + if( height == 0 ) + height = getRowHeight(); + return height; + } + + public int getLineRows(int line) throws BadLocationException { + return getLineHeight(line) / getRowHeight(); + } +}
--- a/src/luan/modules/swing/Text_area.luan Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/Text_area.luan Sat Apr 05 08:20:43 2025 -0600 @@ -9,7 +9,7 @@ local super__new_index = Text_component.__new_index or error() local new_text_component = Text_component.new or error() require "java" -local JTextArea = require "java:javax.swing.JTextArea" +local TextAreaLuan = require "java:luan.modules.swing.TextAreaLuan" local Text_area = {} @@ -67,7 +67,7 @@ local mt = make_metatable(Text_area) function Text_area.new() - local text_area = { java = JTextArea.new() } + local text_area = { java = TextAreaLuan.new() } new_text_component(text_area) local jtext_area = text_area.java set_metatable(text_area,mt)
--- a/src/luan/modules/swing/UndoManagerLuan.java Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/UndoManagerLuan.java Sat Apr 05 08:20:43 2025 -0600 @@ -16,7 +16,7 @@ import goodjava.logging.LoggerFactory; -public final class UndoManagerLuan extends UndoManager { +public class UndoManagerLuan extends UndoManager { private static final Logger logger = LoggerFactory.getLogger(UndoManagerLuan.class); private final WeakHashMap<LuanFunction,Boolean> map = new WeakHashMap<LuanFunction,Boolean>();
--- a/src/luan/modules/swing/WeakDocumentListener.java Thu Apr 03 16:17:56 2025 -0600 +++ b/src/luan/modules/swing/WeakDocumentListener.java Sat Apr 05 08:20:43 2025 -0600 @@ -5,7 +5,7 @@ import javax.swing.event.DocumentEvent; -public final class WeakDocumentListener implements DocumentListener { +public class WeakDocumentListener implements DocumentListener { private final WeakReference<DocumentListener> ref; public WeakDocumentListener(DocumentListener dl) {