0

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);
        }
    });
Johnson
  • 306
  • 1
  • 15

1 Answers1

0

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

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • Unfortunately, this doesn't help in the context of the above listener. The default implementation of the HTMLDocument calls the listener **after** the change to the document has been performed. Which means, deleting the `e` from the content string `test`, looking at the offset/length will point you at the `s` instead of the `e`. – Johnson Jan 26 '15 at 17:24
  • Then you can add a DocumentFilter overriding remove() and use it as listener to get deleted fragment. – StanislavL Jan 27 '15 at 05:37
  • Shame on me, working a lot with SWT lately, I seem to become too focused on using existent Listener interfaces. I had already thought about using DocumentFilters but didn't follow this path because it felt like a workaround and overcomplicated for such an elementary task. In fact, in my case it's more or less a "one-liner". If you would add the advice of your comment to your answer or create a new answer with it, I would love to accept the answer, thanks. – Johnson Jan 27 '15 at 12:02