import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.util.stream.IntStream;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class JTextAreaBug {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TestFrame().launch());
    }
}

class TestFrame extends JFrame {
    private JTextArea txt = new JTextArea(10, 80);
    private JTextField len = new JTextField("9000", 6);
    private JTextField size = new JTextField("14", 4);
    private JComboBox<String> name;

    TestFrame() {
        setTitle("JTextArea - long line render bug example");
        JButton btn = new JButton("Refresh");
        btn.addActionListener(e -> refresh());
        name = new JComboBox<String>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
        name.setSelectedItem(txt.getFont().getFamily());
        JPanel ctrl = new JPanel();
        initCtrl(ctrl, "Line length:", len);
        initCtrl(ctrl, "Font name:", name);
        initCtrl(ctrl, "Font size:", size);
        ctrl.add(btn);
        refresh();
        getContentPane().add(BorderLayout.NORTH, ctrl);
        getContentPane().add(BorderLayout.CENTER, new JScrollPane(txt));
    }

    void launch() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void refresh() {
        try {
            txt.setFont(new Font(name.getSelectedItem().toString(), Font.PLAIN, Integer.parseInt(size.getText())));
            int n = Integer.parseInt(len.getText());
            StringBuilder res = new StringBuilder(n);
            IntStream.range(1, n).forEach(i -> res.append((char) (0x20 + i % 0x5E)));
            txt.setText(res.append("\n").toString());
        } catch (NumberFormatException e) {
            txt.setText("Bad input. Adjust and retry.\nDetails: " + e);
        }
        invalidate();
        repaint();
    }
    
    private final void initCtrl(Container parent, String label, JComponent c) {
        parent.add(new JLabel(label));
        parent.add(c);
    }
} 