JTextPane Study 2

I have done another study on the jTextPane, however it came out quite similar to the first study. Actually, there were things I liked about the first study that aren’t as elegant in the second study.

while I have added Actions (javax.swing.Action) to the program to make it easier coordinate menus with buttons, they almost seem more trouble than they are worth. For my use, when an action is performed, I need specific information that tells me where the caret was when the action was performed and adjust accordingly. Because of this, I would probably do a rewrite so my caret listener will have the information it needs.

Nevertheless, there are some things I learned while writing this, so I am going to go ahead and post it as a study.

Like before, there is an outer and inner class. The inner class is a very simple tool bar.

Here are some of the key APIs I used in the program:

import javax.swing.text.AbstractDocument;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

The StyledEditorKit contains the inner classes that are actions that function to toggle the attribute that I am working with. For instance, it contains StyledEditorKit.BoldAction(), StyledEditorKit.ItalicAction(), and various other pre-made toggles.

The StyleConstants are many of the well known constants that can be manipulated. I used StyleConstants to get information about the font in question.

SimpleAttributeSet is one of the more important functions. There are APIs that require a MutableAttributeSet. When you need a MutableAttributeSet, you can either create your own, or use a pre-made API like SimpleAttributeSet. Since I had no need to create my own, I used SimpleAttributeSet where a MutableAttributeSet was needed.

I think everything else is fairly self explanatory. Just because I’m feeling lazy, and I still need to rewrite this for another study, I’m not going to include the zip file to import the project. Instead, I’m just going to post the code in its entirety.

package GUI;

// imports
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.AbstractDocument;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.JTextPane;
import javax.swing.JScrollPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.Action;
import javax.swing.JToggleButton;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;

public class MainJFrame extends JFrame {
    
    /*
    * These could be converted to variables later and loaded
    * when the program initially runs. At would make the
    * program customizable.
    */
    final int JTEXTPANE_X = 500;
    final int JTEXTPANE_Y = 300;
    final int SMALL_FONT = 12;
    final int MEDIUM_FONT = 16;
    final int LARGE_FONT = 20;
    
    // class variables
    AbstractDocument abstractDocument;
    JTextPane jTextPane;
    JScrollPane jTextPaneScrollPane;
    Action boldAction, italicAction;
    Action smallFontAction, mediumFontAction, largeFontAction;
    TextControlBar textControlBar;
    
    // constructor
    public MainJFrame() {
        super("JTextPane Study version 2");
        createClasswideJTextPane();
        createClasswideActions();
        textControlBar = new TextControlBar();  // instance of inner class
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(textControlBar, BorderLayout.NORTH);
        this.add(jTextPaneScrollPane, BorderLayout.CENTER);
    }
    
