//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.richtext;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.epf.richtext.actions.IRichTextAction;
import org.eclipse.epf.richtext.actions.IRichTextComboAction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * The default rich text tool bar implementation.
 * 
 * @author Kelvin Low
 * @since 1.0
 */
public class RichTextToolBar extends Composite implements IRichTextToolBar {

	private static final String LAST_KEY_CODE = "lastKeyCode"; //$NON-NLS-1$

	// The parent rich text control.
	private IRichText richText;

	// If true, add a new tool bar.
	private boolean addToolBar = true;

	// The current tool bar used to populate the tool actions.
	private ToolBar currentToolBar;

	// The action items in the tool bar(s).
	private List actionItems = new ArrayList();

	/**
	 * Creates a new instance.
	 * 
	 * @param parent
	 *            the parent composite
	 * @param style
	 *            the tool bar style
	 * @param richText
	 *            the parent rich text control
	 */
	public RichTextToolBar(Composite parent, int style, IRichText richText) {
		super(parent, style);
		this.richText = richText;

		GridLayout layout = new GridLayout(10, false);
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		super.setLayout(layout);
	}

	/**
	 * Adds a button action to the tool bar.
	 * 
	 * @param action
	 *            the action to add
	 */
	public void addAction(final IRichTextAction action) {
		if (action != null) {
			addToolBar();
			ToolItem item = new ToolItem(currentToolBar, SWT.NONE);
			item.setImage(action.getImage());
			item.setDisabledImage(action.getDisabledImage());
			item.setToolTipText(action.getToolTipText());
			item.setEnabled(action.getEnabled());
			item.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent event) {
					action.execute(richText);
				};
			});
			item.setData(action);			
			actionItems.add(item);
		}
	}

	/**
	 * Adds a combo action to the tool bar.
	 * 
	 * @param action
	 *            the action to add
	 */
	public void addAction(final IRichTextComboAction action) {
		if (action != null) {
			Combo combo = new Combo(this, SWT.READ_ONLY | SWT.FLAT);
			String[] items = action.getItems();
			for (int i = 0; i < items.length; i++) {
				combo.add(items[i]);
			}
			combo.setVisibleItemCount(combo.getItemCount());
			combo.select(0);
			combo.setToolTipText(action.getToolTipText());
			combo.setEnabled(action.getEnabled());
			combo.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent event) {
					String lastKeyCode = (String) getData(LAST_KEY_CODE);
					if (lastKeyCode == null || lastKeyCode.equals("" + SWT.CR)) { //$NON-NLS-1$
						Object eventSrc = event.getSource();
						if (eventSrc instanceof Combo) {
							action.execute(richText, ((Combo) eventSrc)
									.getSelectionIndex());
						}
					}
					setData(LAST_KEY_CODE, null);
				};
			});
			combo.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent event) {
					if (event.keyCode == SWT.CR) {
						Object eventSrc = event.getSource();
						if (eventSrc instanceof Combo) {
							action.execute(richText, ((Combo) eventSrc)
									.getSelectionIndex());
						}
					}
					setData(LAST_KEY_CODE, "" + event.keyCode); //$NON-NLS-1$
				};
			});
			actionItems.add(combo);
			addToolBar = true;
		}
	}

	/**
	 * Adds a separator to the tool bar.
	 */
	public void addSeparator() {
		addToolBar();
		new ToolItem(currentToolBar, SWT.SEPARATOR);
	}

	/**
	 * Updates the toolbar state.
	 * <p>
	 * Enables/disables actions depending on the currently selected
	 * RichTextEditor tab (RichText vs. HTML)
	 * 
	 * @param editable specifies whether to enable non-ReadOnly commands
	 */
	public void updateToolBar(boolean editable) {
		boolean richTextMode = true;
		if (richText instanceof RichTextEditor
				&& ((RichTextEditor) richText).isHTMLTabSelected()) {
			richTextMode = false;
		}
		for (Iterator i = actionItems.iterator(); i.hasNext();) {
			Object item = i.next();
			if (item instanceof ToolItem) {
				boolean enabledToolItem = true;				
				ToolItem toolItem = (ToolItem) item;
				IRichTextAction action = (IRichTextAction)toolItem.getData();
				if (action != null && !editable && action.disableInReadOnlyMode()) {
					enabledToolItem = false;
				}
				if (action != null && !richTextMode && action.disableInSourceMode()) {
					enabledToolItem = false;
				}
				toolItem.setEnabled(enabledToolItem);
			} else if (item instanceof Combo) {
				if (richTextMode && editable) {
					((Combo) item).setEnabled(true);
				} else {
					((Combo) item).setEnabled(false);
				}
			}
		}
	}

	/**
	 * Adds a tool bar, if necessary, to contain a button action or separator.
	 */
	protected void addToolBar() {
		if (addToolBar) {
			currentToolBar = new ToolBar(this, getStyle());
			currentToolBar.setLayout(new FillLayout());
			addToolBar = false;
		}
	}

}
