This is a strange one. I copied the code from my ap into the runable sample below. I can select a portion of text and then click the "Bold" button and the selected text gets turned to bold. Now if I select the bold text and click the bold button again, nothing happens. HOWEVER, if I select ANY portion of the bold text except for the very last character then I can unbold it.
If I ever select the very last character of a bolded section it will not unbold the section. So I am always left with one character that I can not unbold.
Any ideas what I'm doing wrong. (The relevant code from my real ap is what is inside the boldButton ActionListener)
BTW: I'm a relative newbie to Java.
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.border.*;
import java.awt.*; //for layout managers and more
import java.awt.event.*; //for action events
public class Bolder extends JPanel
{
private String newline = System.getProperty("line.separator");
private JTextPane textPane;
private JLabel label;
private JPanel parent;
private JComponent dragging = null;
private int mOffsetX, mOffsetY;
public Bolder() {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
JToolBar toolBar = buildToolbar();
add(toolBar);
parent = new JPanel();
add(parent);
parent.setBackground( Color.white);
parent.setPreferredSize(new Dimension(640, 480));
// Create a text pane.
textPane = createTextPane();
textPane.setBounds(0, 0, 100, 100);
Border myBorder = BorderFactory.createLineBorder( Color.red );
textPane.setBorder(myBorder);
parent.add(textPane);
}
private JTextPane createTextPane() {
String[] initString =
{ "This is some sample text ",
"including some bold ",
"That can be used for testing purposes."+newline+"If you bold a piece of text"+
" then it cannot be unbolded entirely. All but the last character can be unbolded."+newline+
"A most peculiar phenomenon."
};
String[] initStyles =
{ "regular", "bold", "regular" };
JTextPane textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
addStylesToDocument(doc);
try {
for (int i=0; i < initString.length; i++) {
doc.insertString(doc.getLength(), initString,
doc.getStyle(initStyles[i]));
}
}
catch (BadLocationException ble) {
System.err.println("Couldn't insert initial text into text pane.");
}
return textPane;
}
protected void addStylesToDocument(StyledDocument doc) {
// Initialize some styles.
Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
Style regular = doc.addStyle("regular", def);
StyleConstants.setFontFamily(def, "SansSerif");
Style s = doc.addStyle("italic", regular);
StyleConstants.setItalic(s, true);
s = doc.addStyle("bold", regular);
StyleConstants.setBold(s, true);
s = doc.addStyle("small", regular);
StyleConstants.setFontSize(s, 10);
s = doc.addStyle("large", regular);
StyleConstants.setFontSize(s, 16);
}
private JToolBar buildToolbar() {
JToolBar toolBar = new JToolBar();
toolBar.setRollover( true );
toolBar.setFloatable( false );
JButton boldButton = new JButton("Bold");
boldButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
AttributeSet current = textPane.getCharacterAttributes();
if (current==null) {
// if no currently selected text, apply bold to anything typed in the future
// at this location.
current = textPane.getInputAttributes();
}
MutableAttributeSet attr = new SimpleAttributeSet();
boolean bold = false;
if (current.getAttribute(StyleConstants.Bold)!=null) {
bold = (current.getAttribute(StyleConstants.Bold).toString()=="true") ? true : false;
}
if (bold) {
StyleConstants.setBold(attr, false);
} else {
StyleConstants.setBold(attr,true);
}
textPane.setCharacterAttributes(attr, false);
}
});
toolBar.add( boldButton );
return toolBar;
}
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("Bolder");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new Bolder();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}