    private void createClasswideJTextPane() {
        jTextPane = new JTextPane();
        StyledDocument styledDocument = jTextPane.getStyledDocument();
        // the following error checking comes from the tutorial.
        if(styledDocument instanceof AbstractDocument) {
            abstractDocument = (AbstractDocument)styledDocument;
        } else {
            System.err.println("StyledDocument isn't an AbstractDocument");
            System.exit(-1);
        }
        jTextPane.setPreferredSize(new Dimension(JTEXTPANE_X, JTEXTPANE_Y));
        jTextPaneScrollPane = new JScrollPane(jTextPane);
        jTextPane.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent event) {
                caretUpdateListener(event);
            }
        });
    }
    
    private void createClasswideActions() {
        boldAction = new StyledEditorKit.BoldAction();
        italicAction = new StyledEditorKit.ItalicAction();
        smallFontAction = new StyledEditorKit.FontSizeAction("small", SMALL_FONT);
        mediumFontAction = new StyledEditorKit.FontSizeAction("medium", MEDIUM_FONT);
        largeFontAction = new StyledEditorKit.FontSizeAction("large", LARGE_FONT);
    }
    
    public void caretUpdateListener(CaretEvent event) {
        boolean bold, italic;
        int size, currentDot, length;
        currentDot = event.getDot();
        length = abstractDocument.getLength();
        if(currentDot != length) {
            AttributeSet attributeSet;
            attributeSet = jTextPane.getCharacterAttributes();
            bold = StyleConstants.isBold(attributeSet);
            italic = StyleConstants.isItalic(attributeSet);
            size = StyleConstants.getFontSize(attributeSet);
            textControlBar.updateTextControlBar(bold, italic, size);
        }
    }
    
    static void createAndShowWindow() {
        JFrame jFrame = new MainJFrame();
        jFrame.pack();
        jFrame.setVisible(true);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowWindow();
            }
        });
    }
    
    /*
    *
    *
    * This is an inner class used as a menu bar
    *
    *
    */
    
    class TextControlBar extends JPanel {
        
        // inner class variables
        JComboBox paragraphTextSizeComboBox;
        JToggleButton boldButton;
        JToggleButton italicButton;
        JComboBox textSizeComboBox;
        DefaultComboBoxModel paragraphTextSizeComboBoxModel;
        DefaultComboBoxModel textSizeComboBoxModel;
        Object[] comboBoxEntries;
        
        // constructor
        TextControlBar() {
            boldButton = new JToggleButton(boldAction);
            italicButton = new JToggleButton(italicAction);
            comboBoxEntries = new String[] {"Small", "Medium", "Large"};
            textSizeComboBoxModel = new DefaultComboBoxModel(comboBoxEntries);
            paragraphTextSizeComboBoxModel = new DefaultComboBoxModel(comboBoxEntries);
            textSizeComboBox = new JComboBox(textSizeComboBoxModel);
            paragraphTextSizeComboBox = new JComboBox(paragraphTextSizeComboBoxModel);
            
            setLayout(new FlowLayout(FlowLayout.LEADING));
            
            this.add(paragraphTextSizeComboBox);
            paragraphTextSizeComboBox.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    paragraphTextSizeComboBoxActionListener();
                }
            });
            boldButton.setText("Bold");
            boldButton.setFont(new Font(Font.SERIF, Font.BOLD, 12));
            this.add(boldButton);
            italicButton.setText("Italic");
            italicButton.setFont(new Font(Font.SERIF, Font.ITALIC, 12));
            this.add(italicButton);
            this.add(textSizeComboBox);
            textSizeComboBox.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    textSizeComboBoxActionListener();
                }
            });
        }
        
        public void paragraphTextSizeComboBoxActionListener() {
            int index;
            SimpleAttributeSet simpleAttributeSet;
            simpleAttributeSet = new SimpleAttributeSet();
            index = paragraphTextSizeComboBox.getSelectedIndex();
            switch(index) {
                case 0:
                    StyleConstants.setFontSize(simpleAttributeSet, SMALL_FONT);
                    break;
                case 1:
                    StyleConstants.setFontSize(simpleAttributeSet, MEDIUM_FONT);
                    break;
                case 2:
                    StyleConstants.setFontSize(simpleAttributeSet, LARGE_FONT);
                    break;
                default:
                    StyleConstants.setFontSize(simpleAttributeSet, MEDIUM_FONT);
                    break;
            }
            jTextPane.setParagraphAttributes(simpleAttributeSet, true);
        }
        
        public void textSizeComboBoxActionListener() {
            int index;
            index = textSizeComboBox.getSelectedIndex();
            switch(index) {
                case 0:
                    smallFontAction.actionPerformed(null);
                    break;
                case 1:
                    mediumFontAction.actionPerformed(null);
                    break;
                case 2:
                    largeFontAction.actionPerformed(null);
                    break;
                default:
                    mediumFontAction.actionPerformed(null);
                    break;
            }
        }
        
        public void updateTextControlBar(boolean bold,
                                            boolean italic,
                                            int size) {
            boldButton.setSelected(bold);
            italicButton.setSelected(italic);
            switch(size) {
                case SMALL_FONT:
                    textSizeComboBox.setSelectedIndex(0);
                    break;
                case MEDIUM_FONT:
                    textSizeComboBox.setSelectedIndex(1);
                    break;
                case LARGE_FONT:
                    textSizeComboBox.setSelectedIndex(2);
                    break;
                default:
                    textSizeComboBox.setSelectedIndex(1);
                    break;
            }
        }
    } // end of TextControlBar class
} // End of MainJFrame class
Advertisements

Published by

Marisa

I am a writer of words, a thinker of thoughts, a changer of genders, and a queerer of life. I am an antagonist of the ordinary; and while I do tolerate it, I also look at it with contempt.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s