/******************************************************************************* * Copyright 2015 Maximilian Stark | Dakror <mail@dakror.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package de.dakror.arise.ui; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.Element; /* * A class to control the maximum number of lines to be stored in a Document * Excess lines can be removed from the start or end of the Document * depending on your requirement. * a) if you append text to the Document, then you would want to remove lines * from the start. * b) if you insert text at the beginning of the Document, then you would * want to remove lines from the end. */ public class LimitLinesDocumentListener implements DocumentListener { private int maximumLines; private boolean isRemoveFromStart; /* * Specify the number of lines to be stored in the Document. * Extra lines will be removed from the start of the Document. */ public LimitLinesDocumentListener(int maximumLines) { this(maximumLines, true); } /* * Specify the number of lines to be stored in the Document. * Extra lines will be removed from the start or end of the Document, * depending on the boolean value specified. */ public LimitLinesDocumentListener(int maximumLines, boolean isRemoveFromStart) { setLimitLines(maximumLines); this.isRemoveFromStart = isRemoveFromStart; } /* * Return the maximum number of lines to be stored in the Document */ public int getLimitLines() { return maximumLines; } /* * Set the maximum number of lines to be stored in the Document */ public void setLimitLines(int maximumLines) { if (maximumLines < 1) { String message = "Maximum lines must be greater than 0"; throw new IllegalArgumentException(message); } this.maximumLines = maximumLines; } // Handle insertion of new text into the Document @Override public void insertUpdate(final DocumentEvent e) { // Changes to the Document can not be done within the listener // so we need to add the processing to the end of the EDT SwingUtilities.invokeLater(new Runnable() { @Override public void run() { removeLines(e); } }); } @Override public void removeUpdate(DocumentEvent e) {} @Override public void changedUpdate(DocumentEvent e) {} /* * Remove lines from the Document when necessary */ private void removeLines(DocumentEvent e) { // The root Element of the Document will tell us the total number // of line in the Document. Document document = e.getDocument(); Element root = document.getDefaultRootElement(); while (root.getElementCount() > maximumLines) { if (isRemoveFromStart) { removeFromStart(document, root); } else { removeFromEnd(document, root); } } } /* * Remove lines from the start of the Document */ private void removeFromStart(Document document, Element root) { Element line = root.getElement(0); int end = line.getEndOffset(); try { document.remove(0, end); } catch (BadLocationException ble) { System.out.println(ble); } } /* * Remove lines from the end of the Document */ private void removeFromEnd(Document document, Element root) { // We use start minus 1 to make sure we remove the newline // character of the previous line Element line = root.getElement(root.getElementCount() - 1); int start = line.getStartOffset(); int end = line.getEndOffset(); try { document.remove(start - 1, end - start); } catch (BadLocationException ble) { System.out.println(ble); } } }