All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javafx.collections.ObservableListBase Maven / Gradle / Ivy

There is a newer version: 24-ea+15
Show newest version
/*
 * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.collections;

import com.sun.javafx.collections.ListListenerHelper;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javafx.beans.InvalidationListener;

/**
 * Abstract class that serves as a base class for {@link ObservableList} implementations.
 * The base class provides two functionalities for the implementing classes.
 * 
    *
  • Listener handling by implementing {@code addListener} and {@code removeListener} methods. * {@link #fireChange(javafx.collections.ListChangeListener.Change) } method is provided * for notifying the listeners with a {@code Change} object. *
  • Methods for building up a {@link ListChangeListener.Change} object. There are various methods called * {@code next*}, like {@link #nextAdd(int, int) } for new items in the lists or {@link #nextRemove(int, java.lang.Object) } for * an item being removed from the list. *

    These methods must be always enclosed in {@link #beginChange() } and {@link #endChange() } block. *

    See the example below. *

* * The following example shows how the Change build-up works: *
 *  public void removeOddIndexes() {
 *      beginChange();
 *      try {
 *          for (int i = 1; i < size(); ++i) {
 *              remove(i);
 *          }
 *      } finally {
 *          endChange();
 *      }
 *  }
 *
 *  public void remove(int i) {
 *      beginChange();
 *      try {
 *          E removed = ... //do some stuff that will actually remove the element at index i
 *          nextRemove(i, removed);
 *      } finally {
 *          endChange();
 *      }
 *  }
 *
 * 
* * The {@code try}/{@code finally} blocks in the example are needed only if there's a possibility for an exception to occur * inside a {@code beginChange()} / {@code endChange()} block * *

* Note: If you want to create modifiable {@link ObservableList} implementation, consider * using {@link ModifiableObservableListBase} as a superclass. *

* Note: In order to create list with sequential access, you should override {@link #listIterator()}, * {@link #iterator() } methods and use them in {@link #get}, {@link #size()} and other methods accordingly. * * @param the type of the elements contained in the List * @see ObservableList * @see ListChangeListener.Change * @see ModifiableObservableListBase * @since JavaFX 8.0 */ public abstract class ObservableListBase extends AbstractList implements ObservableList { private ListListenerHelper listenerHelper; private ListChangeBuilder changeBuilder; /** * Creates a default {@code ObservableListBase}. */ public ObservableListBase() { } /** * Adds a new update operation to the change. *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param pos the position in the list where the updated element resides. */ protected final void nextUpdate(int pos) { getListChangeBuilder().nextUpdate(pos); } /** * Adds a new set operation to the change. * Equivalent to {@code nextRemove(idx); nextAdd(idx, idx + 1); }. *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param idx the index of the item that was set * @param old the old value at the {@code idx} position. */ protected final void nextSet(int idx, E old) { getListChangeBuilder().nextSet(idx, old); } /** * Adds a new replace operation to the change. * Equivalent to {@code nextRemove(from, removed); nextAdd(from, to); } *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param from the index where the items were replaced * @param to the end index (exclusive) of the range where the new items reside * @param removed the list of items that were removed */ protected final void nextReplace(int from, int to, List removed) { getListChangeBuilder().nextReplace(from, to, removed); } /** * Adds a new remove operation to the change with multiple items removed. *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param idx the index where the items were removed * @param removed the list of items that were removed */ protected final void nextRemove(int idx, List removed) { getListChangeBuilder().nextRemove(idx, removed); } /** * Adds a new remove operation to the change with single item removed. *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param idx the index where the item was removed * @param removed the item that was removed */ protected final void nextRemove(int idx, E removed) { getListChangeBuilder().nextRemove(idx, removed); } /** * Adds a new permutation operation to the change. * The permutation on index {@code "i"} contains the index, where the item from the index {@code "i"} was moved. *

It's not necessary to provide the smallest permutation possible. It's correct to always call this method * with {@code nextPermutation(0, size(), permutation); } *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param from marks the beginning (inclusive) of the range that was permutated * @param to marks the end (exclusive) of the range that was permutated * @param perm the permutation in that range. Even if {@code from != 0}, the array should * contain the indexes of the list. Therefore, such permutation would not contain indexes of range {@code (0, from)} */ protected final void nextPermutation(int from, int to, int[] perm) { getListChangeBuilder().nextPermutation(from, to, perm); } /** * Adds a new add operation to the change. * There's no need to provide the list of added items as they can be found directly in the list * under the specified indexes. *

Note: needs to be called inside {@code beginChange()} / {@code endChange()} block. *

Note: needs to reflect the current state of the list. * @param from marks the beginning (inclusive) of the range that was added * @param to marks the end (exclusive) of the range that was added */ protected final void nextAdd(int from, int to) { getListChangeBuilder().nextAdd(from, to); } /** * Begins a change block. * * Must be called before any of the {@code next*} methods is called. * For every {@code beginChange()}, there must be a corresponding {@link #endChange() } call. *

{@code beginChange()} calls can be nested in a {@code beginChange()}/{@code endChange()} block. * * @see #endChange() */ protected final void beginChange() { getListChangeBuilder().beginChange(); } /** * Ends the change block. * * If the block is the outer-most block for the {@code ObservableList}, the * {@code Change} is constructed and all listeners are notified. *

Ending a nested block doesn't fire a notification. * * @see #beginChange() */ protected final void endChange() { getListChangeBuilder().endChange(); } private ListChangeBuilder getListChangeBuilder() { if (changeBuilder == null) { changeBuilder = new ListChangeBuilder<>(this); } return changeBuilder; } @Override public final void addListener(InvalidationListener listener) { listenerHelper = ListListenerHelper.addListener(listenerHelper, listener); } @Override public final void removeListener(InvalidationListener listener) { listenerHelper = ListListenerHelper.removeListener(listenerHelper, listener); } @Override public final void addListener(ListChangeListener listener) { listenerHelper = ListListenerHelper.addListener(listenerHelper, listener); } @Override public final void removeListener(ListChangeListener listener) { listenerHelper = ListListenerHelper.removeListener(listenerHelper, listener); } /** * Notifies all listeners of a change * @param change an object representing the change that was done */ protected final void fireChange(ListChangeListener.Change change) { ListListenerHelper.fireValueChangedEvent(listenerHelper, change); } /** * Returns true if there are some listeners registered for this list. * @return true if there is a listener for this list */ protected final boolean hasListeners() { return ListListenerHelper.hasListeners(listenerHelper); } @Override public boolean addAll(E... elements) { return addAll(Arrays.asList(elements)); } @Override public boolean setAll(E... elements) { return setAll(Arrays.asList(elements)); } @Override public boolean setAll(Collection col) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(E... elements) { return removeAll(Arrays.asList(elements)); } @Override public boolean retainAll(E... elements) { return retainAll(Arrays.asList(elements)); } @Override public void remove(int from, int to) { removeRange(from, to); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy