/*
* Copyright (c) 2011, 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.concurrent;
import java.util.*;
import java.util.concurrent.Semaphore;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
/**
* The ObservableListTask is a concrete fully observable implementation of
* FutureTask which has special support for handling a result of type
* ObservableList. An ObservableListTask creates an ObservableList in its
* constructor which is never replaced. Within the call
method,
* the implementation of ObservableListTask will call publish
* one or more times to add items to the observable list in a thread-safe
* manner.
*
*
This implementation is tuned for high performance by limiting the number
* of events placed on the event queue by coalescing items added via the
* publish
methods. Calling publish
with coarse or
* fine granularity should both perform well, allowing the implementation
* of the {@link #call()} method to remain simple.
If you desire to change the ObservableList (such as removing items or
* checking previously added items), you can do so with some complication by
* calling Platform.runLater
and jumping on the FX application
* thread. For most cases this should not be necessary and is discouraged.
The ObservableListTask allows you to specify in one of its constructors * a custom ObservableList to use. This instance is immutable, meaning it will * be set on the ObservableListTask as its value during construction and will * not change thereafter.
* ** The following set of examples demonstrate some of the most common uses of * ObservableListTasks. *
* *This first example constructs an ObservableList of Rectangles. Note that, * as with {@link Task}, cancellation of an ObservableListTask is a cooperative * affair. The ObservableListTask implementation must check the isCancelled * flag to determine whether it should terminate work.
* *
* ObservableListTask<Rectangle> task = new ObservableListTask<Rectangle>() {
* @Override protected void call() throws Exception {
* for (int i=0; i<900; i++) {
* if (isCancelled()) {
* break;
* }
* Rectangle r = new Rectangle(10, 10);
* r.setFill(Color.color(Math.random(), Math.random(), Math.random()));
* publish(r);
* Thread.sleep(20);
* updateProgress(i, 900);
* }
* return iterations;
* }
* };
*
*
* In this example, we simply iterate 900 times creating a single
* Rectangle in each iteration. We first check to see if the user has
* cancelled, and if so, we will terminate the loop. Otherwise we will create
* a Rectangle, assign it some random color, and then publish the Rectangle.
* The Thread.sleep
call in this case is not required, but useful
* for slowing the task down for the sake of example.
In this example we will take the code from the previous example and * wire it up to a FlowPane, and add animations. This is a simple example * demonstrating a thread-safe way to construct Rectangles and animations on * a background thread, and wire the ObservableList to the FlowPane children.
* *
* ObservableListTask<Rectangle> task = new ObservableListTask<Rectangle>() {
* @Override protected void call() throws Exception {
* for (int i=0; i<900; i++) {
* if (isCancelled()) {
* break;
* }
* Rectangle r = new Rectangle(10, 10);
* r.setFill(Color.color(Math.random(), Math.random(), Math.random()));
* r.setOpacity(0);
* FadeTransition tx = new FadeTransition(Duration.seconds(1));
* tx.setToValue(1.0);
* tx.setNode(r);
* tx.play();
* publish(r);
* Thread.sleep(20);
* updateProgress(i, 900);
* }
* return iterations;
* }
* };
* FlowPane pane = new FlowPane(7, 7);
* task.getValue().addListener(new ListChangeListener<Rectangle>() {
* @Override
* public void onChanged(Change<? extends Rectangle> change) {
* while (change.next()) {
* if (change.wasAdded()) {
* group.getChildren().addAll(change.getAddedSubList());
* }
* }
* }
* });
*
*/
public abstract class ObservableListTaskImplementations of this method must call publish
* with any items to be added to the ObservableList.
For example, you may have an ObservableListTask which constructs * records from a ResultSet. In this case you can add records to the * ObservableList incrementally from the background thread.
* *As with the other update methods, Calls to publish * are coalesced and run later on the FX application thread, so calls * to publish, even from the FX Application thread, may not * necessarily result in immediate updates to this property, and * intermediate values may be coalesced to save on event * notifications. However, all items added via this method will * eventually be added to the ObservableList in the order in which * they were added. *
* This method is safe to be called from any thread. *
* * @param items The items to add to the ObservableList */ protected void publish(E... items) { publish(Arrays.asList(items)); } /** * Adds the given items to the ObservableList. This * can be done at any time. This method allows ObservableListTask * implementations to provide intermediate results. * *For example, you may have an ObservableListTask which constructs * records from a ResultSet. In this case you can add records to the * ObservableList incrementally from the background thread.
* *As with the other update methods, Calls to publish * are coalesced and run later on the FX application thread, so calls * to publish, even from the FX Application thread, may not * necessarily result in immediate updates to this property, and * intermediate values may be coalesced to save on event * notifications. However, all items added via this method will * eventually be added to the ObservableList in the order in which * they were added. *
* This method is safe to be called from any thread. *
* * @param items The items to add to the ObservableList */ protected void publish(Collection