package tainavi;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SpringLayout;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/*
 * 検索文字列入力画面
 *
 */
public class VWSearchWordDialog extends JEscCancelDialog {

	private static final long serialVersionUID = 1L;

	/*******************************************************************************
	 * 定数
	 ******************************************************************************/

	// レイアウト関連

	private static final int PARTS_HEIGHT = 30;
	private static final int SEP_WIDTH = 10;
	private static final int SEP_HEIGHT = 10;
	private static final int SEARCH_HEIGHT = 45;

	private static final int LABEL_WIDTH = 120;

	private static final int TEXT_WIDTH = 500;
	private static final int CHECKBOX_WIDTH = 150;
	private static final int DATE_WIDTH = 120;
	private static final int AMONG_WIDTH = 30;
	private static final int NOTE_WIDTH = 600;
	private static final int NOTE_HEIGHT = PARTS_HEIGHT*2;

	private static final int BUTTON_WIDTH = 120;

	private static final int PANEL_WIDTH = SEP_WIDTH+LABEL_WIDTH+SEP_WIDTH+TEXT_WIDTH+SEP_WIDTH*2+BUTTON_WIDTH+SEP_WIDTH;

	// その他
	private static final int MAX_SEARCH_WORDS = 32;

	/*******************************************************************************
	 * 部品
	 ******************************************************************************/

	private JPanel jPanel = null;

	private JLabel jLabel_swlist = null;
	private JComboBoxWithPopup jComboBox_swlist = null;
//	private JTextField jTextField_swlist = null;

	private JLabel jLabel_keyword = null;
	private JTextField jTextField_keyword = null;

	private JLabel jLabel_options = null;
	private JCheckBox jCheckBox_title = null;
	private JCheckBox jCheckBox_detail = null;
	private JCheckBox jCheckBox_filter = null;

	private JLabel jLabel_period = null;
	private JTextField jTextField_from = null;
	private JLabel jLabel_among = null;
	private JTextField jTextField_to = null;
	private JButton jButton_same = null;

	private JButton jButton_delete = null;
	private JButton jButton_search = null;
//	private JButton jButton_cancel = null;
	private JButton jButton_clear = null;
	private JLabel jLabel_note = null;

	private JButton jButton_menu = null;
	private AbsToolBar jToolbar = null;

	// コンポーネント以外
	private Instant last_shown = null;
	private SearchWordList swlist = null;
	private boolean autoclose_enabled = true;

	/*******************************************************************************
	 * コンストラクタ
	 ******************************************************************************/

	public VWSearchWordDialog() {

		super();

//		this.setModal(true);
//		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);	// 閉じるときはキャンセルボタンを使ってクレ
		this.addWindowListener(wl_panel);
		this.setAlwaysOnTop(true);
		this.setContentPane(getJPanel());
		this.setUndecorated(true);
		this.pack();
		this.setTitle("検索条件の編集");
		this.setResizable(false);
	}

	/*******************************************************************************
	 * 公開メソッド
	 ******************************************************************************/
	/*
	 * ダイアログを表示する
	 */
	public void open(AbsToolBar jtoolbar, JButton jbutton, SearchWordList list, String s){
		jToolbar = jtoolbar;
		jButton_menu = jbutton;
		swlist = list;

		Instant now = Instant.now();
		if (last_shown != null && now.minusMillis(100).isBefore(last_shown))
			return;

		updateKeywordComboBox();
		if (s != null){
			jComboBox_swlist.setSelectedItem(s);

			if (s.isEmpty()){
				doClear();
			}
			else{
				decodeKeyword(s);
			}
		}

		updateControlStatus();
		setVisible(true);
	}

	/*
	 * 表示・非表示を切り替える
	 *
	 * @see java.awt.Dialog#setVisible(boolean)
	 */
	@Override
	public void setVisible(boolean b) {
		if (b){
			setLocation();
			jTextField_keyword.requestFocusInWindow();
		}
		else{
			last_shown = Instant.now();
		}

		super.setVisible(b);
	}

	/*
	 * ダイアログを▼ボタンの下、ツールバーの左端に位置決めする
	 */
	public void setLocation(){
		Point pf = jToolbar.getLocationOnScreen();
//		Rectangle rf = jToolbar.getBounds();

		Point pm = jButton_menu.getLocationOnScreen();
		Rectangle rm = jButton_menu.getBounds();

		setPosition(pf.x, pm.y + rm.height);
	}

