Channels ▼

Eric Bruno

Dr. Dobb's Bloggers

A JavaFX File Editor: Part 2

November 27, 2012

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);        

Fileopen

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:

  1. Mark a file as modified, placing an "*" at the end of the Tab name
  2. 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:

  1. The Scene's KeyPressed event
  2. The Scene's KeyReleased 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.

App

Happy coding!
-EJB

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video