I am trying to implement user selectable text alignment in an html document produced in Java. I have tried:
JMenuItem leftAlignMenuItem =
new JMenuItem(new StyledEditorKit.AlignmentAction("Left Align", StyleConstants.ALIGN_LEFT));
JMenuItem centerMenuItem =
new JMenuItem(new StyledEditorKit.AlignmentAction("Center", StyleConstants.ALIGN_CENTER));
JMenuItem rightAlignMenuItem =
new JMenuItem(new StyledEditorKit.AlignmentAction("Right Align", StyleConstants.ALIGN_RIGHT));
and various variations on this theme. Selecting the menu items causes the text to align correctly in the text pane, and adds the appropriate html tag to the document that is saved. The problem is, once the tag is added, clicking another align menu item doesn't change it, so it is not possible to change the text alignment from the default (left) more than once and save the change.
I know I'm not the first person to have this problem but I haven't found any solutions so far, so any help would be most appreciated.
Here is my "M"CVE, which unfortunately is still massive, but I can't remove any more code or it will not demonstrate the problem:
package aligntest;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.JFrame;
public class AlignTest extends JFrame implements ActionListener {
private HTMLDocument doc; // Stores the formatted text.
private JTextPane textPane = new JTextPane(); // The Pane itself.
String FilePath = ""; // Stores the file path.
public AlignTest() { // This method is called automatically when the app is launched.
HTMLEditorKit editorKit = new HTMLEditorKit();
doc = (HTMLDocument)editorKit.createDefaultDocument();
init(); // Calls interface method below.
}
public static void main(String[] args) {
AlignTest editor = new AlignTest();
}
public void init(){
JMenuBar menuBar = new JMenuBar();
getContentPane().add(menuBar, BorderLayout.NORTH);
JMenu fileMenu = new JMenu("File");
JMenu alignMenu = new JMenu("Text Align");
menuBar.add(fileMenu);
menuBar.add(alignMenu);
JMenuItem openItem = new JMenuItem("Open"); //
JMenuItem saveItem = new JMenuItem("Save"); //
openItem.addActionListener(this);
saveItem.addActionListener(this);
fileMenu.add(openItem);
fileMenu.add(saveItem);
JMenuItem leftAlignMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction("Left Align", StyleConstants.ALIGN_LEFT));
JMenuItem centerMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction("Center", StyleConstants.ALIGN_CENTER));
JMenuItem rightAlignMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction("Right Align", StyleConstants.ALIGN_RIGHT));
leftAlignMenuItem.setText("Left");
centerMenuItem.setText("Center");
rightAlignMenuItem.setText("Right");
alignMenu.add(leftAlignMenuItem);
alignMenu.add(centerMenuItem);
alignMenu.add(rightAlignMenuItem);
textPane = new JTextPane(doc); // Create object from doc and set this as value of textPane.
textPane.setContentType("text/html"); // textPane holds html.
JScrollPane scrollPane = new JScrollPane(textPane); // textPane in JScrollPane to allow scrolling if more text than space.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // Get screen size to use below.
Dimension scrollPaneSize = new Dimension(1*screenSize.width/2,1*screenSize.height/2); // Together with next line, sets dimensions of textPane relative to screen size.
scrollPane.setPreferredSize(scrollPaneSize);
getContentPane().add(scrollPane, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
show(); // Actually displays the interface.
}
public void actionPerformed(ActionEvent ae) { // Method called with action commands from interface objects above. Which action depends on the text of the interface element.
String actionCommand = ae.getActionCommand();
if (actionCommand.compareTo("Open") == 0){ // Calls method when action command received.
openDocument();
} else if (actionCommand.compareTo("Save") == 0){
saveDocument();
}
}
public void saveDocument(){
String FP = FilePath; // This paragraph calls Save As instead of Save if file not already saved.
String unsaved = "";
int saved = FP.compareTo(unsaved);
if (saved == 0) {
saveDocumentAs();
} else {
save();
}
}
public void saveDocumentAs(){
JFileChooser SaveDialog = new javax.swing.JFileChooser();
int returnVal = SaveDialog.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
java.io.File saved_file = SaveDialog.getSelectedFile();
FilePath = saved_file.toString();
save();
}
}
public void save(){
try {
WriteFile objPane = new WriteFile(FilePath, false);
String PaneText = textPane.getText(); // Gets text from Title Pane.
objPane.writeToFile(PaneText);
}
catch (Exception ex) {
}
}
public void openDocument(){
JFileChooser OpenDialog = new javax.swing.JFileChooser(); // Creates file chooser object.
int returnVal = OpenDialog.showOpenDialog(this); // Defines 'returnVal' according to what user clicks in file chooser.
if (returnVal == JFileChooser.APPROVE_OPTION) { // Returns value depending on whether user clicks 'yes' or 'OK' etc.
java.io.File file = OpenDialog.getSelectedFile(); // Gets path of selected file.
FilePath = file.toString( ); // Converts path of selected file to String.
// The problem seems to be related to the code that starts here...
try {
ReadFile readPane = new ReadFile(FilePath); // Creates "readPane" object from "FilePath" string, using my ReadFile class.
String[] aryPane = readPane.OpenFile(); // Creates string array "aryPane" from "readPane" object.
int i; // Creates integer variable "i".
String PaneText = "";
for (i=0; i < aryPane.length; i++) { // Creates a for loop with starting "i" value of 0, adding 1 to i each time round and ending when i = the number of lines in the aryLines array.
PaneText = PaneText + aryPane[i]; // Add present line to "PaneText".
}
textPane.setText(PaneText); // Displays "PaneText" in "TextPane".
} catch (Exception ex) {
// and ends here. This code also calls ReadFile, so code in that class may be at fault.
}
}
}
}
It also has to call methods in the following two classes in order to work:
package aligntest;
import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
public class ReadFile {
private String path;
public ReadFile(String file_path) {
path = file_path;
}
public String[] OpenFile() throws IOException {
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines( );
String[] textData = new String[numberOfLines];
int i;
for (i=0; i < numberOfLines; i++) {
textData[i] = textReader.readLine();
}
textReader.close( );
return textData;
}
int readLines() throws IOException {
FileReader file_to_read = new FileReader(path);
BufferedReader bf = new BufferedReader(file_to_read);
String aLine;
int numberOfLines = 0;
while ((aLine = bf.readLine()) != null) {
numberOfLines++;
}
bf.close();
return numberOfLines;
}
}
&
package aligntest;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class WriteFile {
private String path;
private boolean append_to_file = false;
public WriteFile(String file_path) {
path = file_path;
}
public WriteFile(String file_path, boolean append_value) {
path = file_path;
}
public WriteFile(File SectionPath, boolean success) {
throw new UnsupportedOperationException("Not yet implemented");
}
public void writeToFile( String textLine ) throws IOException {
FileWriter write = new FileWriter(path, append_to_file);
PrintWriter print_line = new PrintWriter(write);
print_line.printf( "%s" + "%n" , textLine);
print_line.close();
}
}
The problem appears to be related to opening the document (lines 126 - 138), or the 'ReadFile' class: when viewing the saved file in another program I can see that the tags are changing until the document is closed and then opened again with 'AlignTest'. After this any alignment changes are not reflected in the html.
Hoping someone can help.
Edit: Here is some html produced by 'AlignTest'. If this is pasted into a text file and then opened in 'AlignTest' it should reproduce the problem: 'AlignTest' is unable to change the align tag.
<html>
<head>
<meta id="_moz_html_fragment">
</head>
<body>
<p align="right" style="margin-top: 0pt">
Another
</p>
</body>
</html>