Java/Swing JFC/TextPane

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

A custom caret class

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// CornerCaret.java
//A custom caret class.
//
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.JTextComponent;
public class CornerCaret extends DefaultCaret {
  public CornerCaret() {
    setBlinkRate(500); // half a second
  }
  protected synchronized void damage(Rectangle r) {
    if (r == null)
      return;
    // give values to x,y,width,height (inherited from java.awt.Rectangle)
    x = r.x;
    y = r.y + (r.height * 4 / 5 - 3);
    width = 5;
    height = 5;
    repaint(); // calls getComponent().repaint(x, y, width, height)
  }
  public void paint(Graphics g) {
    JTextComponent comp = getComponent();
    if (comp == null)
      return;
    int dot = getDot();
    Rectangle r = null;
    try {
      r = comp.modelToView(dot);
    } catch (BadLocationException e) {
      return;
    }
    if (r == null)
      return;
    int dist = r.height * 4 / 5 - 3; // will be distance from r.y to top
    if ((x != r.x) || (y != r.y + dist)) {
      // paint() has been called directly, without a previous call to
      // damage(), so do some cleanup. (This happens, for example, when
      // the
      // text component is resized.)
      repaint(); // erase previous location of caret
      x = r.x; // set new values for x,y,width,height
      y = r.y + dist;
      width = 5;
      height = 5;
    }
    if (isVisible()) {
      g.setColor(comp.getCaretColor());
      g.drawLine(r.x, r.y + dist, r.x, r.y + dist + 4); // 5 vertical
                                // pixels
      g.drawLine(r.x, r.y + dist + 4, r.x + 4, r.y + dist + 4); // 5 horiz
                                    // px
    }
  }
  public static void main(String args[]) {
    JFrame frame = new JFrame("CornerCaret demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea area = new JTextArea(8, 32);
    area.setCaret(new CornerCaret());
    area
        .setText("This is the story\nof the hare who\nlost his spectacles.");
    frame.getContentPane().add(new JScrollPane(area), BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }
}





An example of highlighting multiple, discontiguous regions of a text component.

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// MultiHighlight.java
//An example of highlighting multiple, discontiguous regions of a text
//component.
//
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
public class MultiHighlight implements ActionListener {
  private JTextComponent comp;
  private String charsToHighlight;
  public MultiHighlight(JTextComponent c, String chars) {
    comp = c;
    charsToHighlight = chars;
  }
  public void actionPerformed(ActionEvent e) {
    // highlight all characters that appear in charsToHighlight
    Highlighter h = comp.getHighlighter();
    h.removeAllHighlights();
    String text = comp.getText().toUpperCase();
    for (int j = 0; j < text.length(); j += 1) {
      char ch = text.charAt(j);
      if (charsToHighlight.indexOf(ch) >= 0)
        try {
          h.addHighlight(j, j + 1, DefaultHighlighter.DefaultPainter);
        } catch (BadLocationException ble) {
        }
    }
  }
  public static void main(String args[]) {
    JFrame frame = new JFrame("MultiHighlight");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea area = new JTextArea(5, 20);
    area
        .setText("This is the story\nof the hare who\nlost his spectacles.");
    frame.getContentPane().add(new JScrollPane(area), BorderLayout.CENTER);
    JButton b = new JButton("Highlight All Vowels");
    b.addActionListener(new MultiHighlight(area, "aeiouAEIOU"));
    frame.getContentPane().add(b, BorderLayout.SOUTH);
    frame.pack();
    frame.setVisible(true);
  }
}





An example of several text components including password fields and formatted fields.

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TextComponentSampler.java
//An example of several text components including password fields and
//formatted fields.
//
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JEditorPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;
import javax.swing.text.MaskFormatter;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class TextComponentSampler extends JFrame {
  public static String word = "portmeiron";
  public static String markup = "Questions are <font size=\"+1\" color=\"blue\">a burden</font> to others,\n"
      + "answers <font size=\"+2\" color=\"red\">a prison</font> for oneself.";
  public TextComponentSampler() {
    super("TextComponentSampler");
    JTextField tf = new JTextField(word, 12);
    JPasswordField pf = new JPasswordField(word, 12);
    MaskFormatter formatter = null;
    try {
      formatter = new MaskFormatter("UUUUU");
    } catch (java.text.ParseException ex) {
    }
    JFormattedTextField ftf = new JFormattedTextField(formatter);
    ftf.setColumns(12);
    ftf.setValue(word);
    JTextArea ta1 = new JTextArea(markup);
    JScrollPane scroll1 = new JScrollPane(ta1);
    JTextArea ta2 = new JTextArea(markup);
    ta2.setLineWrap(true);
    ta2.setWrapStyleWord(true);
    JScrollPane scroll2 = new JScrollPane(ta2);
    JTextPane tp = new JTextPane();
    tp.setText(markup);
    // Create an AttributeSet with which to change color and font.
    SimpleAttributeSet attrs = new SimpleAttributeSet();
    StyleConstants.setForeground(attrs, Color.blue);
    StyleConstants.setFontFamily(attrs, "Serif");
    // Apply the AttributeSet to a few blocks of text.
    StyledDocument sdoc = tp.getStyledDocument();
    sdoc.setCharacterAttributes(14, 29, attrs, false);
    sdoc.setCharacterAttributes(51, 7, attrs, false);
    sdoc.setCharacterAttributes(78, 28, attrs, false);
    sdoc.setCharacterAttributes(114, 7, attrs, false);
    JScrollPane scroll3 = new JScrollPane(tp);
    JEditorPane ep1 = new JEditorPane("text/plain", markup);
    JScrollPane scroll4 = new JScrollPane(ep1);
    JEditorPane ep2 = new JEditorPane("text/html", markup);
    JScrollPane scroll5 = new JScrollPane(ep2);
    // Done creating text components; now lay them out and make them pretty.
    JPanel panel_tf = new JPanel();
    JPanel panel_pf = new JPanel();
    JPanel panel_ftf = new JPanel();
    panel_tf.add(tf);
    panel_pf.add(pf);
    panel_ftf.add(ftf);
    panel_tf.setBorder(new TitledBorder("JTextField"));
    panel_pf.setBorder(new TitledBorder("JPasswordField"));
    panel_ftf.setBorder(new TitledBorder("JFormattedTextField"));
    scroll1.setBorder(new TitledBorder("JTextArea (line wrap off)"));
    scroll2.setBorder(new TitledBorder("JTextArea (line wrap on)"));
    scroll3.setBorder(new TitledBorder("JTextPane"));
    scroll4.setBorder(new TitledBorder("JEditorPane (text/plain)"));
    scroll5.setBorder(new TitledBorder("JEditorPane (text/html)"));
    JPanel pan = new JPanel(new FlowLayout(FlowLayout.LEFT));
    pan.add(panel_tf);
    pan.add(panel_pf);
    pan.add(panel_ftf);
    Container contentPane = getContentPane();
    contentPane.setLayout(new GridLayout(2, 3, 8, 8));
    contentPane.add(pan);
    contentPane.add(scroll1);
    contentPane.add(scroll2);
    contentPane.add(scroll3);
    contentPane.add(scroll4);
    contentPane.add(scroll5);
  }
  public static void main(String args[]) {
    JFrame frame = new TextComponentSampler();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 450);
    frame.setVisible(true);
  }
}





An implementation of HighlightPainter that underlines text with a thick line

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// LineHighlightPainter.java
//An implementation of HighlightPainter that underlines text with a thick line.
//
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.DefaultCaret;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
public class LineHighlightPainter implements Highlighter.HighlightPainter {
  // paint a thick line under one line of text, from r extending rightward to
  // x2
  private void paintLine(Graphics g, Rectangle r, int x2) {
    int ytop = r.y + r.height - 3;
    g.fillRect(r.x, ytop, x2 - r.x, 3);
  }
  // paint thick lines under a block of text
  public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
    Rectangle r0 = null, r1 = null, rbounds = bounds.getBounds();
    int xmax = rbounds.x + rbounds.width; // x coordinate of right edge
    try { // convert positions to pixel coordinates
      r0 = c.modelToView(p0);
      r1 = c.modelToView(p1);
    } catch (BadLocationException ex) {
      return;
    }
    if ((r0 == null) || (r1 == null))
      return;
    g.setColor(c.getSelectionColor());
    // special case if p0 and p1 are on the same line
    if (r0.y == r1.y) {
      paintLine(g, r0, r1.x);
      return;
    }
    // first line, from p1 to end-of-line
    paintLine(g, r0, xmax);
    // all the full lines in between, if any (assumes that all lines have
    // the same height--not a good assumption with JEditorPane/JTextPane)
    r0.y += r0.height; // move r0 to next line
    r0.x = rbounds.x; // move r0 to left edge
    while (r0.y < r1.y) {
      paintLine(g, r0, xmax);
      r0.y += r0.height; // move r0 to next line
    }
    // last line, from beginning-of-line to p1
    paintLine(g, r0, r1.x);
  }
  public static void main(String args[]) {
    // extend DefaultCaret as an anonymous inner class
    Caret lineHighlightPainterCaret = new DefaultCaret() {
      private Highlighter.HighlightPainter lhp = new LineHighlightPainter();
      // override getSelectionPainter to return the LineHighlightPainter
      protected Highlighter.HighlightPainter getSelectionPainter() {
        return lhp;
      }
    };
    JFrame frame = new JFrame("LineHighlightPainter demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea area = new JTextArea(9, 45);
    area.setCaret(lineHighlightPainterCaret);
    area.setLineWrap(true);
    area.setWrapStyleWord(true);
    area
        .setText("This is the story\nof the hare who\nlost his spectacles.");
    frame.getContentPane().add(new JScrollPane(area), BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }
}





Appending TextPane

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
public class AppendingTextPane extends JTextPane {
  public AppendingTextPane() {
    super();
  }
  public AppendingTextPane(StyledDocument doc) {
    super(doc);
  }
  // Appends text to the document and ensure that it is visible
  public void appendText(String text) {
    try {
      Document doc = getDocument();
      // Move the insertion point to the end
      setCaretPosition(doc.getLength());
      // Insert the text
      replaceSelection(text);
      // Convert the new end location
      // to view co-ordinates
      Rectangle r = modelToView(doc.getLength());
      // Finally, scroll so that the new text is visible
      if (r != null) {
        scrollRectToVisible(r);
      }
    } catch (BadLocationException e) {
      System.out.println("Failed to append text: " + e);
    }
  }
  // Testing method
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Text Pane with Scrolling Append");
    final AppendingTextPane atp = new AppendingTextPane();
    f.getContentPane().add(new JScrollPane(atp));
    f.setSize(200, 200);
    f.setVisible(true);
    // Add some text every second
    Timer t = new Timer(1000, new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String timeString = fmt.format(new Date());
        atp.appendText(timeString + "\n");
      }
      SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss");
    });
    t.start();
  }
}





A separation of a data from the visual representation. In a JTextPane component, we have a StyledDocument for setting the style of the text data.

   
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class DocumentModel {
  public static void main(String[] args) {
    final StyledDocument doc;
    final JTextPane textpane;
    JFrame f = new JFrame();
    f.setTitle("Document Model");
    JToolBar toolbar = new JToolBar();
    JButton boldb = new JButton("bold");
    JButton italb = new JButton("italic");
    JButton strib = new JButton("strike");
    JButton undeb = new JButton("underline");
    toolbar.add(boldb);
    toolbar.add(italb);
    toolbar.add(strib);
    toolbar.add(undeb);
    f.add(toolbar, BorderLayout.NORTH);
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    JScrollPane pane = new JScrollPane();
    textpane = new JTextPane();
    textpane.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
    doc = textpane.getStyledDocument();
    Style style = textpane.addStyle("Bold", null);
    StyleConstants.setBold(style, true);
    style = textpane.addStyle("Italic", null);
    StyleConstants.setItalic(style, true);
    style = textpane.addStyle("Underline", null);
    StyleConstants.setUnderline(style, true);
    style = textpane.addStyle("Strike", null);
    StyleConstants.setStrikeThrough(style, true);
    boldb.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doc.setCharacterAttributes(textpane.getSelectionStart(), textpane.getSelectionEnd()
            - textpane.getSelectionStart(), textpane.getStyle("Bold"), false);
      }
    });
    italb.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doc.setCharacterAttributes(textpane.getSelectionStart(), textpane.getSelectionEnd()
            - textpane.getSelectionStart(), textpane.getStyle("Italic"), false);
      }
    });
    strib.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doc.setCharacterAttributes(textpane.getSelectionStart(), textpane.getSelectionEnd()
            - textpane.getSelectionStart(), textpane.getStyle("Strike"), false);
      }
    });
    undeb.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doc.setCharacterAttributes(textpane.getSelectionStart(), textpane.getSelectionEnd()
            - textpane.getSelectionStart(), textpane.getStyle("Underline"), false);
      }
    });
    pane.getViewport().add(textpane);
    panel.add(pane);
    f.add(panel);
    f.setSize(new Dimension(380, 320));
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}