	/*
	 * ダイアログを位置決めする
	 */
	public void setPosition(int x, int y) {
		Rectangle r = this.getBounds();
		r.x = x;
		r.y = y;
		this.setBounds(r);
	}

	/*******************************************************************************
	 * コンポーネント
	 ******************************************************************************/
	/*
	 * パネル全体
	 */
	private JPanel getJPanel() {
		if (jPanel == null) {
			jPanel = new JPanel();

			jPanel.setLayout(new SpringLayout());

			// １行目
			int y = SEP_HEIGHT;
			int x = SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_swlist("検索履歴"), LABEL_WIDTH, PARTS_HEIGHT, x, y);
			x += LABEL_WIDTH + SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJComboBox_swlist(), TEXT_WIDTH, PARTS_HEIGHT, x, y);
			x += TEXT_WIDTH + SEP_WIDTH*2;
			int xb = x;
			CommonSwingUtils.putComponentOn(jPanel, getJButton_delete("削除"), BUTTON_WIDTH, PARTS_HEIGHT, xb, y);

			// ２行目
			y += PARTS_HEIGHT + SEP_HEIGHT;
			x = SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_keyword("キーワード"), LABEL_WIDTH, PARTS_HEIGHT, x, y);
			x += LABEL_WIDTH + SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJTextField_keyword(), TEXT_WIDTH, PARTS_HEIGHT, x, y);
			CommonSwingUtils.putComponentOn(jPanel, getJButton_search("検索"), BUTTON_WIDTH, SEARCH_HEIGHT, xb, y);

			// ３行目
			y += PARTS_HEIGHT + SEP_HEIGHT;
			x = SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_options("オプション"), LABEL_WIDTH, PARTS_HEIGHT, x, y);
			x += LABEL_WIDTH + SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_title("番組名一致"), CHECKBOX_WIDTH, PARTS_HEIGHT, x, y);
			x += CHECKBOX_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_detail("番組詳細一致"), CHECKBOX_WIDTH, PARTS_HEIGHT, x, y);
			x += CHECKBOX_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJCheckBox_filter("絞り込み"), CHECKBOX_WIDTH, PARTS_HEIGHT, x, y);
			x += SEP_WIDTH;
