package jp.ne.mki.wedge.education.focusmanager;

import java.awt.Component;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.event.KeyEvent;

import javax.swing.InputVerifier;

/**
 * <h2>enqueueKeyEventsの引数の値にdispatchKeyEventでの時間を渡すKeyboardFocusManager。</h2>
 * 
 * <p>
 * JDK1.5.0_10以降 (2007/06/05現在 JDK1.5.0_11,12 も含む) のJDKを使用した場合、
 * フォーカスを取得していないComponentに対して、KeyEventが処理されComponent
 * に反映してしまう現象が発生します。<br />
 * 
 * この現象は、重い処理中(メインスレッドにて何かの処理中)に、TABにてFocus移動を含んだ
 * KEY入力を行った際に、テキストのフォーカス移動"後" (After処理後) に Keyが反映されるという
 * 不具合を招くことになり、内部データと表示データとの整合性が合わない という現象になって
 * 現れます。
 * </p>
 * <p>
 * JDK1.5.0_10での変更の詳細については、Javaネイティブコードに達する為、詳細把握はできていませんが、、
 * {@link DefaultKeyboardFocusManager#enqueueKeyEvents(long, Component)}の
 * 第一引数の long の時間を、{@link DefaultKeyboardFocusManager#dispatchKeyEvent(KeyEvent)}
 * のタイミングの {@link KeyEvent#getWhen()} の値に置き換える処理を組み込むことにより、
 * JDK1.5.0_09以前の動きと擬似的に同じできるのを確認し、このクラスでは その処理を組み込んだ
 * KeyboardFocusManagerになります。<br />
 * 但し、この対応方法は、根本的な解決ではないため、これによる副作用がある可能性があります。<br />
 * (製品のテストケースは全て通るのは確認していますが、予想外の副作用が潜んでいる可能性があります。)
 * </p>
 * <p>
 * このJDK1.5.0_09とJDK1.5.0_10との挙動の差は JDK1.5.0_10 のリリースノートに記述されている、
 * バグID:6448190 「JFrame と JButton でフォーカスの問題」  での修正に依るものと考えられますので、
 * その修正よる不具合解決はできなくなる可能性があります。
 * </p>
 * <p>
 * JDK1.5.0_10,11 にて {@link InputVerifier}にて、waitをかけている間に
 * TABでのFocus移動を含んだKEY操作を行った場合でも<br />
 * {@link InputVerifier#verify(javax.swing.JComponent)} がCallされた後に Text上にKEYが反映される
 * ため、{@link InputVerifier#verify(javax.swing.JComponent)} にて正確にチェックが行えない
 * という現象を確認しています。(JDK1.5.0_10,JDK1.5.0_11,JDK1.6.0,JDK1.6.0_01にて確認)<br />
 * そのためこの現象はJavaSwingの不具合になります。<br />
 * 新しいJDKがリリースされて、この不具合が解決された場合、このKeyboardFocusManagerクラスを設定せずとも
 * 不具合が解消される可能性があります。
 * </p>
 * 
 * 
 * <p class="LicenseTitle">使用にあたって (利用許諾)</p>
 * <p class="LicenseRange">
 * このライブラリはフリーソフトウェアです。<br>
 * このライブラリは役に立つことを願って配布しますが、完全 無保証 です。<br>
 * 本ライブラリを利用して損害が発生した場合、当社は一切の責任を負いません。<br><br>
 * ある特定条件下(タイミング、製品・JDKバージョン)では動作不良を招くなどの可能性もありますので、
 * 使用有無判断/テスト は自己責任でお願いします。<br><br>
 * このライブラリは 製品サポート の対象外になります。<br>
 * お問い合わせには一切応じかねますので予めご了承ください。
 * </p>
 * 
 * @author Media Knowledge Industrial Co.,Ltd.
 *
 */
public class EnqueueNoWaitKeyboardFocusManager extends DefaultKeyboardFocusManager {
	/** 最後に受け取ったKeyEventの時間 */
	long lastWhen = 0;

	/**
	 * dispatchKeyEvent
	 * @param e
	 */
	public boolean dispatchKeyEvent(KeyEvent e) {
		// Dispatchした KeyEventの最終時刻を記録しておく
		lastWhen = e.getWhen();
		return super.dispatchKeyEvent(e);
	}

	/**
	 * enqueueKeyEvents
	 * @param after
	 * @param untilFocused
	 */
	protected synchronized void enqueueKeyEvents(long after, Component untilFocused) {
		// 最終時刻を引数として渡す
		super.enqueueKeyEvents(lastWhen, untilFocused);
	}
}