A style can have multiple attributes; this one makes text bold and italic

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // A style can have multiple attributes; this one makes text bold and italic
    Style style = textPane.addStyle("Bold Italic", null);
    StyleConstants.setBold(style, true);
    StyleConstants.setItalic(style, true);
  }
}





A TabSet in a JTextPane

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TabExample.java
//Demonstrate a TabSet in a JTextPane.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
public class TabExample {
  public static void main(String[] args) {
    JTextPane pane = new JTextPane();
    TabStop[] tabs = new TabStop[4];
    tabs[0] = new TabStop(60, TabStop.ALIGN_RIGHT, TabStop.LEAD_NONE);
    tabs[1] = new TabStop(100, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
    tabs[2] = new TabStop(200, TabStop.ALIGN_CENTER, TabStop.LEAD_NONE);
    tabs[3] = new TabStop(300, TabStop.ALIGN_DECIMAL, TabStop.LEAD_NONE);
    TabSet tabset = new TabSet(tabs);
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
        StyleConstants.TabSet, tabset);
    pane.setParagraphAttributes(aset, false);
    pane.setText("\tright\tleft\tcenter\tdecimal\n" + "\t1\t1\t1\t1.0\n"
        + "\t200.002\t200.002\t200.002\t200.002\n"
        + "\t.33\t.33\t.33\t.33\n");
    JFrame frame = new JFrame("TabExample");
    frame.setContentPane(new JScrollPane(pane));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(360, 120);
    frame.setVisible(true);
  }
}





Background color

   
public class Main{
public static void main(String[] argv){
        // Get the text pane"s document
        JTextPane textPane = new JTextPane();
        StyledDocument doc = (StyledDocument)textPane.getDocument();
    
        // Create a style object and then set the style attributes
        Style style = doc.addStyle("StyleName", null);
        StyleConstants.setBackground(style, Color.blue);
        // Append to document
        doc.insertString(doc.getLength(), "Some Text", style);
}    }





Bi-Directional Text

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
/*
Bi-Directional Text. Model Order and Visual Order. Caret Position and the Selection. 
How Bi-Directional Text Is Handled in the Swing Text Components.
*/
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.PrintStream;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
public class BidiTextExample {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Bi-directional Text");
    final JTextPane tp = new JTextPane();
    if (args.length > 0 && args[0].equalsIgnoreCase("Arabic")) {
      GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
      System.out.println("Using physical font");
      Font font = new Font("Lucida Sans Regular", Font.PLAIN, 32);
      tp.setFont(font);
    } else {
      Font font = new Font("Serif", Font.PLAIN, 32);
      tp.setFont(font);
    }
    String s = new String(new char[] { (char) "A", (char) 0xFE76,
        (char) 0xFE77, (char) 0xFE78, (char) "Z" });
    final AbstractDocument doc = (AbstractDocument) tp.getDocument();
    System.out.println("i18n property is " + doc.getProperty("i18n"));
    // Turn on bi-directional text
    doc.putProperty("i18n", Boolean.TRUE);
    try {
      doc.insertString(0, s, null);
    } catch (Exception e) {
    }
    f.getContentPane().add(new JScrollPane(tp));
    f.setSize(300, 300);
    f.setVisible(true);
    tp.addCaretListener(new CaretListener() {
      public void caretUpdate(CaretEvent evt) {
        System.out.println("Caret position is " + evt.getDot());
      }
    });
    try {
      Thread.sleep(10000);
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          // Dump the model
          doc.dump(System.out);
          // Show the views
          ViewDisplayer.displayViews(tp, System.out);
        }
      });
    } catch (Exception e) {
    }
  }
}
class ViewDisplayer {
  public static void displayViews(JTextComponent comp, PrintStream out) {
    View rootView = comp.getUI().getRootView(comp);
    displayView(rootView, 0, comp.getDocument(), out);
  }
  public static void displayView(View view, int indent, Document doc,
      PrintStream out) {
    String name = view.getClass().getName();
    for (int i = 0; i < indent; i++) {
      out.print("\t");
    }
    int start = view.getStartOffset();
    int end = view.getEndOffset();
    out.println(name + "; offsets [" + start + ", " + end + "]");
    int viewCount = view.getViewCount();
    if (viewCount == 0) {
      int length = Math.min(32, end - start);
      try {
        String txt = doc.getText(start, length);
        for (int i = 0; i < indent + 1; i++) {
          out.print("\t");
        }
        out.println("[" + txt + "]");
      } catch (BadLocationException e) {
      }
    } else {
      for (int i = 0; i < viewCount; i++) {
        displayView(view.getView(i), indent + 1, doc, out);
      }
    }
  }
}





Bold style

   
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    Style style = doc.addStyle("StyleName", null);

    StyleConstants.setBold(style, true);
    doc.insertString(doc.getLength(), "Some Text", style);
  }
}





Brower based on JEditorPane

   
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.net.URL;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ruboBoxModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class Browser extends JFrame {
  protected JEditorPane m_browser;
  protected MemComboBox m_locator = new MemComboBox();
  public Browser() {
    super("HTML Browser");
    setSize(500, 300);
    getContentPane().setLayout(new BorderLayout());
    JPanel p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
    p.add(new JLabel("Address"));
    m_locator.load("addresses.dat");
    BrowserListener lst = new BrowserListener();
    m_locator.addActionListener(lst);
    MemComboAgent agent = new MemComboAgent(m_locator);
    p.add(m_locator);
    getContentPane().add(p, BorderLayout.NORTH);
    m_browser = new JEditorPane();
    m_browser.setEditable(false);
    m_browser.addHyperlinkListener(lst);
    JScrollPane sp = new JScrollPane();
    sp.getViewport().add(m_browser);
    getContentPane().add(sp, BorderLayout.CENTER);
    WindowListener wndCloser = new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        m_locator.save("addresses.dat");
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    setVisible(true);
    m_locator.grabFocus();
  }
  class BrowserListener implements ActionListener, HyperlinkListener {
    public void actionPerformed(ActionEvent evt) {
      String sUrl = (String) m_locator.getSelectedItem();
      if (sUrl == null || sUrl.length() == 0 )
        return;
      BrowserLoader loader = new BrowserLoader(sUrl);
      loader.start();
    }
    public void hyperlinkUpdate(HyperlinkEvent e) {
      URL url = e.getURL();
      if (url == null )
        return;
      BrowserLoader loader = new BrowserLoader(url.toString());
      loader.start();
    }
  }
  class BrowserLoader extends Thread {
    protected String m_sUrl;
    public BrowserLoader(String sUrl) {
      m_sUrl = sUrl;
    }
    public void run() {
      setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      try {
        URL source = new URL(m_sUrl);
        m_browser.setPage(source);
        m_locator.add(m_sUrl);
      } catch (Exception e) {
        JOptionPane.showMessageDialog(Browser.this, "Error: "
            + e.toString(), "Warning", JOptionPane.WARNING_MESSAGE);
      }
      setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }
  }
  public static void main(String argv[]) {
    new Browser();
  }
}
class MemComboAgent extends KeyAdapter {
  protected JComboBox m_comboBox;
  protected JTextField m_editor;
  public MemComboAgent(JComboBox comboBox) {
    m_comboBox = comboBox;
    m_editor = (JTextField) comboBox.getEditor().getEditorComponent();
    m_editor.addKeyListener(this);
  }
  public void keyReleased(KeyEvent e) {
    char ch = e.getKeyChar();
    if (ch == KeyEvent.CHAR_UNDEFINED || Character.isISOControl(ch))
      return;
    int pos = m_editor.getCaretPosition();
    String str = m_editor.getText();
    if (str.length() == 0)
      return;
    for (int k = 0; k < m_comboBox.getItemCount(); k++) {
      String item = m_comboBox.getItemAt(k).toString();
      if (item.startsWith(str)) {
        m_editor.setText(item);
        m_editor.setCaretPosition(item.length());
        m_editor.moveCaretPosition(pos);
        break;
      }
    }
  }
}
class MemComboBox extends JComboBox {
  public static final int MAX_MEM_LEN = 30;
  public MemComboBox() {
    super();
    setEditable(true);
  }
  public void add(String item) {
    removeItem(item);
    insertItemAt(item, 0);
    setSelectedItem(item);
    if (getItemCount() > MAX_MEM_LEN)
      removeItemAt(getItemCount() - 1);
  }
  public void load(String fName) {
    try {
      if (getItemCount() > 0)
        removeAllItems();
      File f = new File(fName);
      if (!f.exists())
        return;
      FileInputStream fStream = new FileInputStream(f);
      ObjectInput stream = new ObjectInputStream(fStream);
      Object obj = stream.readObject();
      if (obj instanceof ComboBoxModel)
        setModel((ComboBoxModel) obj);
      stream.close();
      fStream.close();
    } catch (Exception e) {
      System.err.println("Serialization error: " + e.toString());
    }
  }
  public void save(String fName) {
    try {
      FileOutputStream fStream = new FileOutputStream(fName);
      ObjectOutput stream = new ObjectOutputStream(fStream);
      stream.writeObject(getModel());
      stream.flush();
      stream.close();
      fStream.close();
    } catch (Exception e) {
      System.err.println("Serialization error: " + e.toString());
    }
  }
}





Change the Font size of JTextPane

   
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception{
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    // Create a style object and then set the style attributes
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setFontSize(style, 30);
    doc.insertString(doc.getLength(), "Some Text", style);
  }
}





Create a tab set from the tab stops

   
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
public class Main {
  public static void main(String[] argv) {
      JTextPane textPane = new JTextPane();
    List list = new ArrayList();
    TabStop[] tstops = (TabStop[]) list.toArray(new TabStop[0]);
    TabSet tabs = new TabSet(tstops);
    Style style = textPane.getLogicalStyle();
    StyleConstants.setTabSet(style, tabs);
    textPane.setLogicalStyle(style);
  }
}





Customizing Tab Stops in a JTextPane Component

   
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextPane;
import javax.swing.text.TabStop;
public class Main {
  public static void main(String[] argv) {
    List list = new ArrayList();
    // Create a left-aligned tab stop at 100 pixels from the left margin
    float pos = 100;
    int align = TabStop.ALIGN_LEFT;
    int leader = TabStop.LEAD_NONE;
    TabStop tstop = new TabStop(pos, align, leader);
    list.add(tstop);
  }
}





Determine if the attribute is a color or a font-related attribute.

   
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) {
    // Check if color-based attribute
    boolean b = StyleConstants.Foreground instanceof AttributeSet.ColorAttribute; 
    b = StyleConstants.Italic instanceof AttributeSet.ColorAttribute;
    // Check if font-based attribute
    b = StyleConstants.Italic instanceof AttributeSet.FontAttribute; 
    b = StyleConstants.Foreground instanceof AttributeSet.FontAttribute;
  }
}





Determining If a Style Attribute Applies to a Character or the Paragraph

   
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) {
    // Check if character-based attribute
    boolean b = StyleConstants.Italic instanceof AttributeSet.CharacterAttribute;
    b = StyleConstants.LineSpacing instanceof AttributeSet.CharacterAttribute; 
    // Check if paragraph-based attribute
    b = StyleConstants.LineSpacing instanceof AttributeSet.ParagraphAttribute; 
    b = StyleConstants.Italic instanceof AttributeSet.ParagraphAttribute; 
  }
}





Duplicate style

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // Set text in the range [5, 7) red
    doc.setCharacterAttributes(5, 2, textPane.getStyle("Red"), true);
  }
}





Enumerating the Paragraphs of a JTextPane Component

   
import javax.swing.JTextPane;
import javax.swing.text.Element;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    Element section = textPane.getDocument().getDefaultRootElement();
    int paraCount = section.getElementCount();
    for (int i = 0; i < paraCount; i++) {
      Element e = section.getElement(i);
      int rangeStart = e.getStartOffset();
      int rangeEnd = e.getEndOffset();
      String para = textPane.getText(rangeStart, rangeEnd - rangeStart);
      System.out.println(para);
    }
  }
}





Extension of JTextPane that allows the user to easily append colored text to the document

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// ColorPane.java
//A simple extension of JTextPane that allows the user to easily append
//colored text to the document.
//
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class ColorPane extends JTextPane {
  public void appendNaive(Color c, String s) { // naive implementation
    // bad: instiantiates a new AttributeSet object on each call
    SimpleAttributeSet aset = new SimpleAttributeSet();
    StyleConstants.setForeground(aset, c);
    int len = getText().length();
    setCaretPosition(len); // place caret at the end (with no selection)
    setCharacterAttributes(aset, false);
    replaceSelection(s); // there is no selection, so inserts at caret
  }
  public void append(Color c, String s) { // better implementation--uses
                      // StyleContext
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
        StyleConstants.Foreground, c);
    int len = getDocument().getLength(); // same value as
                       // getText().length();
    setCaretPosition(len); // place caret at the end (with no selection)
    setCharacterAttributes(aset, false);
    replaceSelection(s); // there is no selection, so inserts at caret
  }
  public static void main(String argv[]) {
    ColorPane pane = new ColorPane();
    for (int n = 1; n <= 400; n += 1) {
      if (isPrime(n)) {
        pane.append(Color.red, String.valueOf(n) + " ");
      } else if (isPerfectSquare(n)) {
        pane.append(Color.blue, String.valueOf(n) + " ");
      } else {
        pane.append(Color.black, String.valueOf(n) + " ");
      }
    }
    JFrame f = new JFrame("ColorPane example");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setContentPane(new JScrollPane(pane));
    f.setSize(600, 400);
    f.setVisible(true);
  }
  public static boolean isPrime(int n) {
    if (n < 2)
      return false;
    double max = Math.sqrt(n);
    for (int j = 2; j <= max; j += 1)
      if (n % j == 0)
        return false; // j is a factor
    return true;
  }
  public static boolean isPerfectSquare(int n) {
    int j = 1;
    while (j * j < n && j * j > 0)
      j += 1;
    return (j * j == n);
  }
}





