Search code examples
javaswingtabsjtextpane

Insert tab in JTextPane after linebreak


It's a pretty small thing, but it still would be neat to have it.

Basically, when you program e.g. with Eclipse, it automatically inserts tabs in the class or in a for-loop, so you don't have to align your code after every linebreak again.

Is it possible to implement the "you-don't-have-to-press-tab-again-for-some-alignment-after-a-linebreak" feature somehow in a JTextPane or JEditorPane?


Solution

  • You can use a custom DocumentFilter to implement this behaviour:

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.text.*;
    
    public class EndOfLineFilter extends DocumentFilter
    {
        @Override
        public void replace(FilterBypass fb, final int offset, int length, String text, AttributeSet a)
            throws BadLocationException
        {
            if (text.equals("\n"))
                text = addWhiteSpace(fb, offset, text);
    
            super.replace(fb, offset, length, text, a);
        }
    
    
        private String addWhiteSpace(FilterBypass fb, int offset, String text) throws BadLocationException
        {
            Document doc = fb.getDocument();
            Element rootElement = doc.getDefaultRootElement();
            int line = rootElement.getElementIndex( offset );
            int i = rootElement.getElement(line).getStartOffset();
            StringBuilder whiteSpace = new StringBuilder(text);
    
            while (true)
            {
                String temp = doc.getText(i, 1);
    
                if (temp.equals(" ") || temp.equals("\t"))
                {
                    whiteSpace.append(temp);
                    i++;
                }
                else
                    break;
            }
    
            return whiteSpace.toString();
        }
    
        private static void createAndShowUI()
        {
            JTextArea textArea = new JTextArea(10, 30);
            AbstractDocument doc = (AbstractDocument)textArea.getDocument();
            doc.setDocumentFilter( new EndOfLineFilter() );
    
            JFrame frame = new JFrame("SSCCE");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( new JScrollPane( textArea ) );
            frame.pack();
            frame.setLocationByPlatform( true );
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowUI();
                }
            });
        }
    }
    

    Read the section from the Swing tutorial on Implementing a DocumentFilter for more information.