Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

Swing Chapter 20. (Advanced topics) Constructing a Word Processor. Easy for reading, Click here!

Custom Search
Swing Chapter 20. (Advanced topics) Constructing a Word Processor. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 4/9 



Previous Page Previous Page (3/9) - Next Page (5/9) Next Page
Subpages: 1. Word Processor: part I - Introducing RTF
2. Word Processor: part II - Managing fonts
3. Word Processor: part III - Colors and images
4. Word Processor: part IV - Working with styles
5. Word Processor: part V - Clipboard and undo/redo
6. Word Processor: part VI - Advanced font mangement
7. Word Processor: part VII - Paragraph formatting
8. Word Processor: part VIII - Find and replace
9. Word Processor: part IX - Spell checker [using JDBC and SQL]

20.4  Word Processor: part IV - Working with styles

Using Styles to manage a set of attributes as a single named entity can greatly simplify text editing. The user only has to apply a known style to a selected region of text rather than selecting all appropriate text attributes from the provided toolbar components. By adding a combo box allowing the choice of styles, we can not only save the user time and effort, but we can also provide more uniform text formatting throughout the resulting document (or potentially set of documents). In this section we'll add style management to our word processor. We'll also show how it is possible to create a new style, modify an existing style, or reapply a style to modified text.

Figure 20.4 RTF word processor application with Styles management.

<<file figure20-4.gif>>

The Code: WordProcessor.java

see \Chapter20\4

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.util.*;

import javax.swing.*;

import javax.swing.text.*;

import javax.swing.event.*;

import javax.swing.border.*;

import javax.swing.text.rtf.*;

public class WordProcessor extends JFrame

{

  // Unchanged code from section 20.3

  protected JComboBox m_cbStyles;

  public WordProcessor() {

    // Unchanged code from section 20.3

    showAttributes(0);

    showStyles();

    setVisible(true);

  }

  protected JMenuBar createMenuBar() {

    // Unchanged code from section 20.3

    // The following line is added to the end of the

    // actionNew and actionOpen actionPerformed() methods:

    //

    //   showStyles();

    //

    // (see source code; these methods are not shown here

    //  to conserve space)

    // Unchanged code from section 20.3

    JMenu mFormat = new JMenu("Format");

    mFormat.setMnemonic('o');

    JMenu mStyle = new JMenu("Style");

    mStyle.setMnemonic('s');

    mFormat.add(mStyle);

    item = new JMenuItem("Update");

    item.setMnemonic('u');

    lst = new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        String name = (String)m_cbStyles.getSelectedItem();

        Style style = m_doc.getStyle(name);

        int p = m_monitor.getCaretPosition();

        AttributeSet a = m_doc.getCharacterElement(p).

          getAttributes();

        style.addAttributes(a);

        m_monitor.repaint();

      }

    };

    item.addActionListener(lst);

    mStyle.add(item);

    item = new JMenuItem("Reapply");

    item.setMnemonic('r');

    lst = new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        String name = (String)m_cbStyles.getSelectedItem();

        Style style = m_doc.getStyle(name);

        setAttributeSet(style);

      }

    };

    item.addActionListener(lst);

    mStyle.add(item);

    mFormat.addSeparator();

    // Unchanged code from section 20.3

    menuBar.add(mFormat);

    m_toolBar.addSeparator();

    m_cbStyles = new JComboBox();

    m_cbStyles.setMaximumSize(m_cbStyles.getPreferredSize());

    m_cbStyles.setEditable(true);

    m_toolBar.add(m_cbStyles);

    lst = new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        if (m_skipUpdate || m_cbStyles.getItemCount()==0)

          return;

        String name = (String)m_cbStyles.getSelectedItem();

        int index = m_cbStyles.getSelectedIndex();

        int p = m_monitor.getCaretPosition();

        // New name entered

        if (index == -1) {

          m_cbStyles.addItem(name);

          Style style = m_doc.addStyle(name, null);

          AttributeSet a = m_doc.getCharacterElement(p).

            getAttributes();

          style.addAttributes(a);

          return;

        }

        // Apply the selected style

        Style currStyle = m_doc.getLogicalStyle(p);

        if (!currStyle.getName().equals(name)) {

          Style style = m_doc.getStyle(name);

          setAttributeSet(style);

        }

      }

    };

    m_cbStyles.addActionListener(lst);

    getContentPane().add(m_toolBar, BorderLayout.NORTH);

    return menuBar;

  }

  protected void showAttributes(int p) {

    // Unchanged code from section 20.2

    Style style = m_doc.getLogicalStyle(p);

    name = style.getName();

    m_cbStyles.setSelectedItem(name);

    m_skipUpdate = false;

  }

  // Unchanged code from section 20.3

  protected void showStyles() {

    m_skipUpdate = true;

    if (m_cbStyles.getItemCount() > 0)

      m_cbStyles.removeAllItems();

    Enumeration en = m_doc.getStyleNames();

    while (en.hasMoreElements()) {

      String str = en.nextElement().toString();

      m_cbStyles.addItem(str);

    }

    m_skipUpdate = false;

  }

  public static void main(String argv[]) {

    new WordProcessor();

  }

}