Font family

   
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setFontFamily(style, "SansSerif");
    // Append to document
    doc.insertString(doc.getLength(), "Some Text", style);
  }
}





Foreground color

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception{
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    // Create a style object and then set the style attributes
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setForeground(style, Color.white);
    // Append to document
    doc.insertString(doc.getLength(), "Some Text", style);
  }
}





Get Leading White Space

   
/*
 * StandardUtilities.java - Various miscallaneous utility functions
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2006 Matthieu Casanova, Slava Pestov
 * Portions copyright (C) 2000 Richard S. Hall
 * Portions copyright (C) 2001 Dirk Moebius
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//{{{ Imports
import javax.swing.text.Segment;
import java.util.ruparator;
import java.util.Stack;
//}}}
/**
 * Several tools that depends on JDK only.
 *
 * @author Matthieu Casanova
 * @version $Id: StandardUtilities.java 12884 2008-06-23 18:17:08Z kpouer $
 * @since 4.3pre5
 */
public class StandardUtilities
{
  //{{{ getLeadingWhiteSpace() method
  /**
   * Returns the number of leading white space characters in the
   * specified string.
   *
   * @param str The string
   */
  public static int getLeadingWhiteSpace(String str)
  {
    return getLeadingWhiteSpace((CharSequence)str);
  } //}}}
  //{{{ getLeadingWhiteSpace() method
  /**
   * Returns the number of leading white space characters in the
   * specified string.
   *
   * @param str The string
   * @since jEdit 4.3pre15
   */
  public static int getLeadingWhiteSpace(CharSequence str)
  {
    int whitespace = 0;
loop:   for(;whitespace < str.length();)
    {
      switch(str.charAt(whitespace))
      {
      case " ":
      case "\t":
        whitespace++;
        break;
      default:
        break loop;
      }
    }
    return whitespace;
  } //}}}
}





Get Leading White Space Width

   
/*
 * StandardUtilities.java - Various miscallaneous utility functions
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2006 Matthieu Casanova, Slava Pestov
 * Portions copyright (C) 2000 Richard S. Hall
 * Portions copyright (C) 2001 Dirk Moebius
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//{{{ Imports
import javax.swing.text.Segment;
import java.util.ruparator;
import java.util.Stack;
//}}}
/**
 * Several tools that depends on JDK only.
 *
 * @author Matthieu Casanova
 * @version $Id: StandardUtilities.java 12884 2008-06-23 18:17:08Z kpouer $
 * @since 4.3pre5
 */
public class StandardUtilities
{
  //{{{ getLeadingWhiteSpaceWidth() method
  /**
   * Returns the width of the leading white space in the specified
   * string.
   * @param str The string
   * @param tabSize The tab size
   */
  public static int getLeadingWhiteSpaceWidth(String str, int tabSize)
  {
    return getLeadingWhiteSpaceWidth((CharSequence)str, tabSize);
  } //}}}
  //{{{ getLeadingWhiteSpaceWidth() method
  /**
   * Returns the width of the leading white space in the specified
   * string.
   * @param str The string
   * @param tabSize The tab size
   * @since jEdit 4.3pre15
   */
  public static int getLeadingWhiteSpaceWidth(CharSequence str, int tabSize)
  {
    int whitespace = 0;
loop:   for(int i = 0; i < str.length(); i++)
    {
      switch(str.charAt(i))
      {
        case " ":
          whitespace++;
          break;
        case "\t":
          whitespace += tabSize -
            whitespace % tabSize;
          break;
        default:
          break loop;
      }
    }
    return whitespace;
  } //}}}
}





Get logical style and restore it after new paragraph style

   

import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
  
    Style style = textPane.addStyle(null, null);
    StyleConstants.setForeground(style, Color.red);
    textPane.setLogicalStyle(style);
  
    
    Style logicalStyle = textPane.getLogicalStyle();
    style = textPane.addStyle(null, null);
    StyleConstants.setBold(style, true);
    textPane.setParagraphAttributes(style, true);
    textPane.setLogicalStyle(logicalStyle);
  
  }
}





Get Max Fitting FontSize

   
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * The utillib library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.awt.*;

/**
 * Provides graphics related utilities.
 */
public class GraphicsUtilities{

  /**
   * Calculates the largest size of the given font for which the given string 
   * will fit into the given size. This method uses the default toolkit.
   */
  public static int getMaxFittingFontSize(Graphics g, Font font, String string, Dimension size){
    return getMaxFittingFontSize(g, font, string, size.width, size.height);
  }
  
  /**
   * Calculates the largest size of the given font for which the given string 
   * will fit into the given size.
   */
  public static int getMaxFittingFontSize(Graphics g, Font font, String string, int width, int height){
    int minSize = 0;
    int maxSize = 288;
    int curSize = font.getSize();
    while (maxSize - minSize > 2){
      FontMetrics fm = g.getFontMetrics(new Font(font.getName(), font.getStyle(), curSize));
      int fontWidth = fm.stringWidth(string);
      int fontHeight = fm.getLeading() + fm.getMaxAscent() + fm.getMaxDescent();
      if ((fontWidth > width) || (fontHeight > height)){
        maxSize = curSize;
        curSize = (maxSize + minSize) / 2;
      }
      else{
        minSize = curSize;
        curSize = (minSize + maxSize) / 2;
      }
    }
    return curSize;
  }
  
  
  
  
  /**
   * Returns the <code>FontMetrics</code> for the specified <code>Font</code>.  
   */
  
  public static FontMetrics getFontMetrics(Font font){
    return Toolkit.getDefaultToolkit().getFontMetrics(font); // DEPRECATED    
  }


  /**
   * Returns <code>true</code> if the first rectangle completely contains the
   * second one. Returns <code>false</code> otherwise. This method is needed
   * because there is no Rectangle.contains(Rectangle) method in JDK 1.1
   * (unlike claimed in the 1.2 documentation).
   */
  public static boolean contains(Rectangle rect1, Rectangle rect2){
    return (rect2.x >= rect1.x) &&
           (rect2.y >= rect1.y) &&
           (rect2.x+rect2.width <= rect1.x+rect1.width) &&
           (rect2.y+rect2.height <= rect1.y+rect1.height);
  }


  /**
   * Returns true if the two specified rectangles intersect. Two rectangles
   * intersect if their intersection is nonempty. This method is not really
   * needed because Rectangle.intersects(Rectangle) exists in JDK1.1, but I
   * still like having it here for symmetry.
   */
  public static boolean intersect(Rectangle rect1, Rectangle rect2){
    return rect1.intersects(rect2);
  }

}





Inserting a Component into a JTextPane Component

   

import javax.swing.JButton;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setComponent(style, new JButton("OK"));
    doc.insertString(doc.getLength(), "ignored text", style);
  }
}





Inserting an Image into a JTextPane Component

   
import javax.swing.ImageIcon;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception{
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setIcon(style, new ImageIcon("imagefile"));
    doc.insertString(doc.getLength(), "ignored text", style);
  }
}





Inserting Styled Text in a JTextPane Component

   
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception{
    JTextPane textPane = new JTextPane();
    StyledDocument doc = (StyledDocument) textPane.getDocument();
    Style style = doc.addStyle("StyleName", null);
    StyleConstants.setItalic(style, true);
    doc.insertString(doc.getLength(), "Some Text", style);
  }
}





Italicize the entire paragraph containing the position 12

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // Italicize the entire paragraph containing the position 12
    doc.setParagraphAttributes(12, 1, textPane.getStyle("Italic"), true);
  }
}





JEditorPane Replace Reader

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.io.FileReader;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
public class ReplaceReader {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("JEditorPane with Custom Reader");
    JEditorPane ep = new JEditorPane();
    f.getContentPane().add(new JScrollPane(ep));
    f.setSize(400, 300);
    f.setVisible(true);
    HTMLEditorKit kit = new HTMLEditorKit() {
      public Document createDefaultDocument() {
        HTMLDocument doc = new CustomHTMLDocument(getStyleSheet());
        doc.setAsynchronousLoadPriority(4);
        doc.setTokenThreshold(100);
        return doc;
      }
    };
    ep.setEditorKit(kit);
    
    try {
      Document doc = ep.getDocument();
      doc.putProperty("IgnoreCharsetDirective", new Boolean(true));
      kit.read(new FileReader(args[0]), doc, 0);
    } catch (Exception e) {
      System.out.println("Exception while reading HTML " + e);
    }
  }
}
class CustomHTMLDocument extends HTMLDocument {
  CustomHTMLDocument(StyleSheet styles) {
    super(styles);
  }
  public HTMLEditorKit.ParserCallback getReader(int pos) {
    return new CustomReader(pos);
  }
          
  class CustomReader extends HTMLDocument.HTMLReader {
    public CustomReader(int pos) {
      super(pos);
    }
    public void flush() throws BadLocationException {
      System.out.println("flush called");
      super.flush();
    }
    public void handleText(char[] data, int pos) {
      indent();
      System.out.println("handleText <" + new String(data) + ">, pos " + pos);
      super.handleText(data, pos);
    }
    public void handleComment(char[] data, int pos) {
      indent();
      System.out.println("handleComment <" + new String(data) + ">, pos " + pos);
      super.handleComment(data, pos);
    }
    public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
      indent();
      System.out.println("handleStartTag <" + t + ">, pos " + pos);
      indent();
      System.out.println("Attributes: " + a);
      tagLevel++;
      super.handleStartTag(t, a, pos);
    }
    public void handleEndTag(HTML.Tag t, int pos) {
      tagLevel--;
      indent();
      System.out.println("handleEndTag <" + t + ">, pos " + pos);
      super.handleEndTag(t, pos);
    }
    public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
      indent();
      System.out.println("handleSimpleTag <" + t + ">, pos " + pos);
      indent();
      System.out.println("Attributes: " + a);
      super.handleSimpleTag(t, a, pos);
    }
    public void handleError(String errorMsg, int pos){
      indent();
      System.out.println("handleError <" + errorMsg + ">, pos " + pos);
      super.handleError(errorMsg, pos);
    }
    protected void indent() {
      for (int i = 0; i < tagLevel; i++) {
        System.out.print(" ");
      }
    }
    int tagLevel;
  }
}





JTextPane demo with various format and html loading and rendering

   
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class JTextPaneDemo extends JFrame {
  static SimpleAttributeSet ITALIC_GRAY = new SimpleAttributeSet();
  static SimpleAttributeSet BOLD_BLACK = new SimpleAttributeSet();
  static SimpleAttributeSet BLACK = new SimpleAttributeSet();
  JTextPane textPane = new JTextPane();
  // Best to reuse attribute sets as much as possible.
  static {
    StyleConstants.setForeground(ITALIC_GRAY, Color.gray);
    StyleConstants.setItalic(ITALIC_GRAY, true);
    StyleConstants.setFontFamily(ITALIC_GRAY, "Helvetica");
    StyleConstants.setFontSize(ITALIC_GRAY, 14);
    StyleConstants.setForeground(BOLD_BLACK, Color.black);
    StyleConstants.setBold(BOLD_BLACK, true);
    StyleConstants.setFontFamily(BOLD_BLACK, "Helvetica");
    StyleConstants.setFontSize(BOLD_BLACK, 14);
    StyleConstants.setForeground(BLACK, Color.black);
    StyleConstants.setFontFamily(BLACK, "Helvetica");
    StyleConstants.setFontSize(BLACK, 14);
  }
  public JTextPaneDemo() {
    super("JTextPane Demo");
    JScrollPane scrollPane = new JScrollPane(textPane);
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    setEndSelection();
    textPane.insertIcon(new ImageIcon("jexpLogo.GIF"));
    insertText("\nWebsite for: www.jexp.ru \n\n", BOLD_BLACK);
    setEndSelection();
    insertText("                                    ", BLACK);
    setEndSelection();
    insertText("\n      Java            "
        + "                                    " + "Source\n\n",
        ITALIC_GRAY);
    insertText(" and Support. \n", BLACK);
    setEndSelection();
    JButton manningButton = new JButton("Load the web site for www.jexp.ru");
    manningButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        textPane.setEditable(false);
        try {
          textPane.setPage("http://www.jexp.ru");
        } catch (IOException ioe) {
          ioe.printStackTrace();
        }
      }
    });
    textPane.insertComponent(manningButton);
    setSize(500, 450);
    setVisible(true);
  }
  protected void insertText(String text, AttributeSet set) {
    try {
      textPane.getDocument().insertString(
          textPane.getDocument().getLength(), text, set);
    } catch (BadLocationException e) {
      e.printStackTrace();
    }
  }
  // Needed for inserting icons in the right places
  protected void setEndSelection() {
    textPane.setSelectionStart(textPane.getDocument().getLength());
    textPane.setSelectionEnd(textPane.getDocument().getLength());
  }
  public static void main(String argv[]) {
    new JTextPaneDemo();
  }
}





