/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.swing.control; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.ListIterator; import javax.swing.AbstractListModel; /** * A generic ListModel class to support {@linkplain DnDList}. * <p> * The DnDListModel acts as a wrapper around an internal list of * items; providing notification as the items are changed. * </p> * @author Michael Bedward * @since 2.6 * * @source $URL$ * @version $Id$ */ public class DnDListModel<T> extends AbstractListModel { private static final long serialVersionUID = -6110074993686576005L; List<T> items; private boolean notify; /** * Default constructor */ public DnDListModel() { items = new ArrayList<T>(); notify = true; } public void setNofifyListeners(boolean notify) { this.notify = notify; } public boolean getNotifyListeners() { return notify; } public int getSize() { return items.size(); } /** * Get the list item at the specified index. * <p> * Note: this method returns a live reference. * * @throws IndexOutOfBoundsException if index is invalid */ public T getElementAt(int index) { return items.get(index); } /** * Returns a list of the items at the specified indices. * <p> * Note: The returned List contains live references. * * @throws IndexOutOfBoundsException if any of the indices are invalid */ public List<T> getElementsAt(int[] indices) { List<T> refs = new ArrayList<T>(); for (int k = 0; k < indices.length; k++) { refs.add(items.get(indices[k])); } return refs; } /** * Returns a list of the items at the indices specified in the Collection. * <p> * Note: The returned List contains live references. * * @throws IndexOutOfBoundsException if any of the indices are invalid */ public List<T> getElementsAt(Collection<Integer> indices) { List<T> refs = new ArrayList<T>(); for (Integer index : indices) { refs.add(items.get(index)); } return refs; } /** * Append a new item to the end of the list of current items */ public void addItem(T newItem) { int index = items.size(); items.add(newItem); if (notify) { fireIntervalAdded(this, index, index); } } /** * Add new items to the end of the list of current items */ public void addItems(T[] newItems) { if (newItems.length > 0) { int index0 = items.size(); for (T item : newItems) { items.add(item); } if (notify) { fireIntervalAdded(this, index0, index0 + newItems.length - 1); } } } /** * Add new items to the end of the list of current items */ public void addItems(Collection<T> newItems) { if (!newItems.isEmpty()) { int index0 = items.size(); for (T item : newItems) { items.add(item); } if (notify) { fireIntervalAdded(this, index0, index0 + newItems.size() - 1); } } } /** * Insert an item into the list at the specified position. * @param destIndex the position of the new item: if < 0 the item will * be inserted at the start of the list; if >= the current list size * the item will be appended to the end of the list */ public void insertItem(int destIndex, T newItem) { if (destIndex < 0) { destIndex = 0; } else if (destIndex >= getSize()) { addItem(newItem); return; } items.add(destIndex, newItem); if (notify) { fireIntervalAdded(this, destIndex, destIndex); } } /** * Insert new items into the list at the specified position. * * @param destIndex the position of the new item: if < 0 the items will * be inserted at the start of the list; if >= the current list size * the items will be appended to the end of the list */ public void insertItems(int destIndex, T[] newItems) { insertItems(destIndex, Arrays.asList(newItems)); } /** * Insert new items into the list at the specified position. * * @param destIndex the position of the new item: if < 0 the items will * be inserted at the start of the list; if >= the current list size * the items will be appended to the end of the list */ public void insertItems(int destIndex, Collection<T> newItems) { if (destIndex < 0) { destIndex = 0; } else if (destIndex >= getSize()) { addItems(newItems); return; } items.addAll(destIndex, newItems); if (notify) { fireIntervalAdded(this, destIndex, destIndex + newItems.size() - 1); } } /** * Move the items currently positioned at the indices in the * {@code srcIndices} array as block such that they are inserted * into the list at {@code destIndex}. It is <b>assumed</b> that * srcIndices is sorted in ascending order. */ public void moveItems(int destIndex, int[] srcIndices) { if (srcIndices.length > 0) { List<T> copies = getElementsAt(srcIndices); int minIndex = Math.min(destIndex, srcIndices[0]); int maxIndex = Math.max(destIndex - 1, srcIndices[srcIndices.length - 1]); for (int k = srcIndices.length - 1; k >= 0; k--) { items.remove(srcIndices[k]); } notify = false; insertItems(destIndex, copies); this.fireContentsChanged(this, minIndex, maxIndex); notify = true; } } /** * Remove the item at the specified index */ public void removeAt(int index) { items.remove(index); if (notify) { fireIntervalRemoved(this, index, index); } } /** * Removes the first instance of the specified item if it is contained in the list */ public void removeItem(T item) { ListIterator<T> iter = items.listIterator(); int index = 0; boolean found = false; while (iter.hasNext()) { T anItem = iter.next(); if (anItem.equals(item)) { iter.remove(); found = true; break; } index++; } if (found && notify) { this.fireIntervalRemoved(this, index, index); } } /** * Remove all items from the list */ public void clear() { int prevSize = items.size(); items.clear(); if (notify) { this.fireIntervalRemoved(this, 0, prevSize); } } /** * Query whether this list contains the specified item */ public boolean contains(T item) { return items.contains(item); } /** * Get the (first) index of the given item in the list of items held by this model. * * @param item the item to search for * @return the index or -1 if the item is not present */ public int indexOf(T item) { return items.indexOf(item); } @Override public String toString() { return "DnD:"+items; } }