/* $Id: FlowDesignToolBar.java,v 1.2 2007/12/11 09:54:58 nito Exp $
 * 
 * Copyright (c)ARGO 21, Corporation. 2005, 2006.  All rights reserved.
 * 
 * This file is part of Nautica Workflow.
 * 
 *  Nautica Workflow is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 * 
 *  Nautica Workflow is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with Nautica Workflow; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
 */
package jp.co.argo21.nautica.tool.wfd;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;

import jp.co.argo21.nautica.commons.util.ResourceManager;
import jp.co.argo21.nautica.tool.wfd.dnd.ActivityItemContext;

/**
 * アクティビティ選択用バー。
 * 
 * @author  Norihiro Itoh(ARGO 21 Corp.)
 * @version $Revision: 1.2 $
 * @since   Nautica Workflow 1.0
 */
public class FlowDesignToolBar extends JToolBar
{
	/** シリアルバージョンID */
	private static final long serialVersionUID = 1L;

	/** フロー編集モードを表す定数 */
	public static final int POINT_MODE    = 1;
	/** 接続モードを表す定数 */
	public static final int CONNECT_MODE  = 2;
	/** シミュレーションモードを表す定数 */
	public static final int SIM_MODE      = 3;

	/** ボタンサイズ */
	private static final Dimension BUTTON_SIZE = new Dimension(50, 50);
	/** カーソルの位置 */
	private static final Point CURSOR_POINT = new Point(16, 16);

	/** フロー編集モードボタン */
	JToggleButton pointerButton;

	/** リスナー */
	private List<ModeChangeListener> listeners = new ArrayList<ModeChangeListener>();
	/** 現在のモード */
	private int mode = POINT_MODE;
	/** ドラッグ処理が可能かどうかを示すフラグ */
	private boolean draggable = true;

	/** フローアイテム選択ボタン一覧 */
	private ActivityItem[] buttons
		= new ActivityItem[WorkflowDesignerConstants.DROPPABLE_ITEMS.length];