JTextPane Extended Paragraph Example

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.ParagraphView;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ExtendedParagraphExample {
  public static void createDocumentStyles(StyleContext sc) {
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.white);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    // Create and add the extended para styles
    Style paraStyle = sc.addStyle(paraStyleName, null);
    Color bgColor = Color.gray;
    ExtendedStyleConstants.setParagraphBackground(paraStyle, bgColor);
    ExtendedStyleConstants.setParagraphBorder(paraStyle, BorderFactory
        .createCompoundBorder(BorderFactory.createEmptyBorder(2, 2, 2,
            2), BorderFactory.createCompoundBorder(BorderFactory
            .createEtchedBorder(bgColor.brighter(), bgColor
                .darker()), BorderFactory.createEmptyBorder(4,
            4, 4, 4))));
  }
  public static void addText(JTextPane pane, StyleContext sc,
      Style logicalStyle, Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
            runs[j].styleName == null ? SimpleAttributeSet.EMPTY
                : sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName),
            false);
      }
      if (i != paragraphs - 1) {
        pane.replaceSelection("\n");
      }
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Extended Paragraph Example");
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    pane.setEditorKit(new ExtendedStyledEditorKit());
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Build the styles
          createDocumentStyles(sc);
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  public static final String paraStyleName = "ExtendedPara";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
      new Paragraph(heading2StyleName, new Run[] { new Run(null,
          "Attributes, Styles and Style Contexts") }),
      new Paragraph(
          paraStyleName,
          new Run[] {
              new Run(null, "The simple "),
              new Run(charStyleName, "PlainDocument"),
              new Run(
                  null,
                  " class that you saw in the previous "
                      + "chapter is only capable of holding text. "
                      + "The more complex text components use a more "
                      + "sophisticated model that implements the "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " interface. "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " is a sub-interface of "),
              new Run(charStyleName, "Document"),
              new Run(
                  null,
                  " that contains methods for manipulating attributes "
                      + "that control the way in which the text in the "
                      + "document is displayed. The Swing text package "
                      + "contains a concrete implementation of "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " called "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null,
                  " that is used as the default model for "),
              new Run(charStyleName, "JTextPane"),
              new Run(
                  null,
                  " and is also the base class from which "
                      + "more specific models, such as the "),
              new Run(charStyleName, "HTMLDocument"),
              new Run(
                  null,
                  " class that handles input in HTML format, can be "
                      + "created. In order to make use of "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null, " and "),
              new Run(charStyleName, "JTextPane"),
              new Run(null,
                  " you need to understand how Swing represents "
                      + "and uses attributes.") }) };
}
class ExtendedStyleConstants {
  public ExtendedStyleConstants(String name) {
    this.name = name;
  }
  public String toString() {
    return name;
  }
  /**
   * The border to be used for a paragraph. Type is javax.swing.border.Border
   */
  public static final Object ParagraphBorder = ExtendedParagraphConstants.ParagraphBorder;
  /**
   * The background to be used for a paragraph. Type is java.awt.Color
   */
  public static final Object ParagraphBackground = ExtendedParagraphConstants.ParagraphBackground;
  /* Adds the border attribute */
  public static void setParagraphBorder(MutableAttributeSet a, Border b) {
    a.addAttribute(ParagraphBorder, b);
  }
  /* Gets the border attribute */
  public static Border getParagraphBorder(AttributeSet a) {
    return (Border) a.getAttribute(ParagraphBorder);
  }
  /* Adds the paragraph background attribute */
  public static void setParagraphBackground(MutableAttributeSet a, Color c) {
    a.addAttribute(ParagraphBackground, c);
  }
  /* Gets the paragraph background attribute */
  public static Color getParagraphBackground(AttributeSet a) {
    return (Color) a.getAttribute(ParagraphBackground);
  }
  /* A typesafe collection of extended paragraph attributes */
  public static class ExtendedParagraphConstants extends
      ExtendedStyleConstants implements AttributeSet.ParagraphAttribute {
    /**
     * The paragraph border attribute.
     */
    public static final Object ParagraphBorder = new ExtendedParagraphConstants(
        "ParagraphBorder");
    /**
     * The paragraph background attribute.
     */
    public static final Object ParagraphBackground = new ExtendedParagraphConstants(
        "ParagraphBackground");
    private ExtendedParagraphConstants(String name) {
      super(name);
    }
  }
  protected String name; // Name of an attribute
}
class ExtendedStyledEditorKit extends StyledEditorKit {
  public Object clone() {
    return new ExtendedStyledEditorKit();
  }
  public ViewFactory getViewFactory() {
    return defaultFactory;
  }
  /* The extended view factory */
  static class ExtendedStyledViewFactory implements ViewFactory {
    public View create(Element elem) {
      String elementName = elem.getName();
      if (elementName != null) {
        if (elementName.equals(AbstractDocument.ParagraphElementName)) {
          return new ExtendedParagraphView(elem);
        }
      }
      // Delegate others to StyledEditorKit
      return styledEditorKitFactory.create(elem);
    }
  }
  private static final ViewFactory styledEditorKitFactory = (new StyledEditorKit())
      .getViewFactory();
  private static final ViewFactory defaultFactory = new ExtendedStyledViewFactory();
}
class ExtendedParagraphView extends ParagraphView {
  public ExtendedParagraphView(Element elem) {
    super(elem);
  }
  // Override ParagraphView methods
  protected void setPropertiesFromAttributes() {
    AttributeSet attr = getAttributes();
    if (attr != null) {
      super.setPropertiesFromAttributes();
      paraInsets = new Insets(getTopInset(), getLeftInset(),
          getBottomInset(), getRightInset());
      border = ExtendedStyleConstants.getParagraphBorder(attr);
      bgColor = ExtendedStyleConstants.getParagraphBackground(attr);
      if (bgColor != null && border == null) {
        // Provide a small margin if the background
        // is being filled and there is no border
        border = smallBorder;
      }
      if (border != null) {
        Insets borderInsets = border.getBorderInsets(getContainer());
        setInsets((short) (paraInsets.top + borderInsets.top),
            (short) (paraInsets.left + borderInsets.left),
            (short) (paraInsets.bottom + borderInsets.bottom),
            (short) (paraInsets.right + borderInsets.right));
      }
    }
  }
  public void paint(Graphics g, Shape a) {
    Container comp = getContainer();
    Rectangle alloc = new Rectangle(a.getBounds());
    alloc.x += paraInsets.left;
    alloc.y += paraInsets.top;
    alloc.width -= paraInsets.left + paraInsets.right;
    alloc.height -= paraInsets.top + paraInsets.bottom;
    if (bgColor != null) {
      Color origColor = g.getColor();
      g.setColor(bgColor);
      g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height);
      g.setColor(origColor);
    }
    if (border != null) {
      // Paint the border
      border.paintBorder(comp, g, alloc.x, alloc.y, alloc.width,
          alloc.height);
    }
    super.paint(g, a); // Note: pass ORIGINAL allocation
  }
  // Attribute cache
  protected Color bgColor; // Background color, or null for transparent.
  protected Border border; // Border, or null for no border
  protected Insets paraInsets; // Original paragraph insets
  protected static final Border smallBorder = BorderFactory
      .createEmptyBorder(2, 2, 2, 2);
}





JTextPane Highlight Example

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileReader;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.LayeredHighlighter;
import javax.swing.text.Position;
import javax.swing.text.View;
public class HighlightExample {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Highlight example");
    final JTextPane textPane = new JTextPane();
    textPane.setHighlighter(highlighter);
    JPanel pane = new JPanel();
    pane.setLayout(new BorderLayout());
    pane.add(new JLabel("Enter word: "), "West");
    final JTextField tf = new JTextField();
    pane.add(tf, "Center");
    f.getContentPane().add(pane, "South");
    f.getContentPane().add(new JScrollPane(textPane), "Center");
    try {
      textPane.read(new FileReader("links1.html"), null);
    } catch (Exception e) {
      System.out.println("Failed to load file " + args[0]);
      System.out.println(e);
    }
    final WordSearcher searcher = new WordSearcher(textPane);
    tf.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        word = tf.getText().trim();
        int offset = searcher.search(word);
        if (offset != -1) {
          try {
            textPane.scrollRectToVisible(textPane
                .modelToView(offset));
          } catch (BadLocationException e) {
          }
        }
      }
    });
    textPane.getDocument().addDocumentListener(new DocumentListener() {
      public void insertUpdate(DocumentEvent evt) {
        searcher.search(word);
      }
      public void removeUpdate(DocumentEvent evt) {
        searcher.search(word);
      }
      public void changedUpdate(DocumentEvent evt) {
      }
    });
    f.setSize(400, 400);
    f.setVisible(true);
  }
  public static String word;
  public static Highlighter highlighter = new UnderlineHighlighter(null);
}
// A simple class that searches for a word in
// a document and highlights occurrences of that word
class WordSearcher {
  public WordSearcher(JTextComponent comp) {
    this.rup = comp;
    this.painter = new UnderlineHighlighter.UnderlineHighlightPainter(
        Color.red);
  }
  // Search for a word and return the offset of the
  // first occurrence. Highlights are added for all
  // occurrences found.
  public int search(String word) {
    int firstOffset = -1;
    Highlighter highlighter = comp.getHighlighter();
    // Remove any existing highlights for last word
    Highlighter.Highlight[] highlights = highlighter.getHighlights();
    for (int i = 0; i < highlights.length; i++) {
      Highlighter.Highlight h = highlights[i];
      if (h.getPainter() instanceof UnderlineHighlighter.UnderlineHighlightPainter) {
        highlighter.removeHighlight(h);
      }
    }
    if (word == null || word.equals("")) {
      return -1;
    }
    // Look for the word we are given - insensitive search
    String content = null;
    try {
      Document d = comp.getDocument();
      content = d.getText(0, d.getLength()).toLowerCase();
    } catch (BadLocationException e) {
      // Cannot happen
      return -1;
    }
    word = word.toLowerCase();
    int lastIndex = 0;
    int wordSize = word.length();
    while ((lastIndex = content.indexOf(word, lastIndex)) != -1) {
      int endIndex = lastIndex + wordSize;
      try {
        highlighter.addHighlight(lastIndex, endIndex, painter);
      } catch (BadLocationException e) {
        // Nothing to do
      }
      if (firstOffset == -1) {
        firstOffset = lastIndex;
      }
      lastIndex = endIndex;
    }
    return firstOffset;
  }
  protected JTextComponent comp;
  protected Highlighter.HighlightPainter painter;
}
class UnderlineHighlighter extends DefaultHighlighter {
  public UnderlineHighlighter(Color c) {
    painter = (c == null ? sharedPainter : new UnderlineHighlightPainter(c));
  }
  // Convenience method to add a highlight with
  // the default painter.
  public Object addHighlight(int p0, int p1) throws BadLocationException {
    return addHighlight(p0, p1, painter);
  }
  public void setDrawsLayeredHighlights(boolean newValue) {
    // Illegal if false - we only support layered highlights
    if (newValue == false) {
      throw new IllegalArgumentException(
          "UnderlineHighlighter only draws layered highlights");
    }
    super.setDrawsLayeredHighlights(true);
  }
  // Painter for underlined highlights
  public static class UnderlineHighlightPainter extends
      LayeredHighlighter.LayerPainter {
    public UnderlineHighlightPainter(Color c) {
      color = c;
    }
    public void paint(Graphics g, int offs0, int offs1, Shape bounds,
        JTextComponent c) {
      // Do nothing: this method will never be called
    }
    public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
        JTextComponent c, View view) {
      g.setColor(color == null ? c.getSelectionColor() : color);
      Rectangle alloc = null;
      if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
        if (bounds instanceof Rectangle) {
          alloc = (Rectangle) bounds;
        } else {
          alloc = bounds.getBounds();
        }
      } else {
        try {
          Shape shape = view.modelToView(offs0,
              Position.Bias.Forward, offs1,
              Position.Bias.Backward, bounds);
          alloc = (shape instanceof Rectangle) ? (Rectangle) shape
              : shape.getBounds();
        } catch (BadLocationException e) {
          return null;
        }
      }
      FontMetrics fm = c.getFontMetrics(c.getFont());
      int baseline = alloc.y + alloc.height - fm.getDescent() + 1;
      g.drawLine(alloc.x, baseline, alloc.x + alloc.width, baseline);
      g.drawLine(alloc.x, baseline + 1, alloc.x + alloc.width,
          baseline + 1);
      return alloc;
    }
    protected Color color; // The color for the underline
  }
  // Shared painter used for default highlighting
  protected static final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(
      null);
  // Painter used for this highlighter
  protected Highlighter.HighlightPainter painter;
}





