/* * Copyright 2013 Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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 com.google.dart.tools.debug.core.util; import java.util.ArrayList; import java.util.List; /** * A history list implementation. Elements can be added to the list, and you can navigate forwards * and backwards from the current location. This class can be used to implement browser style * navigation controls. * * @param <T> */ public class HistoryList<T> { private List<T> list = new ArrayList<T>(); private int current = -1; private List<HistoryListListener<T>> listeners = new ArrayList<HistoryListListener<T>>(); public HistoryList() { } public void add(T t) { if (t == null) { throw new IllegalArgumentException("null not allowed"); } fireAboutToChange(getCurrent()); // trim off any items past the current pointer while (hasNext()) { list.remove(list.size() - 1); } list.add(t); current = list.size() - 1; fireChanged(getCurrent()); } public void addListener(HistoryListListener<T> listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } public void clear() { current = -1; list.clear(); fireChanged(getCurrent()); } public T getCurrent() { if (current >= 0 && current < list.size()) { return list.get(current); } else { return null; } } public boolean hasNext() { return (current != -1) && (current + 1 < list.size()); } public boolean hasPrevious() { return current > 0; } public void navigateNext() { if (hasNext()) { fireAboutToChange(getCurrent()); current++; fireChanged(getCurrent()); } } public void navigatePrevious() { if (hasPrevious()) { fireAboutToChange(getCurrent()); current--; fireChanged(getCurrent()); } } public void removeListener(HistoryListListener<T> listener) { listeners.remove(listener); } public void removeMatching(HistoryListMatcher<T> matcher) { boolean removedItem = false; T oldCurrent = getCurrent(); for (int i = list.size() - 1; i >= 0; i--) { T t = list.get(i); if (matcher.matches(t)) { list.remove(i); removedItem = true; if (current > i) { // move the current selection left if we deleted to the left of it current--; } else if (current >= list.size()) { // ensure that we don't point past the end of the list current = list.size() - 1; } } } if (removedItem) { fireAboutToChange(oldCurrent); fireChanged(getCurrent()); } } public int size() { return list.size(); } private void fireAboutToChange(T current) { if (current != null && !listeners.isEmpty()) { for (HistoryListListener<T> l : listeners) { l.historyAboutToChange(current); } } } private void fireChanged(T current) { if (!listeners.isEmpty()) { for (HistoryListListener<T> l : listeners) { l.historyChanged(current); } } } }