/* * Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.antlr.netbeans.editor.commenting; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.text.BadLocationException; import org.antlr.netbeans.editor.DocumentPoint; import org.antlr.netbeans.editor.DocumentSpan; import org.antlr.netbeans.editor.TextEdit; import org.netbeans.editor.BaseDocument; import org.openide.util.Parameters; /** * * @author Sam Harwell */ class TextEditImpl implements TextEdit { // -J-Dorg.antlr.netbeans.editor.commenting.TextEditImpl.level=FINE private static final Logger LOGGER = Logger.getLogger(TextEditImpl.class.getName()); final BaseDocument document; private final List<Change> changes = new ArrayList<>(); public TextEditImpl(BaseDocument document) { Parameters.notNull("document", document); this.document = document; } @Override public boolean apply() { Collections.sort(changes, new Comparator<Change>() { @Override public int compare(Change o1, Change o2) { return o1.offset - o2.offset; } }); document.runAtomicAsUser(new Runnable() { @Override public void run() { for (int i = changes.size() - 1; i >= 0; i--) { Change change = changes.get(i); try { if (change.length > 0) { document.remove(change.offset, change.length); } if (change.newText != null && !change.newText.isEmpty()) { document.insertString(change.offset, change.newText, null); } } catch (BadLocationException ex) { LOGGER.log(Level.WARNING, "An exception occurred while applying text changes.", ex); } } } }); return true; } @Override public void dispose() { } @Override public boolean remove(DocumentSpan span) { Change change = new Change(span.getStart().getOffset(), span.getLength(), null); if (!canAdd(change)) { return false; } changes.add(change); return true; } @Override public boolean remove(int startPosition, int length) { Change change = new Change(startPosition, length, null); if (!canAdd(change)) { return false; } changes.add(change); return true; } @Override public boolean insert(DocumentPoint point, String text) { if (text == null || text.isEmpty()) { return true; } Change change = new Change(point.getOffset(), 0, text); if (!canAdd(change)) { return false; } changes.add(change); return true; } @Override public boolean insert(int position, String text) { if (text == null || text.isEmpty()) { return true; } Change change = new Change(position, 0, text); if (!canAdd(change)) { return false; } changes.add(change); return true; } private boolean canAdd(Change change) { for (Change existing : changes) { if (change.overlaps(existing)) { return false; } } return true; } private static class Change { public int offset; public int length; public String newText; public Change(int offset, int length, String newText) { this.offset = offset; this.length = length; this.newText = newText; } public boolean overlaps(Change other) { Parameters.notNull("other", other); if (offset > other.offset + other.length) { return false; } if (other.offset > offset + length) { return false; } return true; } } }