JTextPane Styles Example 1

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample1 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 1");
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    JTextPane pane = new JTextPane(doc);
    // Create and add the style
    final Style heading2Style = sc.addStyle("Heading2", null);
    heading2Style.addAttribute(StyleConstants.Foreground, Color.red);
    heading2Style.addAttribute(StyleConstants.FontSize, new Integer(16));
    heading2Style.addAttribute(StyleConstants.FontFamily, "serif");
    heading2Style.addAttribute(StyleConstants.Bold, new Boolean(true));
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Add the text to the document
            doc.insertString(0, text, null);
            // Finally, apply the style to the heading
            doc.setParagraphAttributes(0, 1, heading2Style, false);
          } catch (BadLocationException e) {
          }
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = "Attributes, Styles and Style Contexts\n"
      + "The simple PlainDocument class that you saw in the previous "
      + "chapter is only capable of holding text. The more complex text "
      + "components use a more sophisticated model that implements the "
      + "StyledDocument interface. StyledDocument is a sub-interface of "
      + "Document that contains methods for manipulating attributes that "
      + "control the way in which the text in the document is displayed. "
      + "The Swing text package contains a concrete implementation of "
      + "StyledDocument called DefaultStyledDocument that is used as the "
      + "default model for JTextPane and is also the base class from which "
      + "more specific models, such as the HTMLDocument class that handles "
      + "input in HTML format, can be created. In order to make use of "
      + "DefaultStyledDocument and JTextPane, you need to understand how "
      + "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 2

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample2 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 2");
    
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    JTextPane pane = new JTextPane(doc);
    
    // Create and add the main document style
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    final Style mainStyle = sc.addStyle("MainStyle", defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    final Style cwStyle = sc.addStyle("ConstantWidth", null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    final Style heading2Style = sc.addStyle("Heading2", null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Set the logical style
            doc.setLogicalStyle(0, mainStyle);
            // Add the text to the document
            doc.insertString(0, text, null);
            // Apply the character attributes
            doc.setCharacterAttributes(49, 13, cwStyle, false);
            doc.setCharacterAttributes(223, 14, cwStyle, false);
            doc.setCharacterAttributes(249, 14, cwStyle, false);
            doc.setCharacterAttributes(286, 8, cwStyle, false);
            doc.setCharacterAttributes(475, 14, cwStyle, false);
            doc.setCharacterAttributes(497, 21, cwStyle, false);
            doc.setCharacterAttributes(557, 9, cwStyle, false);
            doc.setCharacterAttributes(639, 12, cwStyle, false);
            doc.setCharacterAttributes(733, 21, cwStyle, false);
            doc.setCharacterAttributes(759, 9, cwStyle, false);
            // Finally, apply the style to the heading
            doc.setParagraphAttributes(0, 1, heading2Style, false);
          } catch (BadLocationException e) {
          }
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = 
          "Attributes, Styles and Style Contexts\n" +
          "The simple PlainDocument class that you saw in the previous " + 
          "chapter is only capable of holding text. The more complex text " +
          "components use a more sophisticated model that implements the " +
          "StyledDocument interface. StyledDocument is a sub-interface of " +
          "Document that contains methods for manipulating attributes that " +
          "control the way in which the text in the document is displayed. " +
          "The Swing text package contains a concrete implementation of " +
          "StyledDocument called DefaultStyledDocument that is used as the " +
          "default model for JTextPane and is also the base class from which " +
          "more specific models, such as the HTMLDocument class that handles " +
          "input in HTML format, can be created. In order to make use of " +
          "DefaultStyledDocument and JTextPane, you need to understand how " +
          "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 3

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample3 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 3");
    
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    JTextPane pane = new JTextPane(doc);
    
    // Create and add the main document style
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    final Style mainStyle = sc.addStyle("MainStyle", defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Set the logical style
            doc.setLogicalStyle(0, mainStyle);
            // Add the text to the document
            doc.insertString(0, text, null);          
          } catch (BadLocationException e) {
          }
          doc.dump(System.out);
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = 
          "Attributes, Styles and Style Contexts\n" +
          "The simple PlainDocument class that you saw in the previous " + 
          "chapter is only capable of holding text. The more complex text " +
          "components use a more sophisticated model that implements the " +
          "StyledDocument interface. StyledDocument is a sub-interface of " +
          "Document that contains methods for manipulating attributes that " +
          "control the way in which the text in the document is displayed. " +
          "The Swing text package contains a concrete implementation of " +
          "StyledDocument called DefaultStyledDocument that is used as the " +
          "default model for JTextPane and is also the base class from which " +
          "more specific models, such as the HTMLDocument class that handles " +
          "input in HTML format, can be created. In order to make use of " +
          "DefaultStyledDocument and JTextPane, you need to understand how " +
          "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 4

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample4 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 4");
    
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    JTextPane pane = new JTextPane(doc);
    
    // Create and add the main document style
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    final Style mainStyle = sc.addStyle("MainStyle", defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Add the text to the document
            doc.insertString(0, text, null);
            
            // Set the logical style
            doc.setLogicalStyle(0, mainStyle);
          } catch (BadLocationException e) {
          }
          doc.dump(System.out);
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = 
          "Attributes, Styles and Style Contexts\n" +
          "The simple PlainDocument class that you saw in the previous " + 
          "chapter is only capable of holding text. The more complex text " +
          "components use a more sophisticated model that implements the " +
          "StyledDocument interface. StyledDocument is a sub-interface of " +
          "Document that contains methods for manipulating attributes that " +
          "control the way in which the text in the document is displayed. " +
          "The Swing text package contains a concrete implementation of " +
          "StyledDocument called DefaultStyledDocument that is used as the " +
          "default model for JTextPane and is also the base class from which " +
          "more specific models, such as the HTMLDocument class that handles " +
          "input in HTML format, can be created. In order to make use of " +
          "DefaultStyledDocument and JTextPane, you need to understand how " +
          "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 5

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample5 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 5");
    
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    
    // Create and add the style
    final Style heading2Style = sc.addStyle("Heading2", null);
    heading2Style.addAttribute(StyleConstants.Foreground, Color.red);
    heading2Style.addAttribute(StyleConstants.FontSize, new Integer(16));
    heading2Style.addAttribute(StyleConstants.FontFamily, "serif");
    heading2Style.addAttribute(StyleConstants.Bold, new Boolean(true));
    
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Add the text to the document
            doc.insertString(0, text, null);
            // Finally, apply the style to the heading
            doc.setParagraphAttributes(0, 1, heading2Style, false);
            // Set the foreground and font
            pane.setForeground(Color.blue);
            pane.setFont(new Font("serif", Font.PLAIN, 12));
          } catch (BadLocationException e) {
          }
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = 
          "Attributes, Styles and Style Contexts\n" +
          "The simple PlainDocument class that you saw in the previous " + 
          "chapter is only capable of holding text. The more complex text " +
          "components use a more sophisticated model that implements the " +
          "StyledDocument interface. StyledDocument is a sub-interface of " +
          "Document that contains methods for manipulating attributes that " +
          "control the way in which the text in the document is displayed. " +
          "The Swing text package contains a concrete implementation of " +
          "StyledDocument called DefaultStyledDocument that is used as the " +
          "default model for JTextPane and is also the base class from which " +
          "more specific models, such as the HTMLDocument class that handles " +
          "input in HTML format, can be created. In order to make use of " +
          "DefaultStyledDocument and JTextPane, you need to understand how " +
          "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 6

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample6 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 6");
    
    // Create the StyleContext, the document and the pane
    StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    
    // Create and add the main document style
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    final Style mainStyle = sc.addStyle("MainStyle", defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    final Style cwStyle = sc.addStyle("ConstantWidth", null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    final Style heading2Style = sc.addStyle("Heading2", null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            // Set the logical style
            doc.setLogicalStyle(0, mainStyle);
            // Add the text to the document
            doc.insertString(0, text, null);
            // Apply the character attributes
            doc.setCharacterAttributes(49, 13, cwStyle, false);
            doc.setCharacterAttributes(223, 14, cwStyle, false);
            doc.setCharacterAttributes(249, 14, cwStyle, false);
            doc.setCharacterAttributes(286, 8, cwStyle, false);
            doc.setCharacterAttributes(475, 14, cwStyle, false);
            doc.setCharacterAttributes(497, 21, cwStyle, false);
            doc.setCharacterAttributes(557, 9, cwStyle, false);
            doc.setCharacterAttributes(639, 12, cwStyle, false);
            doc.setCharacterAttributes(733, 21, cwStyle, false);
            doc.setCharacterAttributes(759, 9, cwStyle, false);
            // Finally, apply the style to the heading
            doc.setParagraphAttributes(0, 1, heading2Style, false);
            // Set the foreground color and change the font
            pane.setForeground(Color.pink);
            pane.setFont(new Font("Monospaced", Font.ITALIC, 24));
          } catch (BadLocationException e) {
          }
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  public static final String text = 
          "Attributes, Styles and Style Contexts\n" +
          "The simple PlainDocument class that you saw in the previous " + 
          "chapter is only capable of holding text. The more complex text " +
          "components use a more sophisticated model that implements the " +
          "StyledDocument interface. StyledDocument is a sub-interface of " +
          "Document that contains methods for manipulating attributes that " +
          "control the way in which the text in the document is displayed. " +
          "The Swing text package contains a concrete implementation of " +
          "StyledDocument called DefaultStyledDocument that is used as the " +
          "default model for JTextPane and is also the base class from which " +
          "more specific models, such as the HTMLDocument class that handles " +
          "input in HTML format, can be created. In order to make use of " +
          "DefaultStyledDocument and JTextPane, you need to understand how " +
          "Swing represents and uses attributes.\n";
}





JTextPane Styles Example 7

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample7 {  
  public static void createDocumentStyles(StyleContext sc) {  
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
  }
  public static void addText(JTextPane pane, StyleContext sc, Style logicalStyle,
                Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
          runs[j].styleName == null ? SimpleAttributeSet.EMPTY :
                  sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the 
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName), false);
      }
      
      pane.replaceSelection("\n");
    }    
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 7");
    
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    // Build the styles
    createDocumentStyles(sc);
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);            
        }
      });  
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(400, 300);
    f.setVisible(true);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
    new Paragraph(heading2StyleName, new Run[] {      
        new Run(null, "Attributes, Styles and Style Contexts")
    }),
    new Paragraph(null, new Run[] {
        new Run(null, "The simple "),
        new Run(charStyleName, "PlainDocument"),
        new Run(null, " class that you saw in the previous " +
              "chapter is only capable of holding text. " +
              "The more complex text components use a more " +
              "sophisticated model that implements the "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " interface. "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " is a sub-interface of "),
        new Run(charStyleName, "Document"),
        new Run(null, " that contains methods for manipulating attributes " +
                "that control the way in which the text in the " +
                "document is displayed. The Swing text package " +
                "contains a concrete implementation of "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " called "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " that is used as the default model for "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " and is also the base class from which " +
                "more specific models, such as the "),
        new Run(charStyleName, "HTMLDocument"),
        new Run(null, " class that handles input in HTML format, can be " +
                "created. In order to make use of "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " and "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " you need to understand how Swing represents " +
                "and uses attributes.")
    })
  };  
}





JTextPane Styles Example 8

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.net.URL;
public class StylesExample8 {  
  public static void createDocumentStyles(StyleContext sc) {  
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    // Create and add the Component style
    Class thisClass = StylesExample8.class;
    URL url = thisClass.getResource("jexp.gif");
    ImageIcon icon = new ImageIcon(url);
    JLabel comp = new JLabel("Displaying text with attributes",
                  icon, JLabel.CENTER);
    comp.setVerticalTextPosition(JLabel.BOTTOM);
    comp.setHorizontalTextPosition(JLabel.CENTER);
    comp.setFont(new Font("serif", Font.BOLD | Font.ITALIC, 14));
    Style componentStyle = sc.addStyle(componentStyleName, null);    
    StyleConstants.setComponent(componentStyle, comp);
    // The paragraph style for the component
    Style compParagraphStyle = sc.addStyle(compParaName, null);
    StyleConstants.setSpaceAbove(compParagraphStyle, (float)16.0);    
  }
  public static void addText(JTextPane pane, StyleContext sc, Style logicalStyle,
                Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
          runs[j].styleName == null ? SimpleAttributeSet.EMPTY :
                  sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the 
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName), false);
      }
      
      pane.replaceSelection("\n");
    }    
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Styles Example 8");
    
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    // Build the styles
    createDocumentStyles(sc);
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);            
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(500, 300);
    f.setVisible(true);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  public static final String componentStyleName = "Component";
  public static final String compParaName = "CompPara";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
    new Paragraph(heading2StyleName, new Run[] {      
        new Run(null, "Attributes, Styles and Style Contexts")
    }),
    new Paragraph(null, new Run[] {
        new Run(null, "The simple "),
        new Run(charStyleName, "PlainDocument"),
        new Run(null, " class that you saw in the previous " +
              "chapter is only capable of holding text. " +
              "The more complex text components use a more " +
              "sophisticated model that implements the "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " interface. "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " is a sub-interface of "),
        new Run(charStyleName, "Document"),
        new Run(null, " that contains methods for manipulating attributes " +
                "that control the way in which the text in the " +
                "document is displayed. The Swing text package " +
                "contains a concrete implementation of "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " called "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " that is used as the default model for "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " and is also the base class from which " +
                "more specific models, such as the "),
        new Run(charStyleName, "HTMLDocument"),
        new Run(null, " class that handles input in HTML format, can be " +
                "created. In order to make use of "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " and "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " you need to understand how Swing represents " +
                "and uses attributes.")
    }),
    new Paragraph(compParaName, new Run[] {
        new Run(componentStyleName, " ")
    })
  };  
}