// Unchanged code from section 20.3

Understanding the Code

Class WordProcessor

One new instance variable has been added:

JComboBox m_cbStyles: toolbar component to manage styles.

Note that a new custom method showStyles() (see below) is now called after creating a new document or after loading an existing one.

The createMenuBar() method creates a new menu with two new menu items for updating and reapplying styles, and a new combo box for style selection. The editable styles combobox, m_cbStyles, will hold a list of styles declared in the current document (we will see how this component is populated below). It receives an ActionListener which checks whether the currently selected style name is present among the existing styles. If not, we add it to the drop-down list and retrieve a new Style instance for the selected name using StyledDocument's addStyle() method. This new Style instance is associated with the text attributes of the character element at the current caret position. Otherwise, if the given style name is known already, we retrieve the selected style using StyledDocument's getStyle() method and apply it to the selected text by passing it to our custom setAttributeSet() method (as we did in previous examples when assigning text attributes).

An ambiguous situation occurs when the user selects a style for text which already has the same style, but whose attributes have been modified. The user may either want to update the selected style using the selected text as a base, or reapply the existing style to the selected text. To resolve this situation we need to ask the user what to do. We chose to add two menu items which allow the user to either update or reapply the current selection.

Note: In ambiguous situations such as this, making the decision to allow users to choose between two options, or enforcing a single behavior, can be a tough one to make. In general, the less experienced the target audience is, the less choices that audience should need to become familiar with. In this case we would suggest that a selected style override all attributes of the selected text.

The menu items to perform these tasks are titled "Update" and "Reapply," and are grouped into the "Style" menu. The "Style" menu is added to the "Format" menu. The "Update" menu item receives an ActionListener which retrieves the text attributes of the character element at the current caret position, and assigns them to the selected style. The "Reapply" menu item receives an ActionListener which applies the selected style to the selected text (one might argue that this menu item would be more appropriately  titled "Apply" -- the implications are ambiguous either way).

Our showAttributes() method receives additional code to manage the new styles combobox, m_cbStyles, when the caret moves through the document. It retrieves the style corresponding to the current caret position with StyledDocument's getLogicalStyle() method, and selects the appropriate entry in the combobox.

The new showStyles() method is called to populate the m_cbStyles combobox with the style names from a newly created or loaded document. First it removes the current content of the combobox if it is not empty (another work around due to the fact that if you call removeAllItems() on an empty JComboBox, an exception will be thrown). An Enumeration of style names is then retrieved with StyledDocument's getStyleNames() method, and these names are added to the combobox.

Running the Code

Open an existing RTF file, and note how the styles combobox is populated by the style names defined in this document. Verify that the selected style is automatically updated while the caret moves through the document. Select a portion of text and select a different style from the styles combobox. Note how all text properties are updated according to the new style.

Try selecting a portion of text and modifying its attributes (for instance, foreground color). Type a new name in the styles combobox and press Enter. This will create a new style which can be applied to any other document text.

Note: New styles will not be saved along with an RTF document under the current version of RTFEditorKit.

Try modifying an attribute of a selected region of text (e.g. the font size) and select the "Style|Update" menu item. This will update the style to incorporate the newly selected attributes. Apply the modified style to another portion of text and verify that it applies according to the updated style.

Note: When a style is updated, any regions of text that had been applied with this style do not automatically get updated accordingly. This is another ambiguity that must be considered, depending on what the user expects and what level or experience the target audience has. In this case we assume that the user only wants selected text to be affected by a style update.

Now try modifying some attributes of a portion of selected text and then select the "Style|Reapply" menu item. This will restore the original text attributes associated with the appropriate style.

Note: Recall that we are using one StyleContext instance, m_context, for all documents. This object collects all document styles. These styles are always available when a new document is created or loaded. We might develop a document template mechanism by serializing this StyleContext instance into a file and restoring it with the appropriate document.



[ Return to Swing (Book) ]


Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color


[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3


[ More in News Section ]


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy