/* * BufferSet.java - An ordered list of buffers. * :tabSize=4:indentSize=4:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2008, 2010 Matthieu Casanova * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit.bufferset; //{{{ Imports import org.gjt.sp.jedit.Buffer; import org.gjt.sp.jedit.jEdit; import org.gjt.sp.util.Log; import org.gjt.sp.util.StandardUtilities; import javax.swing.event.EventListenerList; import java.util.List; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import javax.annotation.Nullable; //}}} /** An ordered list of buffers, normally attached to an EditPane * and viewed in a BufferSwitcher. * * @author Matthieu Casanova * @since jEdit 4.3pre15 */ public class BufferSet { /** Possible scopes for BufferSets. */ public enum Scope { editpane, view, global } //{{{ BufferSet constructor public BufferSet(BufferSet source) { if (source == null) buffers = Collections.synchronizedList(new ArrayList<Buffer>()); else buffers = Collections.synchronizedList(new ArrayList<Buffer>(source.buffers)); listeners = new EventListenerList(); if (jEdit.getBooleanProperty("sortBuffers")) { if (jEdit.getBooleanProperty("sortByName")) sorter = nameSorter; else sorter = pathSorter; } }//}}} //{{{ addBuffer() method /** * Internal use only, use * {@link org.gjt.sp.jedit.bufferset.BufferSetManager#addBuffer(org.gjt.sp.jedit.View, org.gjt.sp.jedit.Buffer)} * or * {@link org.gjt.sp.jedit.bufferset.BufferSetManager#addBuffer(org.gjt.sp.jedit.EditPane, org.gjt.sp.jedit.Buffer)} * @param buffer the buffer to be added */ public void addBuffer(Buffer buffer) { addBufferAt(buffer, -1); } //}}} //{{{ addBufferAt() method /** * Internal use only, use * {@link org.gjt.sp.jedit.bufferset.BufferSetManager#addBuffer(org.gjt.sp.jedit.View, org.gjt.sp.jedit.Buffer)} * or * {@link org.gjt.sp.jedit.bufferset.BufferSetManager#addBuffer(org.gjt.sp.jedit.EditPane, org.gjt.sp.jedit.Buffer)} * @param buffer the buffer to be added * @param position the position where it must be added or -1 if we don't care */ public void addBufferAt(Buffer buffer, int position) { Log.log(Log.DEBUG, this, hashCode() + " addBufferAt("+buffer+','+position+')'); Buffer untitledBuffer = null; synchronized (buffers) { if (buffers.size() == 1) { Buffer buf = buffers.get(0); if (buf.isUntitled() && !buf.isDirty()) { untitledBuffer = buf; } } if (sorter != null) { if (buffers.contains(buffer)) return; buffers.add(buffer); Collections.sort(buffers, sorter); position = buffers.indexOf(buffer); } else { int oldPos = buffers.indexOf(buffer); if (oldPos != -1) { if (position == -1) { return; } moveBuffer(oldPos, position); return; } int size = buffers.size(); if (position == -1 || position > size) { position = size; } buffers.add(position, buffer); } } BufferSetListener[] listeners = this.listeners.getListeners(BufferSetListener.class); Log.log(Log.DEBUG, this, hashCode() + ": Buffer added " + buffer + " at " + position); for (BufferSetListener listener : listeners) { listener.bufferAdded(buffer, position); } // I don't like this reverse control if (untitledBuffer != null) { jEdit.getBufferSetManager().removeBuffer(this, untitledBuffer); } } //}}} //{{{ getBuffer() method /** * Returns the Buffer at the given index. * @param index the index. The index must exists * @return the buffer at the index. */ public Buffer getBuffer(int index) { return buffers.get(index); } //}}} //{{{ getSorter() /** @return the Comparator used for this bufferset can be null if there is no sorting @since jEdit 5.2 */ @Nullable public Comparator<Buffer> getSorter() { return sorter; }//}}} //{{{ getPreviousBuffer() method public Buffer getPreviousBuffer(int index) { if (buffers.isEmpty()) return null; if (buffers.size() < 2) return buffers.get(0); if (index <= 0) return buffers.get(buffers.size() - 1); return buffers.get(index - 1); } //}}} //{{{ getNextBuffer() method public Buffer getNextBuffer(int index) { if (buffers.isEmpty()) return null; if (buffers.size() < 2) return buffers.get(buffers.size()-1); if (index >= buffers.size() - 1) return buffers.get(0); return buffers.get(index + 1); } //}}} //{{{ indexOf() method public int indexOf(Buffer buffer) { return buffers.indexOf(buffer); } //}}} //{{{ size() method public int size() { return buffers.size(); } //}}} //{{{ getAllBuffers() methods public void getAllBuffers(BufferSetListener listener) { synchronized (buffers) { for (int i = 0;i<buffers.size();i++) { Buffer buffer = buffers.get(i); Log.log(Log.DEBUG, this, hashCode() + ": Buffer added " + buffer + " at " + i); listener.bufferAdded(buffer, i); } } } /** * Returns an array of all buffers in this bufferSet. * * @return an array of all Buffers */ public Buffer[] getAllBuffers() { Buffer[] buffers = new Buffer[this.buffers.size()]; return this.buffers.toArray(buffers); } //}}} //{{{ addBufferSetListener() method /** * Add a BufferSetListener. * @param listener the new BufferSetListener */ public void addBufferSetListener(BufferSetListener listener) { Log.log(Log.DEBUG, this, hashCode() + ": addBufferSetListener " + listener); listeners.add(BufferSetListener.class, listener); } //}}} //{{{ removeBufferSetListener() method /** * Remove a BufferSetListener. * If there are no listeners anymore, remove all buffers from the bufferSet. * @param listener the removed BufferSetListener */ public void removeBufferSetListener(BufferSetListener listener) { Log.log(Log.DEBUG, this, hashCode() + ": removeBufferSetListener " + listener); listeners.remove(BufferSetListener.class, listener); } //}}} //{{{ toString() method @Override public String toString() { return "BufferSet[nbBuffers="+size()+']'; } //}}} //{{{ sort() method /** * Sort the bufferSet (useful if a buffer has been renamed for example * @since jEdit 4.4pre1 */ public void sort() { if (sorter == null) return; // do the sort Collections.sort(buffers, sorter); // notify the listeners so they can repaint themselves BufferSetListener[] listeners = this.listeners.getListeners(BufferSetListener.class); for (BufferSetListener listener : listeners) { listener.bufferSetSorted(); } } //}}} //{{{ Package-private members //{{{ handleMessage /** * This method is called by BufferSetManager to signal that this * BufferSet needs to react to a change in the sorting properties. */ void propertiesChanged() { if (jEdit.getBooleanProperty("sortBuffers")) { // set the appropriate sorter if (jEdit.getBooleanProperty("sortByName")) sorter = nameSorter; else sorter = pathSorter; sort(); } else { // user has elected not to sort BufferSets sorter = null; } } //}}} //{{{ moveBuffer() method void moveBuffer(int oldPosition, int newPosition) { if (sorter != null) { // Buffers are sorted, do nothing return; } Buffer buffer; synchronized (buffers) { buffer = buffers.remove(oldPosition); int size = buffers.size(); if (newPosition == -1 || newPosition > size) { newPosition = size; } buffers.add(newPosition, buffer); } BufferSetListener[] listeners = this.listeners.getListeners(BufferSetListener.class); Log.log(Log.DEBUG, this, hashCode() + ": Buffer moved " + buffer + " from " + oldPosition + " to " + newPosition); for (BufferSetListener listener : listeners) { listener.bufferMoved(buffer, oldPosition, newPosition); } } //}}} //{{{ removeBuffer() method void removeBuffer(Buffer buffer) { int index; synchronized (buffers) { index = buffers.indexOf(buffer); if (index == -1) return; buffers.remove(index); } BufferSetListener[] listeners = this.listeners.getListeners(BufferSetListener.class); Log.log(Log.DEBUG, this, hashCode() + ": Buffer removed " + buffer); for (BufferSetListener listener : listeners) { listener.bufferRemoved(buffer, index); } } //}}} //}}} //{{{ Private members private final List<Buffer> buffers; private final EventListenerList listeners; private static final Comparator<Buffer> nameSorter = new NameSorter(); private static final Comparator<Buffer> pathSorter = new PathSorter(); private Comparator<Buffer> sorter; //}}} //{{{ NameSorter class public static class NameSorter implements Comparator<Buffer> { public int compare(Buffer o1, Buffer o2) { int ret = StandardUtilities.compareStrings(o1.getName(), o2.getName(), true); if (ret == 0) { ret = StandardUtilities.compareStrings(o1.getPath(), o2.getPath(), true); } return ret; } } //}}} //{{{ PathSorter class public static class PathSorter implements Comparator<Buffer> { public int compare(Buffer o1, Buffer o2) { return StandardUtilities.compareStrings(o1.getPath(), o2.getPath(), true); } } //}}} }