//			int yb2 = y;
//			CommonSwingUtils.putComponentOn(jPanel, getJButton_cancel("閉じる"), BUTTON_WIDTH, PARTS_HEIGHT, xb, yb2);

			// ４行目
			y += PARTS_HEIGHT + SEP_HEIGHT;
			x = SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_period("過去ログ期間※"), LABEL_WIDTH, PARTS_HEIGHT, x, y);
			x += LABEL_WIDTH + SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJTextField_from(), DATE_WIDTH, PARTS_HEIGHT, x, y);
			x += DATE_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_among("～"), AMONG_WIDTH, PARTS_HEIGHT, x, y);
			x += AMONG_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJTextField_to(), DATE_WIDTH, PARTS_HEIGHT, x, y);
			x += DATE_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJButton_same("同値"), BUTTON_WIDTH, PARTS_HEIGHT, x, y);
			x += BUTTON_WIDTH + SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJButton_clear("クリア"), BUTTON_WIDTH, PARTS_HEIGHT, xb, y);

			// ５行目
			y += PARTS_HEIGHT-5;
			x = SEP_WIDTH;
			CommonSwingUtils.putComponentOn(jPanel, getJLabel_note(), NOTE_WIDTH, NOTE_HEIGHT, x, y);
			y += NOTE_HEIGHT+SEP_HEIGHT;


			jPanel.setPreferredSize(new Dimension(PANEL_WIDTH, y));
			jPanel.setBorder(new LineBorder(Color.BLACK, 1));

			// ESCキーをショートカットに登録する（が何故か効かない）
			String ESCKEYACTION = "escape";
			InputMap imap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
			imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), ESCKEYACTION);
			getRootPane().getActionMap().put(ESCKEYACTION, new AbstractAction() {
				private static final long serialVersionUID = 1L;
				@Override
				public void actionPerformed(ActionEvent e) {
					doCancel();
				}
			});
		}

		return jPanel;
	}

	/*
	 * 「検索履歴」ラベル
	 */
	private JLabel getJLabel_swlist(String s) {
		if (jLabel_swlist == null) {
			jLabel_swlist = new JLabel(s);
		}
		return(jLabel_swlist);
	}

	/*
	 * 「検索履歴」コンボボックス
	 */
	private JComboBoxWithPopup getJComboBox_swlist() {
		if (jComboBox_swlist == null) {
			jComboBox_swlist = new JComboBoxWithPopup();
			jComboBox_swlist.setMaximumRowCount(32);
			jComboBox_swlist.addItemListener(il_swlistSelected);

//			jTextField_swlist = ((JTextField)jComboBox_swlist.getEditor().getEditorComponent());
		}

		return(jComboBox_swlist);
	}

	/*
	 * 「削除」ボタン
	 */
	private JButton getJButton_delete(String s) {
		if (jButton_delete == null) {
			jButton_delete = new JButton();
			jButton_delete.setText(s);
			jButton_delete.setForeground(Color.RED);

			jButton_delete.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					doDelete();
					jTextField_keyword.requestFocusInWindow();
					updateControlStatus();
				}
			});
		}
		return(jButton_delete);
	}

	/*
	 * 「キーワード」ラベル
	 */
	private JLabel getJLabel_keyword(String s) {
		if (jLabel_keyword == null) {
			jLabel_keyword = new JLabel(s);
		}
		return(jLabel_keyword);
	}

	/*
	 * 「キーワード」テキストフィールド
	 */
	private JTextField getJTextField_keyword() {
		if (jTextField_keyword == null) {
			jTextField_keyword = new JTextField();
			jTextField_keyword.addActionListener(al_search);
			jTextField_keyword.addKeyListener(kl_escape);
			jTextField_keyword.getDocument().addDocumentListener(dl_documentChanged);
		}

		return(jTextField_keyword);
	}

	/*
	 * 「検索」ボタン
	 */
	private JButton getJButton_search(String s) {
		if (jButton_search == null) {
			jButton_search = new JButton();
			jButton_search.setText(s);

			Font f = jButton_search.getFont();
			jButton_search.setFont(f.deriveFont(f.getStyle() | Font.BOLD, f.getSize()));

			jButton_search.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					doSearch();
				}
			});
		}
		return(jButton_search);
	}

	/*
	 * 「オプション」ラベル
	 */
	private JLabel getJLabel_options(String s) {
		if (jLabel_options == null) {
			jLabel_options = new JLabel(s);
		}
		return(jLabel_options);
	}

	/*
	 * 「番組名一致」チェックボックス
	 */
	private JCheckBox getJCheckBox_title(String s) {
		if (jCheckBox_title == null) {
			jCheckBox_title = new JCheckBox();
			jCheckBox_title.setText(s);
			jCheckBox_title.setSelected(true);
		}
		return(jCheckBox_title);
	}

	/*
	 * 「番組詳細一致」チェックボックス
	 */
	private JCheckBox getJCheckBox_detail(String s) {
		if (jCheckBox_detail == null) {
			jCheckBox_detail = new JCheckBox();
			jCheckBox_detail.setText(s);
			jCheckBox_detail.setSelected(true);
		}
		return(jCheckBox_detail);
	}

	/*
	 * 「絞り込み」チェックボックス
	 */
	private JCheckBox getJCheckBox_filter(String s) {
		if (jCheckBox_filter == null) {
			jCheckBox_filter = new JCheckBox();
			jCheckBox_filter.setText(s);
		}
		return(jCheckBox_filter);
	}

	/*
	 * 「キャンセル」ボタン
	 */