	/**
	 * フローアイテム選択用バーを生成する。
	 */
	public FlowDesignToolBar()
	{
		ResourceManager rm = WorkflowDesignerManager.getResourceManager();
		
		setFloatable(false);
		
		ButtonGroup group = new ButtonGroup();

		pointerButton = new ModeButton("pointer");
		pointerButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					mode = POINT_MODE;
					setDraggable(true);
					fireModeChanged();
				}
			}
		);
		add(pointerButton);
		int maxItem = WorkflowDesignerConstants.DROPPABLE_ITEMS.length;
		for (int i = 0; i < maxItem; i++) {
			buttons[i]
				= new ActivityItem(WorkflowDesignerConstants.DROPPABLE_ITEMS[i]);
			add(buttons[i]);
		}

		JToggleButton connectButton = new ModeButton("connect");
		connectButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					mode = CONNECT_MODE;
					setDraggable(false);
					fireModeChanged();
				}
			}
		);
		add(connectButton);

		JToggleButton simulateButton = new ModeButton("simulate");
		simulateButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					mode = SIM_MODE;
					setDraggable(false);
					fireModeChanged();
				}
			}
		);
		add(simulateButton);

		addSeparator();

		JButton validateButton
			= new JButton(IconManager.getIcon("validation"));
		validateButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					WorkflowDesignerManager.getMainFrame().validatePackage();
				}
			}
		);
		validateButton.setPressedIcon(IconManager.getIcon("validation-s"));
		validateButton.setContentAreaFilled(false);
		validateButton.setFocusPainted(false);
		validateButton.setRolloverEnabled(true);
		validateButton.setBorderPainted(false);
		validateButton.setMaximumSize(BUTTON_SIZE);
		validateButton.setPreferredSize(BUTTON_SIZE);
		validateButton.setToolTipText(rm.getResource("FlowDesignToolBar.validation.tooltip"));
		add(validateButton);

		addSeparator();

		String iconName = WorkflowDesignerConstants.EL_PACKAGE;
		JButton packageButton = new JButton(IconManager.getIcon(iconName));
		packageButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					WorkflowDesignerManager.getMainFrame().showPackageInspector();
				}
			}
		);
		packageButton.setPressedIcon(IconManager.getIcon(iconName + "-s"));
		packageButton.setContentAreaFilled(false);
		packageButton.setFocusPainted(false);
		packageButton.setRolloverEnabled(true);
		packageButton.setBorderPainted(false);
		packageButton.setMaximumSize(BUTTON_SIZE);
		packageButton.setPreferredSize(BUTTON_SIZE);
		packageButton.setToolTipText(rm.getResource("FlowDesignToolBar.model.tooltip"));
		add(packageButton);

		group.add(pointerButton);
		group.add(connectButton);
		group.add(simulateButton);

		pointerButton.setSelected(true);
	}

	/**
	 * ツールバーの初期化を行う。
	 */	
	void init()
	{
		pointerButton.setSelected(true);
		listeners.clear();
	}

	/**
	 * モード変更リスナーを追加する。
	 * 
	 * @param l モード変更リスナー
	 */
	public void addModeChangedListener(ModeChangeListener l)
	{
		if (listeners.contains(l) == false) listeners.add(l);
	}

	/**
	 * モード変更リスナーを削除する。
	 * 
	 * @param l モード変更リスナー
	 */
	public void removeModeChangedListener(ModeChangeListener l)
	{
		if (listeners.contains(l)) listeners.remove(l);
	}

	/**
	 * モード変更リスナーに同報する。
	 */
	private void fireModeChanged()
	{
		for (ModeChangeListener l : listeners) {
			l.modeChanged(mode);
		}
	}

	/**
	 * ドラッグ可能かどうかを設定する。
	 * 
	 * 
	 * @param flag ドラッグ可能フラグ
	 */
	public void setDraggable(boolean flag)
	{
		this.draggable = flag;
		for (int i = 0; i < buttons.length; i++) {
			buttons[i].setEnabled(draggable);
		}
	}
	
	/**
	 * ドラッグ可能かどうかを返す。
	 * 
	 * 
	 * @return ドラッグ可能フラグ
	 */
	public boolean isDraggable()
	{
		return draggable;
	}

	/**
	 * モード変更ボタンコンポーネント
	 */
	class ModeButton extends JToggleButton
	{
		/** シリアルバージョンID */
		private static final long serialVersionUID = 1L;

		/**
		 * モード変更ボタンを生成する。
		 * 
		 * @param name	イメージ名称
		 */
		public ModeButton(String name)
		{
			ResourceManager rm = WorkflowDesignerManager.getResourceManager();
			setContentAreaFilled(false);
			setFocusPainted(false);
			setRolloverEnabled(true);
			setBorderPainted(false);
			setIcon(IconManager.getIcon(name));
			setSelectedIcon(IconManager.getIcon(name + "-s"));
			setMaximumSize(BUTTON_SIZE);
			setPreferredSize(BUTTON_SIZE);
			setToolTipText(rm.getResource("FlowDesignToolBar." + name + ".tooltip"));
		}
	}	

	/**
	 * アクティビティ選択ボタンコンポーネント
	 */
	class ActivityItem extends JLabel
	implements DragGestureListener
	{
		/** シリアルバージョンID */
		private static final long serialVersionUID = 1L;

		/** アクティビティパレット名 */
		private String name;
		
		/**
		 * アクティビティパレット表示用
		 * 
		 * @param name	アクティビティパレット名
		 */
		public ActivityItem(String name)
		{
			this.name = name;
			ResourceManager rm = WorkflowDesignerManager.getResourceManager();
			setBorder(BorderFactory.createLoweredBevelBorder());
			setBorderPainted(true);
			setIcon(IconManager.getIcon(name));
			setMaximumSize(BUTTON_SIZE);
			setPreferredSize(BUTTON_SIZE);
			setToolTipText(rm.getResource("FlowDesignToolBar." + name + ".tooltip"));
			DragSource dragSource = new DragSource();
			dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, this);
		}

		/*
		 * インタフェースDragGestureListener実装
		 */
		/**
		 * ドラッグ処理を開始する。
		 * 
		 * @param e	イベント
		 * @see java.awt.dnd.DragGestureListener#dragGestureRecognized(java.awt.dnd.DragGestureEvent)
		 */
		public void dragGestureRecognized(DragGestureEvent e)
		{
			if (isEnabled() == false) return;

			Point p = e.getDragOrigin();
			int ix = p.y / 50;		
			if (ix < 0) return;
			else if (ix >= WorkflowDesignerConstants.DROPPABLE_ITEMS.length) return;
			
			Transferable t = new ActivityItemContext(name);

			ImageIcon icon = (ImageIcon)IconManager.getIcon(name);
			Cursor cursor = Toolkit.getDefaultToolkit()
				.createCustomCursor(icon.getImage(), CURSOR_POINT, name);

			e.startDrag(cursor, t);
		}
	}	
}
