Search code examples
javajeditorpanedocumentlistenerhtmleditorkithtmldocumentclass

Get changed content in DocumentEvent


The goal:
Working with a JEditorPane and HTMLDocuments I need to react to the removal of images, i.e. Elements defined by <img>..</img> tags.

What I tried:
For now I use DocumentListeners to react to DocumentEvents which are fired upon changes to a document. Unfortunately, DocumentEvents do not directly contain information about the changed content, so I can't identify what kind of element has been removed. It seems all I can do is iterate over all Elements of the document and call the events getChange(Element).

document.addDocumentListener(new DocumentListener() {

    @Override
    public void removeUpdate(DocumentEvent arg0) {
        ElementIterator iter = new ElementIterator(document);
        Element element;
        while ((element=iter.next()) != null) {
            ElementChange change = arg0.getChange(element);
            if (change != null) {                   
                Element[] children = change.getChildrenRemoved();
                for (Element child : children) {
                    Object name = child.getAttributes().getAttribute(StyleConstants.NameAttribute);
                    System.out.println((HTML.Tag)name);                     
                    }
                }               
            }
            notifyContentChanged();
        }
    });
}

Although this solution works partially (sometimes when deleting an image the sysout reports a p-implied instead of a img) I would really appreciate other solutions. Probably, someone knows a simple way of getting the String associated with a change in the document?

SOLUTION
In accordance to the accepted answer, the following code demonstrates the use of DocumentFilters as Listeners (for image removal in this case).

document.setDocumentFilter(new DocumentFilter() {
        @Override
        public void remove(FilterBypass fb, int offset, int length)
                throws BadLocationException {
            if (document.getCharacterElement(offset).getName().equals(HTML.Tag.IMG.toString())) {
                .
                .   
            }
            super.remove(fb, offset, length);
        }
    });

Solution

  • DocumentEvent has getOffset() and getLength() methods. Normally images are leaves so you can use htmlDocument.getCharacterElement() from the range of change and check whether they are images.

    UPDATE: as result of discusing in commetns

    You can add a DocumentFilter overriding remove() and use it as listener to get deleted fragment (in fact fragment to-be-deleted).