//	private JButton getJButton_cancel(String s) {
//		if (jButton_cancel == null) {
//			jButton_cancel = new JButton(s);
//			jButton_cancel.addMouseListener(new MouseAdapter() {
//				@Override
//				public void mouseClicked(MouseEvent e) {
//					doCancel();
//				}
//			});
//		}
//
//		return(jButton_cancel);
//	}

	/*
	 * 「過去ログ期間」ラベル
	 */
	private JLabel getJLabel_period(String s) {
		if (jLabel_period == null) {
			jLabel_period = new JLabel(s);
		}
		return(jLabel_period);
	}

	/*
	 * 「過去ログ期間開始」テキストフィールド
	 */
	private JTextField getJTextField_from() {
		if (jTextField_from == null) {
			jTextField_from = new JTextFieldWithPopup();

			jTextField_from.addActionListener(al_search);
			jTextField_from.addKeyListener(kl_escape);
			jTextField_from.getDocument().addDocumentListener(dl_documentChanged);
		}

		return(jTextField_from);
	}

	/*
	 * 「～」ラベル
	 */
	private JLabel getJLabel_among(String s) {
		if (jLabel_among == null) {
			jLabel_among = new JLabel(s);
			jLabel_among.setHorizontalAlignment(JLabel.CENTER);
		}
		return(jLabel_among);
	}

	/*
	 * 「過去ログ期間終了」テキストフィールド
	 */
	private JTextField getJTextField_to() {
		if (jTextField_to == null) {
			jTextField_to = new JTextFieldWithPopup();

			jTextField_to.addActionListener(al_search);
			jTextField_to.addKeyListener(kl_escape);
			jTextField_to.getDocument().addDocumentListener(dl_documentChanged);
		}

		return(jTextField_to);
	}

	/*
	 * 「同日」ボタン
	 */
	private JButton getJButton_same(String s) {
		if (jButton_same == null) {
			jButton_same = new JButton();
			jButton_same.setText(s);

			jButton_same.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					jTextField_to.setText(jTextField_from.getText());
				}
			});
		}
		return(jButton_same);
	}

	/*
	 * 注釈ラベル
	 */
	private JLabel getJLabel_note() {
		if (jLabel_note == null) {
			String s = "<html>※YYYY/MM/DDかMM/DDの形式で指定してください。<br>※YYYY/MM/DDで開始日のみ指定するとその日の過去ログが閲覧できます。</html>";
			jLabel_note = new JLabel(s);

		}
		return(jLabel_note);
	}

	/*
	 * 「クリア」ボタン
	 */
	private JButton getJButton_clear(String s) {
		if (jButton_clear == null) {
			jButton_clear = new JButton();
			jButton_clear.setText(s);

			jButton_clear.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					doClear();
					jComboBox_swlist.setSelectedItem("");
					jTextField_keyword.requestFocusInWindow();
				}
			});
		}
		return(jButton_clear);
	}

	/*******************************************************************************
	 * アクション
	 ******************************************************************************/
	/*
	 * クリアする
	 */
	protected void doClear(){
		jTextField_keyword.setText("");
		jTextField_from.setText("");
		jTextField_to.setText("");

		jCheckBox_title.setSelected(true);
		jCheckBox_detail.setSelected(true);
		jCheckBox_filter.setSelected(false);
	}

	/*
	 * 履歴を削除する
	 */
	protected void doDelete(){
		int no = jComboBox_swlist.getSelectedIndex();
		if (no < 1)
			return;

		swlist.getWordList().remove(no-1);
		swlist.save();
		updateKeywordComboBox();

		if (jComboBox_swlist.getItemCount() > no){
			jComboBox_swlist.setSelectedIndex(no);
			decodeKeyword((String)jComboBox_swlist.getSelectedItem());
		}
		else
			doClear();
	}

	/*
	 * キャンセルする
	 *
	 * @see tainavi.JEscCancelDialog#doCancel()
	 */
	@Override
	protected void doCancel() {
		setVisible(false);
	}

	/*
	 * 検索する
	 */
	protected boolean doSearch(){
		StringBuilder sb = new StringBuilder("");

		String keyword = jTextField_keyword.getText();

		String from = jTextField_from.getText();
		if (from.length() > 0){
			if (!checkDateFormat(from, true))
				return false;

			sb.append(from);
		}

		String to = jTextField_to.getText();
		if (to.length() > 0){
			if (!checkDateFormat(to, true))
				return false;

			if (sb.length() > 0)
				sb.append(" ");
			sb.append(to);
		}

		if (sb.length() == 0 && jCheckBox_filter.isSelected())
			sb.append("@filter");

		if (keyword.length() > 0){
			if (jCheckBox_title.isSelected() && jCheckBox_detail.isSelected())
				;
			else if (jCheckBox_title.isSelected()){
				if (sb.length() > 0)
					sb.append(" ");
				sb.append("#title");
			}
			else if (jCheckBox_detail.isSelected()){
				if (sb.length() > 0)
					sb.append(" ");
				sb.append("#detail");
			}

			if (sb.length() > 0)
				sb.append(" ");
			sb.append(keyword);
		}

		jToolbar.toolbarSearch(sb.toString());

		setVisible(false);

		return true;
	}

	/*
	 * 「検索履歴」コンボボックスを更新する
	 */
	protected void updateKeywordComboBox(){
		String str = (String)jComboBox_swlist.getSelectedItem();

		jComboBox_swlist.removeAllItems();

		jComboBox_swlist.addItem("");

		int num=0;
		for (SearchWordItem item : swlist.getWordList()){
			if (num >= MAX_SEARCH_WORDS)
				break;

			jComboBox_swlist.addItem(item.getKeyword());
			num++;
		}

		jComboBox_swlist.setSelectedItem(str);
	}

	/*
	 * 部品のステータスを更新する
	 */
	protected void updateControlStatus(){
		String keyword = jTextField_keyword.getText();
		String from = jTextField_from.getText();
		String to = jTextField_to.getText();
		boolean isSelected = jComboBox_swlist.getSelectedIndex() > 0;
		boolean haskey = keyword.length() > 0;
		boolean hasrange = from.length() > 0 || to.length() > 0;
		boolean hasfrom = from.length() == 10 && to.length() == 0;
		boolean passlog = !haskey && hasfrom;
		boolean passkey = hasrange;

		jButton_delete.setEnabled(isSelected);
		jButton_search.setEnabled(haskey || hasfrom);
		jButton_search.setText(passlog ? "過去ログ閲覧" : passkey ? "過去ログ検索" : "検索");
		jButton_same.setEnabled(hasrange);

		jCheckBox_filter.setEnabled(!hasrange);
		jTextField_to.setEnabled(from.length() > 0);

		jTextField_from.setForeground(checkDateFormat(from, false) ? Color.BLACK : Color.RED);
		jTextField_to.setForeground(checkDateFormat(to, false) ? Color.BLACK : Color.RED);
	}

	/*
	 * 過去日の年月日をチェックする
	 */
	private boolean checkPassedDate(String syear, String smonth, String sday, boolean msg){
		int month = Integer.parseInt(smonth);
		int day = Integer.parseInt(sday);

		if (month < 1 || month > 12 || day < 1 || day > 31)
			throw new NumberFormatException();

		String today = null;
		String date = null;
		GregorianCalendar c = new GregorianCalendar();
		if (syear == null){
			today = new SimpleDateFormat("MM/dd").format(c.getTime());
			date = String.format("%02d/%02d",  month, day);
		}
		else{
			int year = Integer.parseInt(syear);
			today = new SimpleDateFormat("yyyy/MM/dd").format(c.getTime());
			date = String.format("%04d/%02d/%02d", year, month, day);
		}

		if (date.compareTo(today) >= 0){
			if (msg)
				showWarnMessage(date + ":過去日を指定してください。");
			return false;
		}

		return true;
	}

	/*
	 * 日付のフォーマットをチェックする
	 */
	private boolean checkDateFormat(String str, boolean msg){
		if (str.length() == 0)
			return true;

		Matcher ma = Pattern.compile("^([0-9]{4})/([0-9]{2})/([0-9]{2})$").matcher(str);
		Matcher mb = Pattern.compile("^([0-9]{2})/([0-9]{2})$").matcher(str);

		try{
			if (ma.find()){
				if (!checkPassedDate(ma.group(1), ma.group(2), ma.group(3), msg))
					return false;
			}
			else if (mb.find()){
				if (!checkPassedDate(null, mb.group(1), mb.group(2), msg))
					return false;
			}
			else{
				throw new NumberFormatException();
			}
		}
		catch(NumberFormatException e){
			if (msg){
				showWarnMessage(str+":不正な日付です！「YYYY/MM/DD」ないし「MM/DD」で指定してください。");
			}
			return false;
		}

		return true;
	}

	/*
	 * 警告メッセージを表示する
	 */
	private void showWarnMessage(String msg){
		autoclose_enabled = false;
		JOptionPane.showConfirmDialog(null, msg, "警告", JOptionPane.CLOSED_OPTION);
		autoclose_enabled = true;
	}

	/*
	 * キーワードをデコードする
	 */
	private void decodeKeyword(String str){
		if (str == null || str.isEmpty())
			return;

		_decodeKeyword(str);
		updateControlStatus();

		jPanel.updateUI();
	}

	/*
	 * キーワードのデコードを実行する
	 */
	private void _decodeKeyword(String str){
		doClear();

		// 過去ログ閲覧
		if (str.matches("^\\d\\d\\d\\d/\\d\\d/\\d\\d$")) {
			jTextField_keyword.setText(str);
			return;
		}

		// 過去ログ検索
		Matcher ma = Pattern.compile("^(\\d\\d\\d\\d/)?(\\d\\d/\\d\\d)([ 　]+((\\d\\d\\d\\d/)?\\d\\d/\\d\\d))?[  　]+(.*)$").matcher(str);
		if (ma.find()) {
			String from = (ma.group(1) != null ? ma.group(1) : "") + ma.group(2);
			String to = ma.group(4);
			str = ma.group(6);

			jTextField_from.setText(from);
			jTextField_to.setText(to);
		}

		// 絞り込みあり
		Matcher mb = Pattern.compile("^@filter[ 　]+(.*)$").matcher(str);
		if ( mb.find() ) {
			str = mb.group(1);
			jCheckBox_filter.setSelected(true);
		}

		// オプションあり
		Matcher	mc = Pattern.compile("^(#title|#detail)?[  　]+(.*)$").matcher(str);
		if (mc.find()){
			jCheckBox_title.setSelected(!mc.group(1).equals("#detail"));
			jCheckBox_detail.setSelected(!mc.group(1).equals("#title"));
			jTextField_keyword.setText(mc.group(2));
		}
		// オプションなし
		else{
			jTextField_keyword.setText(str);
		}

		updateControlStatus();
		jTextField_keyword.requestFocusInWindow();
	}

	/*******************************************************************************
	 * リスナー
	 ******************************************************************************/
	/*
	 * ウインドウのオープン／クローズ等の変化
	 */
	private final WindowListener wl_panel = new WindowListener(){
		@Override
		public void windowOpened(WindowEvent e) {
		}

		@Override
		public void windowClosing(WindowEvent e) {
		}

		@Override
		public void windowClosed(WindowEvent e) {
		}

		@Override
		public void windowIconified(WindowEvent e) {
			if (autoclose_enabled)
				doCancel();
		}

		@Override
		public void windowDeiconified(WindowEvent e) {
		}

		@Override
		public void windowActivated(WindowEvent e) {
		}

		@Override
		public void windowDeactivated(WindowEvent e) {
			if (autoclose_enabled)
				doCancel();
		}
	};

	/*
	 * 「検索履歴」コンボボックスの項目変更
	 */
	private final ItemListener il_swlistSelected = new ItemListener() {

		@Override
		public void itemStateChanged(ItemEvent e) {
            switch (e.getStateChange()) {
                case ItemEvent.SELECTED:
                	decodeKeyword((String)jComboBox_swlist.getSelectedItem());
                    break;
            }
		}
	};

	/*
	 * テキストフィールドでのEnterキー
	 */
	private final ActionListener al_search = new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			if (jButton_search.isEnabled())
				doSearch();
		}
	};

	/**
	 * テキストフィールドでの文書変更
	 */
	private final DocumentListener dl_documentChanged = new DocumentListener(){
		@Override
		public void insertUpdate(DocumentEvent e) {
			updateControlStatus();
		}

		@Override
		public void removeUpdate(DocumentEvent e) {
			updateControlStatus();
		}

		@Override
		public void changedUpdate(DocumentEvent e) {
			updateControlStatus();
		}
	};

	/*
	 * テキストフィールドでのESCキー押下
	 */
	private final KeyListener kl_escape = new KeyListener(){
		@Override
		public void keyTyped(KeyEvent e) {
		}

		@Override
		public void keyPressed(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
				doCancel();
		}

		@Override
		public void keyReleased(KeyEvent e) {
		}
	};
}
