Package open.dolphin.helper

Source Code of open.dolphin.helper.Task$InputBlocker

package open.dolphin.helper;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import open.dolphin.ui.MyProgressMonitor;

/**
* Progress 表示付き Task
* @author pns
*/
public abstract class Task<T> extends SwingWorker<T, Integer> implements ActionListener, PropertyChangeListener {

    /** 起動している Task instance のリスト。表示される ProgressMonitor を1つにするのに使う */
    private static ArrayList<Task> taskList = new ArrayList<Task>();

    /** ProgressMonitor のレンジは 0-100 で固定なので MAX は 100 で固定する */
    private static final double MAX = 100;

    private MyProgressMonitor progressMonitor;
    private Timer timer;
    private InputBlocker blocker;
    private int timeout = 0;
    /** 進捗状況を表示する間隔 (msec) */
    private int interval = 500;
    /** interval と timeout から計算される ProgressMonitor の増加量 */
    private double tick = 0;
    /** 進捗値 0〜MAX の間を動く */
    private double current = 0;
    /** cancel の時に処理に interrupt を入れるかどうか */
    private boolean interrupt = true;

    /**
     * 進捗状況を自分で setProgress する Task を作る
     * setProgress しないと,勝手に 1/10 ずつ count up していくが終了はしない
     * @param parent ダイアログの親
     * @param message ダイアログに出すメッセージ(後から変更不可)
     * @param note ダイアログに出すノート(後から変更可能)
     */
    public Task(Component parent, Object message, String note) {
        this(parent, message, note, 0);
    }

    /**
     * 一定時間ごとに進捗状況を表示する Task を作る
     * maxEstimation=0 の場合は自分で setProgress して管理する必要あり
     * @param parent ダイアログの親
     * @param message ダイアログに出すメッセージ
     * @param note ダイアログに出すノート(後から setNote で変更可能)
     * @param maxEstimation timeout までの時間(msec)
     */
    public Task(Component parent, Object message, String note, int maxEstimation) {
        super();

        // interval (msec) ごとに interrupt して進捗状況を表示
        timeout = maxEstimation;
        if (maxEstimation != 0) {
            tick = MAX * interval / maxEstimation;
        }
        // this をコンストラクタから分離
        initialize(parent, message, note);
    }

    private void initialize(Component c, Object message, String note) {
        timer = new Timer(interval, this);
        progressMonitor = new MyProgressMonitor(c, message, note, 0, 100);
        taskList.add(this);
        addPropertyChangeListener(this);
    }

    /**
     * ProgressMonitor を出す前に無条件で待つ時間 (default = 500 msec)
     * @param sec
     */
    public void setMillisToDecidePopup(int msec) {
        progressMonitor.setMillisToDecideToPopup(msec);
    }
    /**
     * この時間が予想残り時間より短い場合に ProgressMonitor を出す
     * 残り時間は,setValue の度に経過時間から計算される
     * @param msec
     */
    public void setMillisToPopup(int msec) {
        progressMonitor.setMillisToPopup(msec);
    }
    /**
     * Time out までの時間 (msec) 0=time out しない
     * @param msec
     */
    public void setTimeOut(int msec) {
        this.timeout = msec;
    }
    /**
     * ProgressMonitor に note を表示
     * @param note
     */
    public void setNote(String note) {
        progressMonitor.setNote(note);
    }
    /**
     * ProgressMonitor を表示するのは,一番先に加わった task のみにする
     * たくさん ProgressMonitor dialog が出るとうざいので
     * @param nv
     */
    private void setProgressMonitorProgress(int nv) {
        if (!taskList.isEmpty() && taskList.get(0).hashCode() == this.hashCode()) {
            progressMonitor.setProgress(nv);
        }
    }
    /**
     * Task.InputBlocker をセットする
     * @param blocker
     */
    public void setInputBlocker(InputBlocker blocker) {
        this.blocker = blocker;
    }
    /**
     * Cancel の時に,強制 interrupt かけるかどうか
     * doInBackground に自分でキャンセル処理入れた場合 false にする
     * @param b
     */
    public void setInterruptOnCancel(boolean b) {
        interrupt = b;
    }
   
    /**
     * interval 時間ごとに実行される action
     * ProgressBar 表示処理,timeout 処理をする
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        // interval ごとに cancel チェック
        if (progressMonitor.isCanceled()) {
            cancel(interrupt);
            return;
        }

        setProgressMonitorProgress((int) current);

        if (timeout == 0) {
            // timeout しない場合は残りの 1/10 を足す
            current += (MAX - current)/10;
           
        } else  {           
            current += tick;
            // timeout した場合は強制的に cancel
            if (current >= MAX) cancel(true);
        }
    }
    /**
     * SwingWorker からの propertyChange を受け取る
     * @param e
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();

        if ("state".equals(prop)) {
            switch ((StateValue) e.getNewValue()) {
                case STARTED:
                    // 一定時間ごとに割り込んで進捗状況を表示するタイマーをスタート
                    if (!timer.isRunning()) timer.start();
                    if (blocker != null) blocker.block();
                    break;

                case DONE:
                    timer.stop();
                    if (blocker != null) blocker.unblock();
                    break;
            }
        // setProgress した場合呼ばれる
        } else if ("progress".equals(prop)) {
            int nv = (Integer) e.getNewValue();
            setProgressMonitorProgress(nv);
            current = nv;
        }
    }

    @Override
    protected void done() {
        taskList.remove(this);
        progressMonitor.close();

        if (isCancelled()) cancelled();
        else {
            try {
                succeeded(get());
            }
            catch (InterruptedException e) {
                interrupted(e);
            }
            catch (ExecutionException e) {
                failed(e.getCause());
            }
        }
    }

    /**
     * 入力ブロッカー
     */
    public interface InputBlocker {
        public void block();
        public void unblock();
    }

    protected abstract void succeeded(T result);

    protected void cancelled() {};

    protected void failed(Throwable cause) {};

    protected void interrupted(InterruptedException ex) {};

    public static void main (String[] argv) {
        Task task = new Task<String>(null, "テスト1", "実行中...") {

            @Override
            protected String doInBackground() throws Exception {
                for(int i=0; i<4; i++) {
                    setProgress(i*25);
                    Thread.sleep(1000);
                }
                return "test";
            }

            @Override
            protected void succeeded(String result) {
                System.out.println("ended: " + new java.util.Date());
                System.out.println("result=" + result);
            }

            @Override
            protected void cancelled() {
                System.out.println("Canceled");
            }
            @Override
            protected void failed(Throwable cause) {
                System.out.println("failed " + cause);
            }
            @Override
            protected void interrupted(InterruptedException ex) {
                System.out.println("interrupted " + ex);
            }
           
        };
        task.setTimeOut(3000);
        task.execute();
        System.out.println("Task thread started: " + new java.util.Date());

        Task task2 = new Task(null, "テスト2", "実行中...") {

            @Override
            protected Object doInBackground() throws Exception {
                System.out.println("task2 start");
                for(int i=0; i<5; i++) {
                    setProgress(i*20);
                    Thread.sleep(1000);
                }
                return null;
            }

            @Override
            protected void succeeded(Object result) {
                System.out.println("task2 done");
            }

        };
        task2.setTimeOut(5000);
        task2.execute();


        System.out.println("Main thread is waiting for the thread done.");
        try {
            Thread.sleep(6000);
        } catch (InterruptedException ex) {
        }
        System.out.println("Main thread ended.");
    }
}
TOP

Related Classes of open.dolphin.helper.Task$InputBlocker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.