PageRenderTime 69ms CodeModel.GetById 62ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/CommonControls/common/swingworker/AccumulativeRunnable.java

#
Java | 142 lines | 29 code | 9 blank | 104 comment | 3 complexity | cc525361e0270e2335f6d1f44bce9dd5 MD5 | raw file
  1/*
  2 * $Id: AccumulativeRunnable.java,v 1.2 2006/09/28 20:20:28 idk Exp $
  3 *
  4 * Copyright 2005 Sun Microsystems, Inc. All rights
  5 * reserved. Use is subject to license terms.
  6 */
  7
  8//package org.jdesktop.swingworker;
  9package common.swingworker;
 10
 11import java.util.*;
 12import javax.swing.SwingUtilities;
 13
 14/**
 15 * An abstract class to be used in the cases where we need {@code Runnable}
 16 * to perform  some actions on an appendable set of data.
 17 * The set of data might be appended after the {@code Runnable} is
 18 * sent for the execution. Usually such {@code Runnables} are sent to
 19 * the EDT.
 20 *
 21 * <p>
 22 * Usage example:
 23 *
 24 * <p>
 25 * Say we want to implement JLabel.setText(String text) which sends
 26 * {@code text} string to the JLabel.setTextImpl(String text) on the EDT.
 27 * In the event JLabel.setText is called rapidly many times off the EDT
 28 * we will get many updates on the EDT but only the last one is important.
 29 * (Every next updates overrides the previous one.)
 30 * We might want to implement this {@code setText} in a way that only
 31 * the last update is delivered.
 32 * <p>
 33 * Here is how one can do this using {@code AccumulativeRunnable}:
 34 * <pre>
 35 * AccumulativeRunnable<String> doSetTextImpl =
 36 * new  AccumulativeRunnable<String>() {
 37 *     @Override
 38 *     protected void run(List&lt;String&gt; args) {
 39 *         //set to the last string being passed
 40 *         setTextImpl(args.get(args.size() - 1);
 41 *     }
 42 * }
 43 * void setText(String text) {
 44 *     //add text and send for the execution if needed.
 45 *     doSetTextImpl.add(text);
 46 * }
 47 * </pre>
 48 *
 49 * <p>
 50 * Say we want want to implement addDirtyRegion(Rectangle rect)
 51 * which sends this region to the
 52 * handleDirtyRegions(List<Rect> regions) on the EDT.
 53 * addDirtyRegions better be accumulated before handling on the EDT.
 54 *
 55 * <p>
 56 * Here is how it can be implemented using AccumulativeRunnable:
 57 * <pre>
 58 * AccumulativeRunnable<Rectangle> doHandleDirtyRegions =
 59 *     new AccumulativeRunnable<Rectangle>() {
 60 *         @Override
 61 *         protected void run(List&lt;Rectangle&gt; args) {
 62 *             handleDirtyRegions(args);
 63 *         }
 64 *     };
 65 *  void addDirtyRegion(Rectangle rect) {
 66 *      doHandleDirtyRegions.add(rect);
 67 *  }
 68 * </pre>
 69 *
 70 * @author Igor Kushnirskiy
 71 * @version $Revision: 1.2 $ $Date: 2006/09/28 20:20:28 $
 72 *
 73 * @param <T> the type this {@code Runnable} accumulates
 74 *
 75 */
 76abstract class AccumulativeRunnable<T> implements Runnable {
 77    private List<T> arguments = null;
 78
 79    /**
 80     * Equivalent to {@code Runnable.run} method with the
 81     * accumulated arguments to process.
 82     *
 83     * @param args accumulated arguments to process.
 84     */
 85    protected abstract void run(List<T> args);
 86
 87    /**
 88     * {@inheritDoc}
 89     *
 90     * <p>
 91     * This implementation calls {@code run(List<T> args)} method
 92     * with the list of accumulated arguments.
 93     */
 94    public final void run() {
 95        run(flush());
 96    }
 97
 98    /**
 99     * appends arguments and sends this {@code Runnable} for the
100     * execution if needed.
101     * <p>
102     * This implementation uses {@see #submit} to send this
103     * {@code Runnable} for execution.
104     * @param args the arguments to accumulate
105     */
106    public final synchronized void add(T... args) {
107        boolean isSubmitted = true;
108        if (arguments == null) {
109            isSubmitted = false;
110            arguments = new ArrayList<T>();
111        }
112        Collections.addAll(arguments, args);
113        if (!isSubmitted) {
114            submit();
115        }
116    }
117
118    /**
119     * Sends this {@code Runnable} for the execution
120     *
121     * <p>
122     * This method is to be executed only from {@code add} method.
123     *
124     * <p>
125     * This implementation uses {@code SwingWorker.invokeLater}.
126     */
127    protected void submit() {
128        SwingUtilities.invokeLater(this);
129    }
130
131    /**
132     * Returns accumulated arguments and flashes the arguments storage.
133     *
134     * @return accumulated arguments
135     */
136    private final synchronized List<T> flush() {
137        List<T> list = arguments;
138        arguments = null;
139        return list;
140    }
141}
142