/*
 * 作成日: 2007/06/18
 */
package net.sourceforge.swingx;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

/**
 * プログレス・ダイアログ.
 *  
 */
public class SxProgressDialog extends JDialog {
	
	Thread thread;
	final String title;
	final JProgressBar progress;
	final JLabel label = new JLabel("message");
	final JButton button;
	private boolean isAbort = false;
	private boolean isInquire = true;
	/**
	 * 
	 * @param owner
	 * @param title
	 * @param thread	nullのときには、中断ボタンが表示されない。
	 * @param min
	 * @param max
	 */
	public SxProgressDialog(Frame owner, String title, Thread thread, int min, int max) {
		super(owner, title, true);
		assert owner != null;
		assert title != null;
		assert thread != null;
		assert min < max: "min="+min+" max="+max;
		this.thread = thread;
		this.title = title;
		progress = new JProgressBar(JProgressBar.HORIZONTAL, min, max);
		button = new JButton(new AboutAction());
		if (thread == null) button.setVisible(false);
		label.setHorizontalAlignment(JLabel.CENTER);
		JPanel panel = new JPanel(new BorderLayout());
		panel.add(progress, BorderLayout.SOUTH);
		panel.add(label, BorderLayout.CENTER);
		JPanel button_panel = new JPanel();
		button_panel.add(button);
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(panel, BorderLayout.CENTER);
		getContentPane().add(button_panel, BorderLayout.SOUTH);
		((JPanel) getContentPane()).setBorder(new EmptyBorder(10, 10, 10, 10));
		getRootPane().setDefaultButton(button);
		setSize(320, 240);
		setLocationRelativeTo(owner);
	}
	
	public SxProgressDialog(Frame owner, String title, Thread thread) {
		this(owner, title, thread, 0, 100);
	}
	/** 中断ボタンが押されたとき、問い合わせるか？それともすぐに中断するか？ */
	public void setInquire(boolean isInquire) {
		this.isInquire = isInquire;
	}
	
	// TODO:これは必要か？
	public void start() {
		assert thread != null;
		thread.start();
		setVisible(true);
	}

	/**
	 * このメソッドはSwingのイベントディスパッチスレッドとは別のスレッドから呼ばれることを想定しています。
	 * イベントディスパッチスレッドから呼んでも構いません。
	 */
	public void setProgress(final int pos, final String message) {
		assert message != null;
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				progress.setValue(pos);
				label.setText(message);
			}
		});
	}
	/** 
	 * 中断ボタンが押されたかを返す。
	 * 問い合わせを行うときには、それが確認されるまでは、falseを返す。
	 */
	public boolean isAbort() { return isAbort; }
	
	
	/** 中断ボタンが押されたときのアクション. */
	private class AboutAction extends AbstractAction {
		AboutAction() {
			super("中断");
		}
		public void actionPerformed(ActionEvent event) {
			// 問い合わせるか？それともすぐに中断するか？
			if (isInquire) {
				int rc = JOptionPane.showConfirmDialog(SxProgressDialog.this, 
		            "中断しますか？",
		            title, JOptionPane.YES_NO_OPTION);
				if (rc != JOptionPane.YES_OPTION) return;
			}
			// 中断要求
			isAbort = true;
			dispose();
		}
	}
	/** テスト用のダイアログ. */
	private static class TestProgressDialog {
		JFrame frame = new JFrame("SxProgressDialogのテスト");
		SxProgressDialog dialog;
		TestAction start = new TestAction();
		void test() {
			JMenuBar menubar = new JMenuBar();
			JMenu test = new JMenu("テスト");
			test.add(new JMenuItem(start));
			menubar.add(test);
			frame.setJMenuBar(menubar);
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setSize(640, 480);
			frame.setVisible(true);
		}
		class TestAction extends AbstractAction {
			TestAction() {
				super("テスト");
			}
			public void actionPerformed(ActionEvent e) {
				thread = new Thread() {
						public void run() {
							for (int i=0; i<100; i++) {
								if (dialog.isAbort()) break;
								try { Thread.sleep(100); } catch (InterruptedException e) {}
								dialog.setProgress(i, "message="+i);
								System.out.println("message="+i);
							}
							dialog.dispose();
							System.out.println("dispose");
						}
					};
				dialog = new SxProgressDialog(frame, "SxProgressDialog", thread);
				dialog.start();
			}
		};
		Thread thread;
	}
	public static void main(String[] args) {
		new TestProgressDialog().test();
	}
}
