Path: blob/master/src/java.desktop/share/classes/sun/swing/AccumulativeRunnable.java
41153 views
/*1* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.swing;2526import java.util.*;27import java.lang.reflect.Array;28import javax.swing.SwingUtilities;2930/**31* An abstract class to be used in the cases where we need {@code Runnable}32* to perform some actions on an appendable set of data.33* The set of data might be appended after the {@code Runnable} is34* sent for the execution. Usually such {@code Runnables} are sent to35* the EDT.36*37* <p>38* Usage example:39*40* <p>41* Say we want to implement JLabel.setText(String text) which sends42* {@code text} string to the JLabel.setTextImpl(String text) on the EDT.43* In the event JLabel.setText is called rapidly many times off the EDT44* we will get many updates on the EDT but only the last one is important.45* (Every next updates overrides the previous one.)46* We might want to implement this {@code setText} in a way that only47* the last update is delivered.48* <p>49* Here is how one can do this using {@code AccumulativeRunnable}:50* <pre>51* {@code AccumulativeRunnable<String> doSetTextImpl =52* new AccumulativeRunnable<String>()} {53* {@literal @Override}54* {@code protected void run(List<String> args)} {55* //set to the last string being passed56* setTextImpl(args.get(args.size() - 1));57* }58* }59* void setText(String text) {60* //add text and send for the execution if needed.61* doSetTextImpl.add(text);62* }63* </pre>64*65* <p>66* Say we want to implement addDirtyRegion(Rectangle rect)67* which sends this region to the68* {@code handleDirtyRegions(List<Rect> regiouns)} on the EDT.69* addDirtyRegions better be accumulated before handling on the EDT.70*71* <p>72* Here is how it can be implemented using AccumulativeRunnable:73* <pre>74* {@code AccumulativeRunnable<Rectangle> doHandleDirtyRegions =}75* {@code new AccumulativeRunnable<Rectangle>()} {76* {@literal @Override}77* {@code protected void run(List<Rectangle> args)} {78* handleDirtyRegions(args);79* }80* };81* void addDirtyRegion(Rectangle rect) {82* doHandleDirtyRegions.add(rect);83* }84* </pre>85*86* @author Igor Kushnirskiy87*88* @param <T> the type this {@code Runnable} accumulates89*90* @since 1.691*/92public abstract class AccumulativeRunnable<T> implements Runnable {93private List<T> arguments = null;9495/**96* Equivalent to {@code Runnable.run} method with the97* accumulated arguments to process.98*99* @param args accumulated argumets to process.100*/101protected abstract void run(List<T> args);102103/**104* {@inheritDoc}105*106* <p>107* This implementation calls {@code run(List<T> args)} mehtod108* with the list of accumulated arguments.109*/110public final void run() {111run(flush());112}113114/**115* appends arguments and sends this {@code Runnable} for the116* execution if needed.117* <p>118* This implementation uses {@see #submit} to send this119* {@code Runnable} for execution.120* @param args the arguments to accumulate121*/122@SafeVarargs123@SuppressWarnings("varargs") // Copying args is safe124public final synchronized void add(T... args) {125boolean isSubmitted = true;126if (arguments == null) {127isSubmitted = false;128arguments = new ArrayList<T>();129}130Collections.addAll(arguments, args);131if (!isSubmitted) {132submit();133}134}135136/**137* Sends this {@code Runnable} for the execution138*139* <p>140* This method is to be executed only from {@code add} method.141*142* <p>143* This implementation uses {@code SwingWorker.invokeLater}.144*/145protected void submit() {146SwingUtilities.invokeLater(this);147}148149/**150* Returns accumulated arguments and flashes the arguments storage.151*152* @return accumulated arguments153*/154private synchronized List<T> flush() {155List<T> list = arguments;156arguments = null;157return list;158}159}160161162