A JavaFX File Editor: Part 2
WebView
component, the simple file editor itself, and keyboard processing.
The Simple Editor Control
The editor itself is perhaps the simplest component in this sample application. It's represented by a class, SimpleEditor
, that encapsulates a TextArea
control, a flag to indicate that the content has been modified since it was last saved, and the filename used to load/save the content.
public class SimpleEditor implements Content { public boolean modified = false; public TextArea textArea = new TextArea(); public String filename = null; public boolean isModified() { return modified; } public void setModified(boolean modified) { this.modified = modified; } public TextArea getRoot() { return textArea; } public void setText(String text) { textArea.setText(text); } public String getText() { return textArea.getText(); } }
First, to load a file into the editor within a Tab
, we use the JavaFX FileChooser
class, which is very straightforward:
FileChooser fc = new FileChooser(); File fileToOpen = fc.showOpenDialog(null); String openFileName = fileToOpen.getAbsolutePath();
Next, the content of the file is loaded, set in a SimpleEditor
component, and placed within a tab:
// Create the editor with this content and store it SimpleEditor editor = new SimpleEditor(); editor.setText( sb.toString() ); editor.filename = openFileName; editors.add(editor); // Create a tab to house the new editor Tab tab = new Tab(); tab.setText(fileToOpen.getName()); tab.setContent(editor.getRoot()); tabPane.getTabs().add(tab);
Saving a file also uses the FileChooser
class, which allows the user to navigate the filesystem and enter a filename to save the editor content:
FileChooser fc = new FileChooser(); File newFile = fc.showSaveDialog(null);
Next, the content is written to the file, using try-with-resources, and the Tab
's title text is set to the file's name:
// Write the content to the file try ( FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos) ) { String text = editor.getText(); bos.write(text.getBytes()); bos.flush(); success = true; } catch ( Exception e ) { success = false; } finally { if ( success ) { if ( editor != null ) { editor.modified = false; } selectedTab.setText(file.getName()); } }
Handling Keyboard Input
The application needs to track certain types of keyboard input to do one of two things:
- Mark a file as modified, placing an "*" at the end of the
Tab
name - Save the file when the Ctrl-S (or Command-S on a Mac) key combination is pressed
Complicating matters, some special keys need to be tracked, such as backspace, delete, and enter, to also mark the content as modified. This processing is done in the method handleKeyPress
:
private void handleKeyPress(KeyEvent ke) { boolean modifier = false; String text = ke.getText(); KeyCode code = ke.getCode(); if ( ke.isControlDown() || ke.isMetaDown() ) { modifier = true; } if ( modifier && text.equalsIgnoreCase("s") ) { saveFileRev(); ignoreNextPress = true; } else if ( ! ignoreNextPress ) { if ( code == KeyCode.BACK_SPACE || code == KeyCode.ENTER || code == KeyCode.DELETE ) { indicateFileModified(); } else if ( text != null && text.length() > 0 ) { if ( ! modifier ) { indicateFileModified(); } } } }
This method is called in one of two places:
- The
Scene
'sKeyPressed
event - The
Scene
'sKeyReleased
event
The reason for this is that some events only come through as "pressed" events (such as the important CONTROL
and COMMAND
keys), while the rest come through as "released" events.
scene.setOnKeyPressed(new EventHandler<KeyEvent>() { public void handle(KeyEvent ke) { handleKeyPress(ke); } });
Conclusion
As this application shows, JavaFX makes even seemingly difficult tasks easy. Combined with some of Java 7's improvements (i.e., try-with-resources), JavaFX makes for a great client application programming solution. You can download the complete source code with NetBeans project for the simple file editor application here.
Happy coding!
-EJB