List HTML Values

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.text.html.HTML;
public class ListHTMLValues {
  public static void main(String[] args) {
  
    HTML.Tag[] tags = HTML.getAllTags();
    HTML.Attribute[] attrs = HTML.getAllAttributeKeys();
    System.out.println("HTML Tags:");
    for (int i = 0; i < tags.length - 1; i++) {
      System.out.print(tags[i] + ", ");
      if ((i % 8) == 7) {
        System.out.println("");
      }
    }
    System.out.println(tags[tags.length - 1]);
    System.out.println("\n\nHTML Attributes:");
    for (int i = 0; i < attrs.length - 1; i++) {
      System.out.print(attrs[i] + ", ");
      if ((i % 8) == 7) {
        System.out.println("");
      }
    }
    System.out.println(attrs[attrs.length - 1]);
  }
}





Listing the Attributes in a Style

   
import java.util.Enumeration;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    DefaultStyledDocument doc = (DefaultStyledDocument) textPane.getDocument();
    Enumeration e1 = doc.getStyleNames();
    while (e1.hasMoreElements()) {
      String styleName = (String) e1.nextElement();
      System.out.println(styleName);
      Style style = doc.getStyle(styleName);
      int count = style.getAttributeCount();
      System.out.println(count);
      Enumeration e = style.getAttributeNames();
      while (e.hasMoreElements()) {
        Object o = e.nextElement();
        if (o instanceof String) {
          String attrName = (String) o;
          Object attrValue = style.getAttribute(attrName);
          System.out.println(attrValue);
        } else if (o == StyleConstants.NameAttribute) {
          styleName = (String) style.getAttribute(o);
          System.out.println(styleName);
        } else if (o == StyleConstants.ResolveAttribute) {
          Style parent = (Style) style.getAttribute(o);
          System.out.println(parent.getName());
        } else {
          String attrName = o.toString();
          System.out.println(attrName);
          Object attrValue = style.getAttribute(o);
          System.out.println(attrValue);
        }
      }
    }
  }
}





Listing the Styles Associated with a JTextPane

   
import java.util.Enumeration;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    
    DefaultStyledDocument doc = (DefaultStyledDocument) textPane.getDocument();
    Enumeration e = doc.getStyleNames();
    while (e.hasMoreElements()) {
      String styleName = (String) e.nextElement();
      System.out.println(styleName);
      Style style = doc.getStyle(styleName);
    }
  }
}





Parentheses matcher

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// ParenMatcher.java
//A simple parenthesis matcher.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class ParenMatcher extends JTextPane implements Runnable {
  public static Color[] matchColor = { Color.blue, Color.magenta, Color.green };
  public static Color badColor = Color.red;
  private AttributeSet[] matchAttrSet;
  private AttributeSet badAttrSet;
  public ParenMatcher() {
    // create an array of AttributeSets from the array of Colors
    StyleContext sc = StyleContext.getDefaultStyleContext();
    badAttrSet = sc.addAttribute(SimpleAttributeSet.EMPTY,
        StyleConstants.Foreground, badColor);
    matchAttrSet = new AttributeSet[matchColor.length];
    for (int j = 0; j < matchColor.length; j += 1)
      matchAttrSet[j] = sc.addAttribute(SimpleAttributeSet.EMPTY,
          StyleConstants.Foreground, matchColor[j]);
  }
  // match and color the parens/brackets/braces
  public void run() {
    StyledDocument doc = getStyledDocument();
    String text = "";
    int len = doc.getLength();
    try {
      text = doc.getText(0, len);
    } catch (BadLocationException ble) {
    }
    java.util.Stack stack = new java.util.Stack();
    for (int j = 0; j < text.length(); j += 1) {
      char ch = text.charAt(j);
      if (ch == "(" || ch == "[" || ch == "{") {
        int depth = stack.size();
        stack.push("" + ch + j); // push a String containg the char and
                     // the offset
        AttributeSet aset = matchAttrSet[depth % matchAttrSet.length];
        doc.setCharacterAttributes(j, 1, aset, false);
      }
      if (ch == ")" || ch == "]" || ch == "}") {
        String peek = stack.empty() ? "." : (String) stack.peek();
        if (matches(peek.charAt(0), ch)) { // does it match?
          stack.pop();
          int depth = stack.size();
          AttributeSet aset = matchAttrSet[depth
              % matchAttrSet.length];
          doc.setCharacterAttributes(j, 1, aset, false);
        } else { // mismatch
          doc.setCharacterAttributes(j, 1, badAttrSet, false);
        }
      }
    }
    while (!stack.empty()) { // anything left in the stack is a mismatch
      String pop = (String) stack.pop();
      int offset = Integer.parseInt(pop.substring(1));
      doc.setCharacterAttributes(offset, 1, badAttrSet, false);
    }
  }
  // unset the foreground color (if any) whenever the user enters text
  // (if not for this, text entered after a paren would catch the paren"s
  // color)
  public void replaceSelection(String content) {
    getInputAttributes().removeAttribute(StyleConstants.Foreground);
    super.replaceSelection(content);
  }
  // return true if "left" and "right" are matching parens/brackets/braces
  public static boolean matches(char left, char right) {
    if (left == "(")
      return (right == ")");
    if (left == "[")
      return (right == "]");
    if (left == "{")
      return (right == "}");
    return false;
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("ParenMatcher");
    final ParenMatcher matcher = new ParenMatcher();
    matcher.setText("int fact(int n) {\n" + "  if (n <= 1) return 1;\n"
        + "  return(n * fact(n-1));\n" + "}\n");
    frame.getContentPane().add(new JScrollPane(matcher),
        BorderLayout.CENTER);
    JButton matchButton = new JButton("match parens");
    matchButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        matcher.run();
      }
    });
    frame.getContentPane().add(matchButton, BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200, 150);
    frame.setVisible(true);
  }
}





Reads a AttributedString object that has been serialised by the SerialUtilities.writeAttributedString(AttributedString, ObjectOutputStream)} method.

  
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.util.HashMap;
import java.util.Map;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

public class Main {
  /**
   * Returns <code>true</code> if a class implements <code>Serializable</code>
   * and <code>false</code> otherwise.
   *
   * @param c  the class.
   *
   * @return A boolean.
   */
  public static boolean isSerializable(final Class c) {
      /**
      final Class[] interfaces = c.getInterfaces();
      for (int i = 0; i < interfaces.length; i++) {
          if (interfaces[i].equals(Serializable.class)) {
              return true;
          }
      }
      Class cc = c.getSuperclass();
      if (cc != null) {
          return isSerializable(cc);
      }
       */
      return (Serializable.class.isAssignableFrom(c));
  }

  /**
   * Reads a <code>AttributedString</code> object that has been serialised by
   * the {@link SerialUtilities#writeAttributedString(AttributedString,
   * ObjectOutputStream)} method.
   *
   * @param stream  the input stream (<code>null</code> not permitted).
   *
   * @return The attributed string object (possibly <code>null</code>).
   *
   * @throws IOException  if there is an I/O problem.
   * @throws ClassNotFoundException  if there is a problem loading a class.
   */
  public static AttributedString readAttributedString(
          ObjectInputStream stream)
          throws IOException, ClassNotFoundException {
      if (stream == null) {
          throw new IllegalArgumentException("Null "stream" argument.");
      }
      AttributedString result = null;
      final boolean isNull = stream.readBoolean();
      if (!isNull) {
          // read string and attributes then create result
          String plainStr = (String) stream.readObject();
          result = new AttributedString(plainStr);
          char c = stream.readChar();
          int start = 0;
          while (c != CharacterIterator.DONE) {
              int limit = stream.readInt();
              Map atts = (Map) stream.readObject();
              result.addAttributes(atts, start, limit);
              start = limit;
              c = stream.readChar();
          }
      }
      return result;
  }
  /**
   * Serialises an <code>AttributedString</code> object.
   *
   * @param as  the attributed string object (<code>null</code> permitted).
   * @param stream  the output stream (<code>null</code> not permitted).
   *
   * @throws IOException if there is an I/O error.
   */
  public static void writeAttributedString(AttributedString as,
          ObjectOutputStream stream) throws IOException {
      if (stream == null) {
          throw new IllegalArgumentException("Null "stream" argument.");
      }
      if (as != null) {
          stream.writeBoolean(false);
          AttributedCharacterIterator aci = as.getIterator();
          // build a plain string from aci
          // then write the string
          StringBuffer plainStr = new StringBuffer();
          char current = aci.first();
          while (current != CharacterIterator.DONE) {
              plainStr = plainStr.append(current);
              current = aci.next();
          }
          stream.writeObject(plainStr.toString());
          // then write the attributes and limits for each run
          current = aci.first();
          int begin = aci.getBeginIndex();
          while (current != CharacterIterator.DONE) {
              // write the current character - when the reader sees that this
              // is not CharacterIterator.DONE, it will know to read the
              // run limits and attributes
              stream.writeChar(current);
              // now write the limit, adjusted as if beginIndex is zero
              int limit = aci.getRunLimit();
              stream.writeInt(limit - begin);
              // now write the attribute set
              Map atts = new HashMap(aci.getAttributes());
              stream.writeObject(atts);
              current = aci.setIndex(limit);
          }
          // write a character that signals to the reader that all runs
          // are done...
          stream.writeChar(CharacterIterator.DONE);
      }
      else {
          // write a flag that indicates a null
          stream.writeBoolean(true);
      }
  }
}





Replace style

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    Style style = textPane.addStyle(null, null);
    StyleConstants.setForeground(style, Color.red);
    textPane.setLogicalStyle(style);
    
    // Set paragraph style; removes logical style
    style = textPane.addStyle(null, null);
    StyleConstants.setUnderline(style, true);
    textPane.setParagraphAttributes(style, true);
    // paragraph is now underlined, not red
  }
}





Set logical style; replaces paragraph style"s parent

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    Style style = textPane.addStyle(null, null);
    StyleConstants.setForeground(style, Color.red);
    textPane.setLogicalStyle(style);
    style = textPane.addStyle(null, null);
    StyleConstants.setForeground(style, Color.red);
    textPane.setLogicalStyle(style);
  }
}





Sharing Styles Between JTextPanes

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane c1 = new JTextPane();
    JTextPane c2 = new JTextPane();
    StyleContext styleContext = new StyleContext();
    c1.setDocument(new DefaultStyledDocument(styleContext));
    c2.setDocument(new DefaultStyledDocument(styleContext));
    Style style = c1.addStyle("style name", null);
    StyleConstants.setForeground(style, Color.red);
    style = c2.getStyle("style name");
    StyleConstants.setBold(style, true);
  }
}





Show how Icons, Components, and text can be added to a JTextPane

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// PaneInsertionMethods.java
//Show how Icons, Components, and text can be added to a JTextPane.
//
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
public class PaneInsertionMethods {
  public static void main(String[] args) {
    final JTextPane pane = new JTextPane();
    // button to insert some text
    JButton textButton = new JButton("Insert Text");
    textButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        pane.replaceSelection("text");
      }
    });
    // button to insert an icon
    final ImageIcon icon = new ImageIcon("bluepaw.gif");
    JButton iconButton = new JButton(icon);
    iconButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        pane.insertIcon(icon);
      }
    });
    // button to insert a button
    JButton buttonButton = new JButton("Insert Button");
    buttonButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        pane.insertComponent(new JButton("Click Me"));
      }
    });
    // layout
    JPanel buttons = new JPanel();
    buttons.add(textButton);
    buttons.add(iconButton);
    buttons.add(buttonButton);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(pane, BorderLayout.CENTER);
    frame.getContentPane().add(buttons, BorderLayout.SOUTH);
    frame.setSize(360, 180);
    frame.setVisible(true);
  }
}





Show HTML Document

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.PrintStream;
import java.util.Enumeration;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
public class ShowHTMLDocument {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    try {
      JFrame f = new JFrame("HTMLDocument Structure");
      final JEditorPane ep = new JEditorPane("links1.html");
      ep.setEditable(false);
      f.getContentPane().add(new JScrollPane(ep));
      f.setSize(400, 300);
      f.setVisible(true);
      ep.addPropertyChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          if (evt.getPropertyName().equals("page")) {
            HTMLDocDisplay.displayModel(ep, System.out);
          }
        }
      });
    } catch (Exception e) {
      System.out.println(e);
      System.exit(1);
    }
  }
}
class HTMLDocDisplay {
  public static void displayAttributes(AttributeSet a, int indent,
      PrintStream out) {
    if (a == null)
      return;
    a = a.copyAttributes();
    Enumeration x = a.getAttributeNames();
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    if (x != null) {
      out.println("ATTRIBUTES:");
      while (x.hasMoreElements()) {
        for (int i = 0; i < indent; i++) {
          out.print("  ");
        }
        Object attr = x.nextElement();
        out.println(" (" + attr + ", " + a.getAttribute(attr) + ")"
            + " [" + getShortClassName(attr.getClass()) + "/"
            + getShortClassName(a.getAttribute(attr).getClass())
            + "] ");
      }
    } else {
      out.println("No attributes");
    }
    if (a.getResolveParent() != null) {
      displayAttributes(a.getResolveParent().copyAttributes(),
          indent + 1, out);
    }
  }
  public static void displayModel(JTextComponent comp, PrintStream out) {
    Document doc = comp.getDocument();
    Element e = doc.getDefaultRootElement();
    displayElement(doc, e, 0, out);
  }
  public static void displayElement(Document doc, Element e, int indent,
      PrintStream out) {
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    out.println("===== Element Class: " + getShortClassName(e.getClass()));
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    int startOffset = e.getStartOffset();
    int endOffset = e.getEndOffset();
    out.println("Offsets [" + startOffset + ", " + endOffset + "]");
    AttributeSet a = e.getAttributes();
    Enumeration x = a.getAttributeNames();
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    out.println("ATTRIBUTES:");
    while (x.hasMoreElements()) {
      for (int i = 0; i < indent; i++) {
        out.print("  ");
      }
      Object attr = x.nextElement();
      out
          .println(" ("
              + attr
              + ", "
              + a.getAttribute(attr)
              + ")"
              + " ["
              + getShortClassName(attr.getClass())
              + "/"
              + getShortClassName(a.getAttribute(attr).getClass())
              + "] ");
    }
    // Display the text for a leaf element
    if (e.isLeaf()) {
      try {
        String str = doc.getText(startOffset, endOffset - startOffset);
        if (str.length() > 40) {
          str = str.substring(0, 40);
        }
        if (str.length() > 0) {
          for (int i = 0; i < indent; i++) {
            out.print("  ");
          }
          out.println("[" + str + "]");
        }
      } catch (BadLocationException ex) {
      }
    }
    // Display child elements
    int count = e.getElementCount();
    for (int i = 0; i < count; i++) {
      displayElement(doc, e.getElement(i), indent + 1, out);
    }
  }
  public static String getShortClassName(Class clazz) {
    String className = clazz.getName();
    return className.substring(className.lastIndexOf(".") + 1);
  }
}





Show HTML Views

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.PrintStream;
import java.util.Enumeration;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
public class ShowHTMLViews {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    try {
      JFrame f = new JFrame("HTML Document View Structure");
      final JEditorPane ep = new JEditorPane(args[0]);
      ep.setEditable(false);
      f.getContentPane().add(new JScrollPane(ep));
      f.setSize(400, 300);
      f.setVisible(true);
      ep.addPropertyChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          if (evt.getPropertyName().equals("page")) {
            System.out.println("Document:\n");
            HTMLDocDisplay.displayModel(ep, System.out);
            System.out.println("\n\nViews:\n");
            HTMLViewDisplayer.displayViews(ep, System.out);
          }
        }
      });
    } catch (Exception e) {
      System.out.println(e);
      System.exit(1);
    }
  }
}
class HTMLDocDisplay {
  public static void displayAttributes(AttributeSet a, int indent,
      PrintStream out) {
    if (a == null)
      return;
    a = a.copyAttributes();
    Enumeration x = a.getAttributeNames();
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    if (x != null) {
      out.println("ATTRIBUTES:");
      while (x.hasMoreElements()) {
        for (int i = 0; i < indent; i++) {
          out.print("  ");
        }
        Object attr = x.nextElement();
        out.println(" (" + attr + ", " + a.getAttribute(attr) + ")"
            + " [" + getShortClassName(attr.getClass()) + "/"
            + getShortClassName(a.getAttribute(attr).getClass())
            + "] ");
      }
    } else {
      out.println("No attributes");
    }
    if (a.getResolveParent() != null) {
      displayAttributes(a.getResolveParent().copyAttributes(),
          indent + 1, out);
    }
  }
  public static void displayModel(JTextComponent comp, PrintStream out) {
    Document doc = comp.getDocument();
    Element e = doc.getDefaultRootElement();
    displayElement(doc, e, 0, out);
  }
  public static void displayElement(Document doc, Element e, int indent,
      PrintStream out) {
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    out.println("===== Element Class: " + getShortClassName(e.getClass()));
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    int startOffset = e.getStartOffset();
    int endOffset = e.getEndOffset();
    out.println("Offsets [" + startOffset + ", " + endOffset + "]");
    AttributeSet a = e.getAttributes();
    Enumeration x = a.getAttributeNames();
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    out.println("ATTRIBUTES:");
    while (x.hasMoreElements()) {
      for (int i = 0; i < indent; i++) {
        out.print("  ");
      }
      Object attr = x.nextElement();
      out
          .println(" ("
              + attr
              + ", "
              + a.getAttribute(attr)
              + ")"
              + " ["
              + getShortClassName(attr.getClass())
              + "/"
              + getShortClassName(a.getAttribute(attr).getClass())
              + "] ");
    }
    // Display the text for a leaf element
    if (e.isLeaf()) {
      try {
        String str = doc.getText(startOffset, endOffset - startOffset);
        if (str.length() > 40) {
          str = str.substring(0, 40);
        }
        if (str.length() > 0) {
          for (int i = 0; i < indent; i++) {
            out.print("  ");
          }
          out.println("[" + str + "]");
        }
      } catch (BadLocationException ex) {
      }
    }
    // Display child elements
    int count = e.getElementCount();
    for (int i = 0; i < count; i++) {
      displayElement(doc, e.getElement(i), indent + 1, out);
    }
  }
  public static String getShortClassName(Class clazz) {
    String className = clazz.getName();
    return className.substring(className.lastIndexOf(".") + 1);
  }
}
class HTMLViewDisplayer {
  public static void displayViews(JTextComponent comp, PrintStream out) {
    View rootView = comp.getUI().getRootView(comp);
    displayView(rootView, 0, comp.getDocument(), out);
  }
  public static void displayView(View view, int indent, Document doc,
      PrintStream out) {
    String name = view.getClass().getName();
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    int start = view.getStartOffset();
    int end = view.getEndOffset();
    out.println(name + "; offsets [" + start + ", " + end + "]");
    for (int i = 0; i < indent; i++) {
      out.print("  ");
    }
    HTMLDocDisplay.displayAttributes(view.getAttributes(), indent, out);
    int viewCount = view.getViewCount();
    if (viewCount == 0) {
      int length = Math.min(32, end - start);
      try {
        String txt = doc.getText(start, length);
        for (int i = 0; i < indent + 1; i++) {
          out.print("  ");
        }
        out.println("[" + txt + "]");
      } catch (BadLocationException e) {
      }
    } else {
      for (int i = 0; i < viewCount; i++) {
        displayView(view.getView(i), indent + 1, doc, out);
      }
    }
    out.println("");
  }
}





Styled Text

   
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class StyledText {
  public static void main(String args[]) throws BadLocationException {
    JFrame jf = new JFrame("StyledText");
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container cp = jf.getContentPane();
    JTextPane pane = new JTextPane();
    SimpleAttributeSet set = new SimpleAttributeSet();
    StyleConstants.setBold(set, true);
    // Set the attributes before adding text
    pane.setCharacterAttributes(set, true);
    pane.setText("Eine ");
    set = new SimpleAttributeSet();
    StyleConstants.setItalic(set, true);
    StyleConstants.setForeground(set, Color.red);
    StyleConstants.setBackground(set, Color.blue);
    Document doc = pane.getStyledDocument();
    doc.insertString(doc.getLength(), "Kleine ", set);
    set = new SimpleAttributeSet();
    StyleConstants.setFontSize(set, 24);
    doc.insertString(doc.getLength(), "Nachtmusic", set);
    JScrollPane scrollPane = new JScrollPane(pane);
    cp.add(scrollPane, BorderLayout.CENTER);
    jf.setSize(400, 300);
    jf.setVisible(true);
  }
}





Tests two attributed strings for equality.

 
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------------------------
 * AttributedStringUtilities.java
 * ------------------------------
 * (C)opyright 2005, by Object Refinery Limited and Contributors.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: AttributedStringUtilities.java,v 1.2 2005/10/18 13:24:19 mungady Exp $
 *
 * Changes
 * -------
 * 29-Jul-2005 : Version 1(DG);
 * 
 */
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.util.Map;
/**
 * Some utility methods for working with <code>AttributedString</code>
 * objects.
 * 
 * @author David Gilbert
 */
public class AttributedStringUtilities {
  /**
   * Tests two attributed strings for equality.
   * 
   * @param s1
   *          string 1 (<code>null</code> permitted).
   * @param s2
   *          string 2 (<code>null</code> permitted).
   * 
   * @return <code>true</code> if <code>s1</code> and <code>s2</code> are
   *         equal or both <code>null</code>, and <code>false</code>
   *         otherwise.
   */
  public static boolean equal(AttributedString s1, AttributedString s2) {
    if (s1 == null) {
      return (s2 == null);
    }
    if (s2 == null) {
      return false;
    }
    AttributedCharacterIterator it1 = s1.getIterator();
    AttributedCharacterIterator it2 = s2.getIterator();
    char c1 = it1.first();
    char c2 = it2.first();
    int start = 0;
    while (c1 != CharacterIterator.DONE) {
      int limit1 = it1.getRunLimit();
      int limit2 = it2.getRunLimit();
      if (limit1 != limit2) {
        return false;
      }
      // if maps aren"t equivalent, return false
      Map m1 = it1.getAttributes();
      Map m2 = it2.getAttributes();
      if (!m1.equals(m2)) {
        return false;
      }
      // now check characters in the run are the same
      for (int i = start; i < limit1; i++) {
        if (c1 != c2) {
          return false;
        }
        c1 = it1.next();
        c2 = it2.next();
      }
      start = limit1;
    }
    return c2 == CharacterIterator.DONE;
  }
}





Text Component Display

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.UIManager;
import javax.swing.text.*;
import javax.swing.plaf.*;
import java.io.*;
public class TextComponentDisplay {
  public static void displayModel(JTextComponent comp, 
                  PrintStream out) {
    Document doc = comp.getDocument();
    if (doc instanceof AbstractDocument) {
      ((AbstractDocument)doc).dump(out);
    }
  }
  public static void displayViews(JTextComponent comp,
                  PrintStream out) {
    TextUI textUI = (TextUI)comp.getUI();
    View rootView = textUI.getRootView(comp);
    displayView(rootView, 0, out);
  }
  public static void displayView(View view, int tabs,
                  PrintStream out) {
    // Print info about this view
    for (int i = 0; i < tabs; i++) {
      out.print("\t");
    }
    out.println(view.getClass().getName());
    for (int i = 0; i < tabs; i++) {
      out.print("\t");
    }
    out.println("Start: " + view.getStartOffset() + 
            "; end: " + view.getEndOffset());
    // Display child views, if any.
    int childViews = view.getViewCount();
    for (int i = 0; i < childViews ; i++) {
      View childView = view.getView(i);
      displayView(childView, tabs + 1, out);
    }
  }
}





TextPane: DocumentEvent

   
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// LiveParenMatcher.java
//Like ParenMatcher but continuously colors as the user edits the document.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.Segment;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class LiveParenMatcher extends ParenMatcher implements DocumentListener {
  public LiveParenMatcher() {
    super();
    getDocument().addDocumentListener(this);
  }
  public void changedUpdate(DocumentEvent de) {
    // no insertion or deletion, so do nothing
  }
  public void insertUpdate(DocumentEvent de) {
    SwingUtilities.invokeLater(this); // will call run()
  }
  public void removeUpdate(DocumentEvent de) {
    SwingUtilities.invokeLater(this); // will call run()
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("LiveParenMatcher");
    frame.setContentPane(new JScrollPane(new LiveParenMatcher()));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 200);
    frame.setVisible(true);
  }
  // ---- finished example from "The DocumentListener Interface" ----
  // ---- begin example from "The DocumentEvent Interface" ----
  //      (method renamed to insertUpdate_2)
  public void insertUpdate_2(DocumentEvent de) {
    Document doc = de.getDocument();
    int offset = de.getOffset();
    int length = de.getLength();
    String inserted = "";
    try {
      inserted = doc.getText(offset, length);
    } catch (BadLocationException ble) {
    }
    for (int j = 0; j < inserted.length(); j += 1) {
      char ch = inserted.charAt(j);
      if (ch == "(" || ch == "[" || ch == "{" || ch == ")" || ch == "]"
          || ch == "}") {
        SwingUtilities.invokeLater(this); // will call run()
        return; // no need to check further
      }
    }
  }
  // ---- begin example from "The Segment Class" ----
  //      (method renamed to insertUpdate_3)
  public void insertUpdate_3(DocumentEvent de) {
    Document doc = de.getDocument();
    int offset = de.getOffset();
    int length = de.getLength();
    Segment seg = new Segment();
    try {
      doc.getText(offset, length, seg); // text placed in Segment
    } catch (BadLocationException ble) {
    }
    // iterate through the Segment
    for (char ch = seg.first(); ch != seg.DONE; ch = seg.next())
      if (ch == "(" || ch == "[" || ch == "{" || ch == ")" || ch == "]"
          || ch == "}") {
        SwingUtilities.invokeLater(this); // will call run()
        return; // no need to check further
      }
  }
  // ---- begin example from "The ElementIterator Class" ----
  //      (method renamed to removeUpdate_2)
  public void removeUpdate_2(DocumentEvent de) {
    // print some debugging information before matching the parens
    ElementIterator iter = new ElementIterator(de.getDocument());
    for (Element elem = iter.first(); elem != null; elem = iter.next()) {
      DocumentEvent.ElementChange change = de.getChange(elem);
      if (change != null) { // null means there was no change in elem
        System.out.println("Element " + elem.getName() + " (depth "
            + iter.depth() + ") changed its children: "
            + change.getChildrenRemoved().length
            + " children removed, "
            + change.getChildrenAdded().length
            + " children added.\n");
      }
    }
    SwingUtilities.invokeLater(this); // will call run()
  }
}
class ParenMatcher extends JTextPane implements Runnable {
  public static Color[] matchColor = { Color.blue, Color.magenta, Color.green };
  public static Color badColor = Color.red;
  private AttributeSet[] matchAttrSet;
  private AttributeSet badAttrSet;
  public ParenMatcher() {
    // create an array of AttributeSets from the array of Colors
    StyleContext sc = StyleContext.getDefaultStyleContext();
    badAttrSet = sc.addAttribute(SimpleAttributeSet.EMPTY,
        StyleConstants.Foreground, badColor);
    matchAttrSet = new AttributeSet[matchColor.length];
    for (int j = 0; j < matchColor.length; j += 1)
      matchAttrSet[j] = sc.addAttribute(SimpleAttributeSet.EMPTY,
          StyleConstants.Foreground, matchColor[j]);
  }
  // match and color the parens/brackets/braces
  public void run() {
    StyledDocument doc = getStyledDocument();
    String text = "";
    int len = doc.getLength();
    try {
      text = doc.getText(0, len);
    } catch (BadLocationException ble) {
    }
    java.util.Stack stack = new java.util.Stack();
    for (int j = 0; j < text.length(); j += 1) {
      char ch = text.charAt(j);
      if (ch == "(" || ch == "[" || ch == "{") {
        int depth = stack.size();
        stack.push("" + ch + j); // push a String containg the char and
        // the offset
        AttributeSet aset = matchAttrSet[depth % matchAttrSet.length];
        doc.setCharacterAttributes(j, 1, aset, false);
      }
      if (ch == ")" || ch == "]" || ch == "}") {
        String peek = stack.empty() ? "." : (String) stack.peek();
        if (matches(peek.charAt(0), ch)) { // does it match?
          stack.pop();
          int depth = stack.size();
          AttributeSet aset = matchAttrSet[depth
              % matchAttrSet.length];
          doc.setCharacterAttributes(j, 1, aset, false);
        } else { // mismatch
          doc.setCharacterAttributes(j, 1, badAttrSet, false);
        }
      }
    }
    while (!stack.empty()) { // anything left in the stack is a mismatch
      String pop = (String) stack.pop();
      int offset = Integer.parseInt(pop.substring(1));
      doc.setCharacterAttributes(offset, 1, badAttrSet, false);
    }
  }
  // unset the foreground color (if any) whenever the user enters text
  // (if not for this, text entered after a paren would catch the paren"s
  // color)
  public void replaceSelection(String content) {
    getInputAttributes().removeAttribute(StyleConstants.Foreground);
    super.replaceSelection(content);
  }
  // return true if "left" and "right" are matching parens/brackets/braces
  public static boolean matches(char left, char right) {
    if (left == "(")
      return (right == ")");
    if (left == "[")
      return (right == "]");
    if (left == "{")
      return (right == "}");
    return false;
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("ParenMatcher");
    final ParenMatcher matcher = new ParenMatcher();
    matcher.setText("int fact(int n) {\n" + "  if (n <= 1) return 1;\n"
        + "  return(n * fact(n-1));\n" + "}\n");
    frame.getContentPane().add(new JScrollPane(matcher),
        BorderLayout.CENTER);
    JButton matchButton = new JButton("match parens");
    matchButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        matcher.run();
      }
    });
    frame.getContentPane().add(matchButton, BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200, 150);
    frame.setVisible(true);
  }
}





TextPane Elements

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.net.URL;
public class TextPaneElements {  
  public static void createDocumentStyles(StyleContext sc) {  
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    // Create and add the Component style
    Class thisClass = TextPaneElements.class;
    URL url = thisClass.getResource("jexp.gif");
    ImageIcon icon = new ImageIcon(url);
    JLabel comp = new JLabel("Displaying text with attributes",
                  icon, JLabel.CENTER);
    comp.setVerticalTextPosition(JLabel.BOTTOM);
    comp.setHorizontalTextPosition(JLabel.CENTER);
    comp.setFont(new Font("serif", Font.BOLD | Font.ITALIC, 14));
    Style componentStyle = sc.addStyle(componentStyleName, null);    
    StyleConstants.setComponent(componentStyle, comp);
    // The paragraph style for the component
    Style compParagraphStyle = sc.addStyle(compParaName, null);
    StyleConstants.setSpaceAbove(compParagraphStyle, (float)16.0);    
  }
  public static void addText(JTextPane pane, StyleContext sc, Style logicalStyle,
                Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
          runs[j].styleName == null ? SimpleAttributeSet.EMPTY :
                  sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the 
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName), false);
      }
      
      pane.replaceSelection("\n");
    }    
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Text Pane Elements");
    
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    // Build the styles
    createDocumentStyles(sc);
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);  
          
          // Dump the element structure
          ((AbstractDocument)pane.getDocument()).dump(System.out);
        }
      });  
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(500, 300);
    f.setVisible(true);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  public static final String componentStyleName = "Component";
  public static final String compParaName = "CompPara";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
    new Paragraph(heading2StyleName, new Run[] {      
        new Run(null, "Attributes, Styles and Style Contexts")
    }),
    new Paragraph(null, new Run[] {
        new Run(null, "The simple "),
        new Run(charStyleName, "PlainDocument"),
        new Run(null, " class that you saw in the previous " +
              "chapter is only capable of holding text. " +
              "The more complex text components use a more " +
              "sophisticated model that implements the "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " interface. "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " is a sub-interface of "),
        new Run(charStyleName, "Document"),
        new Run(null, " that contains methods for manipulating attributes " +
                "that control the way in which the text in the " +
                "document is displayed. The Swing text package " +
                "contains a concrete implementation of "),
        new Run(charStyleName, "StyledDocument"),
        new Run(null, " called "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " that is used as the default model for "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " and is also the base class from which " +
                "more specific models, such as the "),
        new Run(charStyleName, "HTMLDocument"),
        new Run(null, " class that handles input in HTML format, can be " +
                "created. In order to make use of "),
        new Run(charStyleName, "DefaultStyledDocument"),
        new Run(null, " and "),
        new Run(charStyleName, "JTextPane"),
        new Run(null, " you need to understand how Swing represents " +
                "and uses attributes.")
    }),
    new Paragraph(compParaName, new Run[] {
        new Run(componentStyleName, " ")
    })
  };  
}





TextPane Sample

   
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class TextPaneSample {
  private static String message = "In the beginning, there was COBOL, then there was FORTRAN, "
      + "then there was BASIC, ... and now there is Java.\n";
  public static void main(String args[]) {
    String title = (args.length == 0 ? "TextPane Example" : args[0]);
    JFrame frame = new JFrame(title);
    Container content = frame.getContentPane();
    StyleContext context = new StyleContext();
    StyledDocument document = new DefaultStyledDocument(context);
    Style style = context.getStyle(StyleContext.DEFAULT_STYLE);
    StyleConstants.setAlignment(style, StyleConstants.ALIGN_RIGHT);
    StyleConstants.setFontSize(style, 14);
    StyleConstants.setSpaceAbove(style, 4);
    StyleConstants.setSpaceBelow(style, 4);
    // Insert content
    try {
      document.insertString(document.getLength(), message, style);
    } catch (BadLocationException badLocationException) {
      System.err.println("Oops");
    }
    SimpleAttributeSet attributes = new SimpleAttributeSet();
    StyleConstants.setBold(attributes, true);
    StyleConstants.setItalic(attributes, true);
    // Insert content
    try {
      document.insertString(document.getLength(), "Hello Java",
          attributes);
    } catch (BadLocationException badLocationException) {
      System.err.println("Oops");
    }
    // Third style for icon/component
    Style labelStyle = context.getStyle(StyleContext.DEFAULT_STYLE);
    Icon icon = new ImageIcon("Computer.gif");
    JLabel label = new JLabel(icon);
    StyleConstants.setComponent(labelStyle, label);
    // Insert content
    try {
      document.insertString(document.getLength(), "Ignored", labelStyle);
    } catch (BadLocationException badLocationException) {
      System.err.println("Oops");
    }
    JTextPane textPane = new JTextPane(document);
    textPane.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(textPane);
    content.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





TextPane Views 2

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Font;
import java.io.PrintStream;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.View;
public class TextPaneViews {
  public static void createDocumentStyles(StyleContext sc) {
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    // Create and add the Component style
    Class thisClass = TextPaneViews.class;
    URL url = thisClass.getResource("jexp.gif");
    ImageIcon icon = new ImageIcon(url);
    JLabel comp = new JLabel("Displaying text with attributes", icon,
        JLabel.CENTER);
    comp.setVerticalTextPosition(JLabel.BOTTOM);
    comp.setHorizontalTextPosition(JLabel.CENTER);
    comp.setFont(new Font("serif", Font.BOLD | Font.ITALIC, 14));
    Style componentStyle = sc.addStyle(componentStyleName, null);
    StyleConstants.setComponent(componentStyle, comp);
    // The paragraph style for the component
    Style compParagraphStyle = sc.addStyle(compParaName, null);
    StyleConstants.setSpaceAbove(compParagraphStyle, (float) 16.0);
  }
  public static void addText(JTextPane pane, StyleContext sc,
      Style logicalStyle, Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
            runs[j].styleName == null ? SimpleAttributeSet.EMPTY
                : sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName),
            false);
      }
      pane.replaceSelection("\n");
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Text Pane Views");
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    // Build the styles
    createDocumentStyles(sc);
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    f.getContentPane().add(new JScrollPane(pane));
    f.setSize(500, 300);
    f.setVisible(true);
    try {
      // Dump the view structure
      Thread.sleep(30000);
      ViewDisplayer.displayViews(pane, System.out);
    } catch (InterruptedException e) {
    }
    System.out.flush();
    System.exit(0);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  public static final String componentStyleName = "Component";
  public static final String compParaName = "CompPara";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
      new Paragraph(heading2StyleName, new Run[] { new Run(null,
          "Attributes, Styles and Style Contexts") }),
      new Paragraph(
          null,
          new Run[] {
              new Run(null, "The simple "),
              new Run(charStyleName, "PlainDocument"),
              new Run(
                  null,
                  " class that you saw in the previous "
                      + "chapter is only capable of holding text. "
                      + "The more complex text components use a more "
                      + "sophisticated model that implements the "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " interface. "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " is a sub-interface of "),
              new Run(charStyleName, "Document"),
              new Run(
                  null,
                  " that contains methods for manipulating attributes "
                      + "that control the way in which the text in the "
                      + "document is displayed. The Swing text package "
                      + "contains a concrete implementation of "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " called "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null,
                  " that is used as the default model for "),
              new Run(charStyleName, "JTextPane"),
              new Run(
                  null,
                  " and is also the base class from which "
                      + "more specific models, such as the "),
              new Run(charStyleName, "HTMLDocument"),
              new Run(
                  null,
                  " class that handles input in HTML format, can be "
                      + "created. In order to make use of "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null, " and "),
              new Run(charStyleName, "JTextPane"),
              new Run(null,
                  " you need to understand how Swing represents "
                      + "and uses attributes.") }),
      new Paragraph(compParaName, new Run[] { new Run(componentStyleName,
          " ") }) };
}
class ViewDisplayer {
  public static void displayViews(JTextComponent comp, PrintStream out) {
    View rootView = comp.getUI().getRootView(comp);
    displayView(rootView, 0, comp.getDocument(), out);
  }
  public static void displayView(View view, int indent, Document doc,
      PrintStream out) {
    String name = view.getClass().getName();
    for (int i = 0; i < indent; i++) {
      out.print("\t");
    }
    int start = view.getStartOffset();
    int end = view.getEndOffset();
    out.println(name + "; offsets [" + start + ", " + end + "]");
    int viewCount = view.getViewCount();
    if (viewCount == 0) {
      int length = Math.min(32, end - start);
      try {
        String txt = doc.getText(start, length);
        for (int i = 0; i < indent + 1; i++) {
          out.print("\t");
        }
        out.println("[" + txt + "]");
      } catch (BadLocationException e) {
      }
    } else {
      for (int i = 0; i < viewCount; i++) {
        displayView(view.getView(i), indent + 1, doc, out);
      }
    }
  }
}