package org.eclipse.swt.custom;

/*
 * Copyright (c) 2000, 2002 IBM Corp.  All rights reserved.
 * This file is made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 */

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.accessibility.*;

/**
 * Instances of this class implement the notebook user interface
 * metaphor.  It allows the user to select a notebook page from
 * set of pages.
 * <p>
 * The item children that may be added to instances of this class
 * must be of type <code>CTabItem</code>.
 * <code>Control</code> children are created and then set into a
 * tab item using <code>CTabItem#setControl</code>.
 * </p><p>
 * Note that although this class is a subclass of <code>Composite</code>,
 * it does not make sense to set a layout on it.
 * </p><p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>TOP, BOTTOM, FLAT</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Selection</dd>
 * <dd>"CTabFolder"</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles TOP and BOTTOM 
 * may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 */
 
public class CTabFolder extends Composite {
	
	/**
	 * marginWidth specifies the number of pixels of horizontal margin
	 * that will be placed along the left and right edges of the form.
	 *
	 * The default value is 0.
	 */
 	public int marginWidth = 0;
	/**
	 * marginHeight specifies the number of pixels of vertical margin
	 * that will be placed along the top and bottom edges of the form.
	 *
	 * The default value is 0.
	 */
 	public int marginHeight = 0;
	
	/**
	 * Color of innermost line of drop shadow border.
	 */
	public static RGB borderInsideRGB  = new RGB (132, 130, 132);
	/**
	 * Color of middle line of drop shadow border.
	 */
	public static RGB borderMiddleRGB  = new RGB (143, 141, 138);
	/**
	 * Color of outermost line of drop shadow border.
	 */
	public static RGB borderOutsideRGB = new RGB (171, 168, 165); 
	
	/*
	 * A multiple of the tab height that specifies the minimum width to which a tab 
	 * will be compressed before scrolling arrows are used to navigate the tabs.
	 */
	public int MIN_TAB_WIDTH = 3;

	/* sizing, positioning */
	int xClient, yClient;
	boolean onBottom = false;
	int fixedTabHeight = 0;
	
	/* item management */
	private CTabItem items[] = new CTabItem[0];
	private int selectedIndex = -1;
	int topTabIndex = -1; // index of the left most visible tab.

	/* External Listener management */
	private CTabFolderListener[] tabListeners = new CTabFolderListener[0];
	
	/* Color appearance */
	Image backgroundImage;
	Color[] gradientColors;
	int[] gradientPercents;
	Color selectionForeground;
	Color background;

	// internal constants
	private static final int DEFAULT_WIDTH = 64;
	private static final int DEFAULT_HEIGHT = 64;
	
	// scrolling arrows
	private ToolBar arrowBar;
	private Image arrowLeftImage;
	private Image arrowRightImage;
	
	// close button
	boolean showClose = false;
	private Image closeImage;
	ToolBar closeBar;
	private ToolBar inactiveCloseBar;
	private CTabItem inactiveItem;	
	
	// borders
	boolean showBorders = false;
	private int borderBottom = 0;
	private int borderLeft = 0;
	private int borderRight = 0;
	private int borderTop = 0;
	private Color borderColor1;
	private Color borderColor2;
	private Color borderColor3;

	// when disposing CTabFolder, don't try to layout the items or 
	// change the selection as each child is destroyed.
	private boolean inDispose = false;

	// keep track of size changes in order to redraw only affected area
	// on Resize
	private Point oldSize;
	
	// insertion marker
	int insertionIndex = -2; // Index of insert marker.  Marker always shown after index.
	                         // -2 means no insert marker
	                         
	// tool tip
	private Shell tip;
	private Label label;
	private boolean showToolTip = false;
	private CTabItem toolTipItem;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together 
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 * </ul>
 *
 * @see SWT#TOP
 * @see SWT#BOTTOM
 * @see SWT#FLAT
 * @see #getStyle
 */
public CTabFolder(Composite parent, int style) {
	super(parent, checkStyle (style));
	
	onBottom = (getStyle() & SWT.BOTTOM) != 0;
	
	borderColor1 = new Color(getDisplay(), borderInsideRGB);
	borderColor2 = new Color(getDisplay(), borderMiddleRGB);
	borderColor3 = new Color(getDisplay(), borderOutsideRGB);

	// tool tip support
	Display display = getDisplay();
	tip = new Shell (getShell(), SWT.ON_TOP);
	label = new Label (tip, SWT.CENTER);
	
	// Add all listeners
	Listener listener = new Listener() {
		public void handleEvent(Event event) {
			switch (event.type) {
				case SWT.Dispose:           onDispose(); break;
				case SWT.Paint:             onPaint(event);	break;
				case SWT.Resize:            onResize();	break;
				case SWT.MouseDoubleClick:  onMouseDoubleClick(event);	break;
				case SWT.MouseDown:         onMouseDown(event);	break;
				case SWT.MouseExit:         onMouseExit(event);	break;
				case SWT.MouseHover:		onMouseHover(event);	break;
				case SWT.MouseMove:         onMouseMove(event);	break;
				case SWT.FocusIn:           onFocus(event);	break;
				case SWT.FocusOut:          onFocus(event);	break;
				case SWT.KeyDown:           onKeyDown(event); break;
				case SWT.Traverse:          onTraverse(event); break;
			}
		}
	};

	int[] folderEvents = new int[]{
		SWT.Dispose,
		SWT.Paint,
		SWT.Resize,  
		SWT.MouseDoubleClick, 
		SWT.MouseDown, 
		SWT.MouseExit,
		SWT.MouseHover, 
		SWT.MouseMove,
		SWT.FocusIn, 
		SWT.FocusOut, 
		SWT.KeyDown,
		SWT.Traverse,
	};
	for (int i = 0; i < folderEvents.length; i++) {
		addListener(folderEvents[i], listener);
	}
	
	createArrowBar();
	createCloseBar();
	
	setBorderVisible((style & SWT.BORDER) != 0);
	
	initAccessible();	

}
private static int checkStyle (int style) {
	int mask = SWT.TOP | SWT.BOTTOM | SWT.FLAT;
	style = style & mask;
	// TOP and BOTTOM are mutually exlusive.
	// TOP is the default
	if ((style & SWT.TOP) != 0) 
		style = style & ~(SWT.TOP | SWT.BOTTOM) | SWT.TOP;
	// reduce the flash by not redrawing the entire area on a Resize event
	style |= SWT.NO_REDRAW_RESIZE;
	return style;
}
/**	 
* Adds the listener to receive events.
* <p>
*
* @param listener the listener
*
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
* 		<li>ERROR_NULL_ARGUMENT when listener is null</li>
*	</ul>
*/
public void addSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	TypedListener typedListener = new TypedListener(listener);
	addListener(SWT.Selection, typedListener);
	addListener(SWT.DefaultSelection, typedListener);
}
/**
 * Adds the listener to the collection of listeners who will
 * be notified when a tab item is closed.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 *      <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 *
 * @see CTabFolderListener
 * @see #removeCTabFolderListener
 */
public void addCTabFolderListener(CTabFolderListener listener) {
	checkWidget();
	if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	// add to array
	CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length + 1];
	System.arraycopy(tabListeners, 0, newTabListeners, 0, tabListeners.length);
	tabListeners = newTabListeners;
	tabListeners[tabListeners.length - 1] = listener;
	showClose = true;
	setButtonBounds();
}
void onClientAreaChange() {
	oldSize = null;
	notifyListeners(SWT.Resize, new Event());
}
private void closeNotify(CTabItem item, int time) {
	if (item == null) return;
	
	CTabFolderEvent event = new CTabFolderEvent(this);
	event.widget = this;
	event.time = time;
	event.item = item;
	event.doit = true;
	if (tabListeners != null) {
		for (int i = 0; i < tabListeners.length; i++) {
			tabListeners[i].itemClosed(event);
		}
	}
	if (event.doit) {
		item.dispose();
	}
}
public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	int minWidth = 0;
	int minHeight = 0;

	// preferred width of tab area to show all tabs
	GC gc = new GC(this);
	for (int i = 0; i < items.length; i++) {
		minWidth += items[i].preferredWidth(gc);
	}
	gc.dispose();

	// preferred size of controls in tab items
	for (int i = 0; i < items.length; i++) {
		Control control = items[i].getControl();
		if (control != null && !control.isDisposed()){
			Point size = control.computeSize (wHint, hHint);
			minWidth = Math.max (minWidth, size.x);
			minHeight = Math.max (minHeight, size.y);
		}
	}
	if (minWidth == 0) minWidth = DEFAULT_WIDTH;
	if (minHeight == 0) minHeight = DEFAULT_HEIGHT;

	if (wHint != SWT.DEFAULT) minWidth  = wHint;
	if (hHint != SWT.DEFAULT) minHeight = hHint;

	Rectangle trim = computeTrim(0, 0, minWidth, minHeight);
	return new Point (trim.width, trim.height);
}
public Rectangle computeTrim (int x, int y, int width, int height) {
	checkWidget();
	if (items.length == 0) {
		if (!showBorders) return new Rectangle(x, y, width, height);
		int trimX = x - borderRight - 1;
		int trimY = y - borderBottom - 1;
		int trimWidth = width + borderRight + 2;
		int trimHeight = height + borderBottom + 2;
		return new Rectangle (trimX, trimY, trimWidth, trimHeight);
	} else {
		int tabHeight = getTabHeight();
		int trimX = x - marginWidth - borderLeft;
		int trimY = y - marginHeight - tabHeight - borderTop - 1;
		// -1 is for the line at the bottom of the tabs
		if (onBottom) {
			trimY = y - marginHeight - borderTop;
		}
		int trimWidth = width + borderLeft + borderRight + 2*marginWidth;
		int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + 1;
		return new Rectangle (trimX, trimY, trimWidth, trimHeight);
	}
}
/**
 * Create the specified item at 'index'.
 */
void createItem (CTabItem item, int index) {
	if (0 > index || index > getItemCount ()){ 
		SWT.error (SWT.ERROR_INVALID_RANGE);
	}
	// grow by one and rearrange the array.
	CTabItem[] newItems = new CTabItem [items.length + 1];
	System.arraycopy(items, 0, newItems, 0, index);
	newItems[index] = item;
	System.arraycopy(items, index, newItems, index + 1, items.length - index);
	items = newItems;
	
	item.parent = this;
	
	if (selectedIndex >= index) {
		 selectedIndex ++;
	}
	if (items.length == 1) {
		topTabIndex = 0;
	}
	setItemBounds();
	showItem(item);
	
	if (items.length == 1) {
		redraw();
	} else {
		redrawTabArea(-1);
	}
}

private void createArrowBar() {
	// create arrow buttons for scrolling 
	arrowBar = new ToolBar(this, SWT.FLAT);
	arrowBar.setVisible(false);
	arrowBar.setBackground(background);
	ToolItem scrollLeft = new ToolItem(arrowBar, SWT.PUSH);
	scrollLeft.setEnabled(false);
	ToolItem scrollRight = new ToolItem(arrowBar, SWT.PUSH);
	scrollRight.setEnabled(false);
	
	scrollLeft.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
			scroll_scrollLeft();
		}
	});
	scrollRight.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
			scroll_scrollRight();
		}
	});
	
}
private void createCloseBar() {
	closeBar = new ToolBar(this, SWT.FLAT);
	closeBar.setVisible(false);
	if (gradientColors != null && gradientColors.length > 0) {
		closeBar.setBackground(gradientColors[gradientColors.length - 1]);
	} else {
		closeBar.setBackground(background);
	}
	ToolItem closeItem = new ToolItem(closeBar, SWT.PUSH);
	
	inactiveCloseBar = new ToolBar(this, SWT.FLAT);
	inactiveCloseBar.setVisible(false);
	inactiveCloseBar.setBackground(background);
	ToolItem inactiveCloseItem = new ToolItem(inactiveCloseBar, SWT.PUSH);

	closeItem.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
			closeNotify(getSelection(), event.time);
		}
	});
	inactiveCloseItem.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
			closeNotify(inactiveItem, event.time);
			inactiveCloseBar.setVisible(false);
			inactiveItem = null;
		}
	});
	inactiveCloseBar.addListener (SWT.MouseExit, new Listener() {
		public void handleEvent(Event event) {
			if (inactiveItem != null) {
				Rectangle itemBounds = inactiveItem.getBounds();
				if (itemBounds.contains(event.x, event.y)) return;
			}
			inactiveCloseBar.setVisible(false);
			inactiveItem = null;
		}
	});
	
}
/**
 * Destroy the specified item.
 */
void destroyItem (CTabItem item) {
	if (inDispose) return;
	
	int index = indexOf(item);
	if (index == -1) return; 	// should this trigger an error?
	
	insertionIndex = -2;
	
	if (items.length == 1) {
		items = new CTabItem[0];
		selectedIndex = -1;
		topTabIndex = 0;
		
		Control control = item.getControl();
		if (control != null && !control.isDisposed()) {
			control.setVisible(false);
		}
		closeBar.setVisible(false);
		redraw();
		return;
	} 
		
	// shrink by one and rearrange the array.
	CTabItem[] newItems = new CTabItem [items.length - 1];
	System.arraycopy(items, 0, newItems, 0, index);
	System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
	items = newItems;
	
	if (topTabIndex == items.length) {
		--topTabIndex;
	}
	
	// move the selection if this item is selected
	if (selectedIndex == index) {
		Control control = item.getControl();
		if (control != null && !control.isDisposed()) {
			control.setVisible(false);
		}
		selectedIndex = -1;
		setSelection(Math.max(0, index - 1), true);
	} else if (selectedIndex > index) {
		selectedIndex --;
	}
	
	setItemBounds();
	redrawTabArea(-1);
}
private void onKeyDown(Event e) {
	if (e.keyCode == SWT.ARROW_LEFT) {
		if (selectedIndex > 0) {
			setSelection(selectedIndex - 1, true);
		}
	}
	if (e.keyCode == SWT.ARROW_RIGHT) {
		if (selectedIndex < items.length - 1) {
			setSelection(selectedIndex + 1, true);
		}
	}
}
/**
 * Dispose the items of the receiver
 */
private void onDispose() {
	/*
	 * Usually when an item is disposed, destroyItem will change the size of the items array, 
	 * reset the bounds of all the tabs and manage the widget associated with the tab.
	 * Since the whole folder is being disposed, this is not necessary.  For speed
	 * the inDispose flag is used to skip over this part of the item dispose.
	 */
	inDispose = true;
	
	int length = items.length;
	for (int i = 0; i < length; i++) {						
		if (items[i] != null) {
			items[i].dispose();
		}
	}
	
	// clean up resources
	if (tip != null  && !tip.isDisposed()) {
		tip.dispose();
		tip = null;
		label = null;
	}
	
	if (arrowLeftImage != null) arrowLeftImage.dispose();
	arrowLeftImage = null;
	if (arrowRightImage != null) arrowRightImage.dispose();
	arrowRightImage = null;
	if (closeImage != null) closeImage.dispose();
	closeImage = null;
	
	gradientColors = null;
	gradientPercents = null;
	backgroundImage = null;

	if (borderColor1 != null) borderColor1.dispose();
	borderColor1 = null;
	
	if (borderColor2 != null) borderColor2.dispose();
	borderColor2 = null;
	
	if (borderColor3 != null) borderColor3.dispose();
	borderColor3 = null;
}
private void onFocus(Event e) {
	checkWidget();
	if (selectedIndex >= 0) {
		redrawTabArea(selectedIndex);
	} else {
		setSelection(0, true);
	}
}
/** 
 * Draw a border around the receiver.
 */
private void drawBorder(GC gc) {
	
	Rectangle d = super.getClientArea();
	
	if (showBorders) {
		if ((getStyle() & SWT.FLAT) != 0) {
			gc.setForeground(borderColor1);
			gc.drawRectangle(d.x, d.y, d.x + d.width - 1, d.y + d.height - 1);
		} else {
			gc.setForeground(borderColor1);
			gc.drawRectangle(d.x, d.y, d.x + d.width - 3, d.y + d.height - 3);
		
			gc.setForeground(borderColor2);
			gc.drawLine(d.x + 1,           d.y + d.height - 2, d.x + d.width - 1, d.y + d.height - 2);
			gc.drawLine(d.x + d.width - 2, d.y + 1,            d.x + d.width - 2, d.y + d.height - 1);
		
			gc.setForeground(borderColor3);
			gc.drawLine(d.x + 2,           d.y + d.height - 1, d.x + d.width - 2, d.y + d.height - 1);
			gc.drawLine(d.x + d.width - 1, d.y + 2,            d.x + d.width - 1, d.y + d.height - 2);
		
			// fill in corners with parent's background
			gc.setForeground(getParent().getBackground());
			gc.drawLine(d.x + d.width - 2, d.y,     d.x + d.width - 1, d.y);
			gc.drawLine(d.x + d.width - 1, d.y + 1, d.x + d.width - 1, d.y + 1);
		
			gc.drawLine(d.x, d.y + d.height - 2, d.x,     d.y + d.height - 2);
			gc.drawLine(d.x, d.y + d.height - 1, d.x + 1, d.y + d.height - 1);
		
			gc.drawLine(d.x + d.width - 1, d.y + d.height - 1, d.x + d.width - 1, d.y + d.height - 1);
		}
		
	}

	// draw a separator line
	if (items.length > 0) {	
		int tabHeight = getTabHeight();
		int lineY = d.y + borderTop + tabHeight;
		if (onBottom) {
			lineY = d.y + d.height - borderBottom - tabHeight - 1;
		}
		gc.setForeground(borderColor1);
		gc.drawLine(d.x + borderLeft, lineY, d.x + d.width - borderRight, lineY);
	}

	gc.setForeground(getForeground());
}
public Rectangle getClientArea() {
	checkWidget();
	Point size = getSize();
	if (items.length == 0) {
		if (!showBorders) return super.getClientArea();
		int width = size.x - borderRight - 2;
		int height = size.y - borderBottom - 2;
		return new Rectangle(borderRight + 1, borderBottom + 1, width, height);	
	} else {
		int width = size.x - 2*marginWidth - borderLeft - borderRight;
		int height = size.y - 2*marginHeight - borderTop - borderBottom - getTabHeight() - 1;
		return new Rectangle(xClient, yClient, width, height);
	}
}
/**
 * Returns the height of the tab
 * 
 * @return the height of the tab
 * 
 * @exception SWTError <ul>
 *		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 *	</ul>
 */
public int getTabHeight(){
	checkWidget();
	if (fixedTabHeight > 0) return fixedTabHeight;

	int tempHeight = 0;
	GC gc = new GC(this);
	for (int i=0; i < items.length; i++) { 
		tempHeight = Math.max(tempHeight, items[i].preferredHeight(gc));
	}
	gc.dispose();
	return tempHeight;
}
/**
 * Return the tab that is located at the specified index.
 * 
 * @return the item at the specified index
 */
public CTabItem getItem (int index) {
	//checkWidget();
	if (index  < 0 || index >= items.length) 
		SWT.error(SWT.ERROR_INVALID_RANGE);
	return items [index];
}
/**
* Gets the item at a point in the widget.
* <p>
*
* @return the item at a point
*/
public CTabItem getItem (Point pt) {
	//checkWidget();
	if (items.length == 0) return null;
	int lastItem = getLastItem();
	lastItem = Math.min(items.length - 1, lastItem + 1);
	for (int i = topTabIndex; i <= lastItem; i++) {
		Rectangle bounds = items[i].getBounds();
		if (bounds.contains(pt)) return items[i];
	}
	return null;
}
/**
 * Return the number of tabs in the folder.
 * 
 * @return the number of tabs in the folder
 */
public int getItemCount(){
	//checkWidget();
	return items.length;
}
/**
 * Return the tab items.
 * 
 * @return the tab items
 */
public CTabItem [] getItems() {
	//checkWidget();
	CTabItem[] tabItems = new CTabItem [items.length];
	System.arraycopy(items, 0, tabItems, 0, items.length);
	return tabItems;
}
private int getLastItem(){
	if (items.length == 0) return -1;
	if (!scroll_leftVisible() && !scroll_rightVisible()) return items.length -1;
	Rectangle area = getClientArea();
	if (area.width <= 0) return 0;
	int width = area.width - arrowBar.getSize().x;
	int index = topTabIndex;
	int tabWidth = items[index].width;
	while (index < items.length - 1) {
		tabWidth += items[index + 1].width;
		if (tabWidth > width) break;
		index++;
	}
	return index;
}
/**
 * Return the selected tab item, or an empty array if there
 * is no selection.
 * 
 * @return the selected tab item
 */
public CTabItem getSelection() {
	//checkWidget();
	if (selectedIndex == -1) return null;
	return items[selectedIndex];
}
/**
 * Return the index of the selected tab item, or -1 if there
 * is no selection.
 * 
 * @return the index of the selected tab item or -1
 */
public int getSelectionIndex() {
	//checkWidget();
	return selectedIndex;
}

/**
 * Return the index of the specified tab or -1 if the tab is not 
 * in the receiver.
 * 
 * @return the index of the specified tab item or -1
 * 
 * @exception SWTError <ul>
 *      <li>ERROR_NULL_ARGUMENT when the item is null</li>
 *	</ul>
 */
public int indexOf(CTabItem item) {
	//checkWidget();
	if (item == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	for (int i = 0; i < items.length; i++) {
		if (items[i] == item) return i;
	}
	return -1;
}

private void initAccessible() {
	final Accessible accessible = getAccessible();
	accessible.addAccessibleListener(new AccessibleAdapter() {
		public void getName(AccessibleEvent e) {
			String name = null;
			int childID = e.childID;
			if (childID >= 0 && childID < items.length) {
				name = items[childID].getText();
				int index = name.indexOf('&');
				if (index > 0) {
					name = name.substring(0, index) + name.substring(index + 1);
				}
			}
			e.result = name;
		}

		public void getHelp(AccessibleEvent e) {
			String help = null;
			int childID = e.childID;
			if (childID == ACC.CHILDID_SELF) {
				help = getToolTipText();
			} else if (childID >= 0 && childID < items.length) {
				help = items[childID].getToolTipText();
			}
			e.result = help;
		}
		
		public void getKeyboardShortcut(AccessibleEvent e) {
			String shortcut = null;
			int childID = e.childID;
			if (childID >= 0 && childID < items.length) {
				String text = items[childID].getText();
				if (text != null) {
					char mnemonic = getMnemonic(text);	
					if (mnemonic != '\0') {
						shortcut = "Alt+"+mnemonic;
					}
				}
			}
			e.result = shortcut;
		}
	});
	
	accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
		public void getChildAtPoint(AccessibleControlEvent e) {
			Point testPoint = toControl(new Point(e.x, e.y));
			int childID = ACC.CHILDID_NONE;
			for (int i = 0; i < items.length; i++) {
				if (items[i].getBounds().contains(testPoint)) {
					childID = i;
					break;
				}
			}
			if (childID == ACC.CHILDID_NONE) {
				Rectangle location = getBounds();
				location.height = location.height - getClientArea().height;
				if (location.contains(testPoint)) {
					childID = ACC.CHILDID_SELF;
				}
			}
			e.childID = childID;
		}

		
		public void getLocation(AccessibleControlEvent e) {
			Rectangle location = null;
			int childID = e.childID;
			if (childID == ACC.CHILDID_SELF) {
				location = getBounds();
			}
			if (childID >= 0 && childID < items.length) {
				location = items[childID].getBounds();
			}
			if (location != null) {
				Point pt = toDisplay(new Point(location.x, location.y));
				e.x = pt.x;
				e.y = pt.y;
				e.width = location.width;
				e.height = location.height;
			}
		}
		
		public void getChildCount(AccessibleControlEvent e) {
			e.detail = items.length;
		}
		
		public void getDefaultAction(AccessibleControlEvent e) {
			String action = null;
			int childID = e.childID;
			if (childID >= 0 && childID < items.length) {
				action = "Switch";
			}
			e.result = action;
		}

		public void getFocus(AccessibleControlEvent e) {
			int childID = ACC.CHILDID_NONE;
			if (isFocusControl()) {
				if (selectedIndex == -1) {
					childID = ACC.CHILDID_SELF;
				} else {
					childID = selectedIndex;
				}
			}
			e.childID = childID;
		}

		public void getRole(AccessibleControlEvent e) {
			int role = 0;
			int childID = e.childID;
			if (childID == ACC.CHILDID_SELF) {
				role = ACC.ROLE_TABFOLDER;
			} else if (childID >= 0 && childID < items.length) {
				role = ACC.ROLE_TABITEM;
			}
			e.detail = role;
		}
		
		public void getSelection(AccessibleControlEvent e) {
			e.childID = (selectedIndex == -1) ? ACC.CHILDID_NONE : selectedIndex;
		}
		
		public void getState(AccessibleControlEvent e) {
			int state = 0;
			int childID = e.childID;
			if (childID == ACC.CHILDID_SELF) {
				state = ACC.STATE_NORMAL;
			} else if (childID >= 0 && childID < items.length) {
				state = ACC.STATE_SELECTABLE;
				if (isFocusControl()) {
					state |= ACC.STATE_FOCUSABLE;
				}
				if (selectedIndex == childID) {
					state |= ACC.STATE_SELECTED;
					if (isFocusControl()) {
						state |= ACC.STATE_FOCUSED;
					}
				}
			}
			e.detail = state;
		}
		
		public void getChildren(AccessibleControlEvent e) {
			Object[] children = new Object[items.length];
			for (int i = 0; i < items.length; i++) {
				children[i] = new Integer(i);
			}
			e.children = children;
		}
	});
	
	addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
			if (isFocusControl()) {
				if (selectedIndex == -1) {
					accessible.setFocus(ACC.CHILDID_SELF);
				} else {
					accessible.setFocus(selectedIndex);
				}
			}
		}
	});

	addListener(SWT.FocusIn, new Listener() {
		public void handleEvent(Event event) {
			if (selectedIndex == -1) {
				accessible.setFocus(ACC.CHILDID_SELF);
			} else {
				accessible.setFocus(selectedIndex);
			}
		}
	});
}

private void setButtonBounds() {
	
	updateArrowBar();
	updateCloseBar();
	
	int tabHeight = getTabHeight();
	Rectangle area = super.getClientArea();
	
	boolean leftVisible = scroll_leftVisible();
	boolean rightVisible = scroll_rightVisible();
	if (leftVisible || rightVisible) {
		Point size = arrowBar.computeSize(SWT.DEFAULT, tabHeight);
		int x = area.x + area.width - borderRight - size.x;
		int y = (onBottom) ? area.y + area.height - borderBottom - size.y : area.y + borderTop;
		
		arrowBar.setBounds(x, y, size.x, size.y);
		ToolItem[] items = arrowBar.getItems();
		items[0].setEnabled(leftVisible);
		items[1].setEnabled(rightVisible);
		arrowBar.setVisible(true);
	} else {
		arrowBar.setVisible(false);
	}
	
	// When the close button is right at the edge of the Tab folder, hide it because
	// otherwise it may block off a part of the border on the right
	if (showClose) {
		inactiveCloseBar.setVisible(false);
		CTabItem item = getSelection();
		if (item == null) {
			closeBar.setVisible(false);
		} else {
			int toolbarHeight = tabHeight - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN + 2; // +2 to ignore gab between focus rectangle
			Point size = closeBar.computeSize(SWT.DEFAULT, toolbarHeight);
			int x = item.x + item.width - size.x - 2; // -2 to not overlap focus rectangle and trim
			int y = item.y + Math.max(0, (item.height - toolbarHeight)/2);		
			closeBar.setBounds(x, y, size.x, toolbarHeight);
			if (scroll_leftVisible() || scroll_rightVisible()) {
				Rectangle arrowRect = arrowBar.getBounds();
				arrowRect.width += borderRight;
				closeBar.setVisible(!arrowRect.contains(x, y));
			} else {
				closeBar.setVisible(true);
			}
		}
	}
}
private boolean setItemLocation() {
	if (items.length == 0) return false;
	Rectangle area = super.getClientArea();
	int x = area.x;
	int y = area.y + borderTop;
	if (onBottom) {
		int tabHeight = getTabHeight();
		y = Math.max(0, area.y + area.height - borderBottom - tabHeight);
	}
	boolean changed = false;
	for (int i = topTabIndex - 1; i>=0; i--) { 
		// if the first visible tab is not the first tab
		CTabItem tab = items[i];
		x -= tab.width; 
		if (!changed && (tab.x != x || tab.y != y) ) changed = true;
		// layout tab items from right to left thus making them invisible
		tab.x = x;
		tab.y = y;
	}
	
	x = area.x + borderLeft;
	for (int i = topTabIndex; i < items.length; i++) {
		// continue laying out remaining, visible items left to right 
		CTabItem tab = items[i];
		tab.x = x;
		tab.y = y;
		x = x + tab.width;
	}
	setButtonBounds();
	return changed;
}
private void setLastItem(int index) {
	if (index < 0 || index > items.length - 1) return;
	Rectangle area = getClientArea();
	if (area.width <= 0) return;
	if (scroll_leftVisible() || scroll_rightVisible()) {
		int maxWidth = area.width - arrowBar.getSize().x;
		int tabWidth = items[index].width;
		while (index > 0) {
			tabWidth += items[index - 1].width;
			if (tabWidth > maxWidth) break;
			index--;
		}
	} else {
		index = 0;
	}
	topTabIndex = index;
	setItemLocation();
	redrawTabArea(-1);
}
/**
 * Layout the items and store the client area size.
 */
boolean setItemBounds() {
	boolean changed = false;
	if (isDisposed()) return changed;
	Rectangle area = super.getClientArea();
	
	int tabHeight = getTabHeight();
	xClient = area.x + borderLeft + marginWidth;
	if (onBottom) {
		yClient = area.y + borderTop + marginHeight; 
	} else {
		yClient = area.y + borderTop + tabHeight + 1 + marginHeight; 
		// +1 is for the line at the bottom of the tabs
	}
	
	if (area.width <= 0 || area.height <= 0 || items.length == 0) return changed;
	
	int[] widths = new int[items.length];
	GC gc = new GC(this);
	for (int i = 0; i < items.length; i++) {
		widths[i] = items[i].preferredWidth(gc);
	}
	gc.dispose();

	int oldAverageWidth = 0;
	int averageWidth = (area.width - borderLeft - borderRight) / items.length;
	while (averageWidth > oldAverageWidth) {
		int width = area.width - borderLeft - borderRight;
		int count = items.length;
		for (int i = 0; i < items.length; i++) {
			if (widths[i] < averageWidth) {
				width -= widths[i];
				count--;
			}
		}
		oldAverageWidth = averageWidth;
		if (count > 0) {
			averageWidth = width / count;
		}
	}
	averageWidth = Math.max(averageWidth, MIN_TAB_WIDTH * tabHeight);
	for (int i = 0; i < items.length; i++) {
		if (widths[i] > averageWidth) {
			widths[i] = averageWidth;
		}
	}
	
	int totalWidth = 0;
	for (int i = 0; i < items.length; i++) { 
		CTabItem tab = items[i];
		if (tab.height != tabHeight || tab.width != widths[i]) changed = true;
		tab.height = tabHeight;
		tab.width = widths[i];
		totalWidth += widths[i];
	}
	
	int areaWidth = area.x + area.width - borderRight;
	if (totalWidth <= areaWidth) {
		topTabIndex = 0;
	} 
	if (setItemLocation()) changed = true;
	
	// Is there a gap after last item showing
	if (correctLastItem()) changed = true;
	return changed;
}
private boolean onMnemonic (Event event) {
	char key = event.character;
	for (int i = 0; i < items.length; i++) {
		if (items[i] != null) {
			char mnemonic = getMnemonic (items[i].getText ());
			if (mnemonic != '\0') {
				if (Character.toUpperCase (key) == Character.toUpperCase (mnemonic)) {
					setSelection(i, true);
					return true;
				}
			}
		}
	}
	return false;
}
/** 
 * Paint the receiver.
 */
private void onPaint(Event event) {
	GC gc = event.gc;
	Rectangle rect = super.getClientArea();
	if (items.length == 0) {
		if (showBorders) {		
			if ((getStyle() & SWT.FLAT) != 0) {
				gc.setForeground(borderColor1);
				gc.drawRectangle(rect.x, rect.y, rect.x + rect.width - 1, rect.y + rect.height - 1);
			} else {
				gc.setForeground(borderColor1);
				gc.drawRectangle(rect.x, rect.y, rect.x + rect.width - 3, rect.y + rect.height - 3);
						
				// fill in right and bottom edges with parent's background
				gc.setBackground(getParent().getBackground());
				gc.fillRectangle(rect.x + rect.width - 2, rect.y, 2, rect.height);
				gc.fillRectangle(rect.x, rect.y + rect.height - 2, rect.width, 2);
			}
			gc.setForeground(getForeground());
		}
		return;
	}
	
	// redraw the Border
	drawBorder(gc);
	
	rect.x += borderLeft;
	rect.y += borderTop;
	rect.width -= borderLeft + borderRight;
	rect.height -= borderTop + borderBottom;
	Rectangle clip = gc.getClipping ();
	gc.setClipping(clip.intersection(rect));
	
	// Draw the unselected tabs first.
	for (int i=0; i < items.length; i++) {
		if (i != selectedIndex && event.getBounds().intersects(items[i].getBounds())) {
			items[i].onPaint(gc, false);
		}
	}
	// Selected tab comes last
	if (selectedIndex != -1) {
		items[selectedIndex].onPaint(gc, true);
	}
	
	// draw insertion mark
	if (insertionIndex > -2) {
		gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
		if (insertionIndex == -1) {
			Rectangle bounds = items[0].getBounds();
			gc.drawLine(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height - 1);
			gc.drawLine(bounds.x - 2, bounds.y, bounds.x + 2, bounds.y);
			gc.drawLine(bounds.x - 1, bounds.y + 1, bounds.x + 1, bounds.y + 1);
			gc.drawLine(bounds.x - 1, bounds.y + bounds.height - 2, bounds.x + 1, bounds.y + bounds.height - 2);
			gc.drawLine(bounds.x - 2, bounds.y + bounds.height - 1, bounds.x + 2, bounds.y + bounds.height - 1);

		} else {
			Rectangle bounds = items[insertionIndex].getBounds();
			gc.drawLine(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height - 1);
			gc.drawLine(bounds.x + bounds.width - 2, bounds.y, bounds.x + bounds.width + 2, bounds.y);
			gc.drawLine(bounds.x + bounds.width - 1, bounds.y + 1, bounds.x + bounds.width + 1, bounds.y + 1);
			gc.drawLine(bounds.x + bounds.width - 1, bounds.y + bounds.height - 2, bounds.x + bounds.width + 1, bounds.y + bounds.height - 2);
			gc.drawLine(bounds.x + bounds.width - 2, bounds.y + bounds.height - 1, bounds.x + bounds.width + 2, bounds.y + bounds.height - 1);
		}
	}
	
	gc.setForeground(getForeground());
	gc.setBackground(getBackground());	
}
private void redrawTabArea(int index) {
	int x = 0, y = 0, width = 0, height = 0;
	if (index == -1) {
		Rectangle area = super.getClientArea();
		if (area.width == 0 || area.height == 0) return;
		width = area.x + area.width - borderLeft - borderRight;
		height = getTabHeight() + 1; // +1 causes top line between content and tabs to be redrawn
		x = area.x + borderLeft;
		y = area.y + borderTop; 
		if (onBottom) {
			y = Math.max(0, area.y + area.height - borderBottom - height);
		}
	} else {
		CTabItem item = items[index];
		x = item.x;
		y = item.y;
		Rectangle area = super.getClientArea();
		width = area.x + area.width - x;
		height = item.height;
	}
	redraw(x, y, width, height, false);
}

/**	 
 * Removes the listener.
 *
 * @param listener the listener
 *
 * @exception SWTError
 *	<ul><li>ERROR_THREAD_INVALID_ACCESS	when called from the wrong thread</li>
 * 		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * 		<li>ERROR_NULL_ARGUMENT when listener is null</li></ul>
 */
public void removeSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(SWT.Selection, listener);
	removeListener(SWT.DefaultSelection, listener);	
}
/**	 
 * Removes the listener.
 *
 * @param listener the listener
 *
 * @exception SWTError
 *	<ul><li>ERROR_THREAD_INVALID_ACCESS	when called from the wrong thread</li>
 * 		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * 		<li>ERROR_NULL_ARGUMENT when listener is null</li></ul>
 */
public void removeCTabFolderListener(CTabFolderListener listener) {
	checkWidget();
	if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	if (tabListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < tabListeners.length; i++) {
		if (listener == tabListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (tabListeners.length == 1) {
		tabListeners = new CTabFolderListener[0];
		showClose = false;
		setButtonBounds();
		return;
	}
	CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length - 1];
	System.arraycopy(tabListeners, 0, newTabListeners, 0, index);
	System.arraycopy(tabListeners, index + 1, newTabListeners, index, tabListeners.length - index - 1);
	tabListeners = newTabListeners;
}

/**
 * The widget was resized. Adjust the size of the currently selected page.
 */ 
private void onResize() {

	if (items.length == 0) {
		redraw();
		return;
	}
	
	if (setItemBounds()) {
		redrawTabArea(-1);
	}
	
	Point size = getSize();
	if (oldSize == null) {
		redraw();
	} else {
		if (onBottom && size.y != oldSize.y) {
			redraw();
		} else {
			int x1 = Math.min(size.x, oldSize.x);
			if (size.x != oldSize.x) x1 -= 10;
			int y1 = Math.min(size.y, oldSize.y);
			if (size.y != oldSize.y) y1 -= 10;
			int x2 = Math.max(size.x, oldSize.x);
			int y2 = Math.max(size.y, oldSize.y);		
			redraw(0, y1, x2 + 10, y2 - y1, false);
			redraw(x1, 0, x2 - x1, y2, false);
		}
	}
	oldSize = size;
	
	// resize content
	if (selectedIndex != -1) {
		Control control = items[selectedIndex].getControl();
		if (control != null && !control.isDisposed()) {
			control.setBounds(getClientArea());
		}
	}
}

public void setBackground (Color color) {
	super.setBackground(color);
	background = color;
	// init inactive close button
	inactiveCloseBar.setBackground(color);
	
	// init scroll buttons
	arrowBar.setBackground(color);
	
	// init close button
	if (gradientColors == null) {
		closeBar.setBackground(color);
	}
}
/**
 * Specify a gradient of colours to be draw in the background of the selected tab.
 * For example to draw a gradient that varies from dark blue to blue and then to
 * white, use the following call to setBackground:
 * <pre>
 *	cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), 
 *		                           display.getSystemColor(SWT.COLOR_BLUE),
 *		                           display.getSystemColor(SWT.COLOR_WHITE), 
 *		                           display.getSystemColor(SWT.COLOR_WHITE)},
 *		               new int[] {25, 50, 100});
 * </pre>
 *
 * @param colors an array of Color that specifies the colors to appear in the gradient 
 *               in order of appearance left to right.  The value <code>null</code> clears the
 *               background gradient. The value <code>null</code> can be used inside the array of 
 *               Color to specify the background color.
 * @param percents an array of integers between 0 and 100 specifying the percent of the width 
 *                 of the widget at which the color should change.  The size of the percents array must be one 
 *                 less than the size of the colors array.
 * 
 * @exception SWTError <ul>
 *		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 *	</ul>
 */

public void setSelectionBackground(Color[] colors, int[] percents) {
	checkWidget();
	if (colors != null) {
		if (percents == null || percents.length != colors.length - 1) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		if (getDisplay().getDepth() < 15) {
			// Don't use gradients on low color displays
			colors = new Color[] { colors[0] };
			percents = new int[] { };
		}
		for (int i = 0; i < percents.length; i++) {
			if (percents[i] < 0 || percents[i] > 100) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			if (i > 0 && percents[i] < percents[i-1]) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
		}
	}
	
	// Are these settings the same as before?
	if (backgroundImage == null) {
		if ((gradientColors != null) && (colors != null) && 
			(gradientColors.length == colors.length)) {
			boolean same = false;
			for (int i = 0; i < gradientColors.length; i++) {
				if (gradientColors[i] == null) {
					same = colors[i] == null;
				} else {
					same = gradientColors[i].equals(colors[i]);
				}
				if (!same) break;
			}
			if (same) {
				for (int i = 0; i < gradientPercents.length; i++) {
					same = gradientPercents[i] == percents[i];
					if (!same) break;
				}
			}
			if (same) return;
		}
	} else {
		backgroundImage = null;
	}
	// Store the new settings
	if (colors == null) {
		gradientColors = null;
		gradientPercents = null;
		closeBar.setBackground(background);
	} else {
		gradientColors = new Color[colors.length];
		for (int i = 0; i < colors.length; ++i)
			gradientColors[i] = colors[i];
		gradientPercents = new int[percents.length];
		for (int i = 0; i < percents.length; ++i)
			gradientPercents[i] = percents[i];
		if (getDisplay().getDepth() < 15) closeBar.setBackground(background);
		else closeBar.setBackground(gradientColors[gradientColors.length - 1]);
	}

	// Refresh with the new settings
	if (selectedIndex > -1) redrawTabArea(selectedIndex);
}

/**
 * Set the image to be drawn in the background of the selected tab.
 * 
 * @param image the image to be drawn in the background
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelectionBackground(Image image) {
	checkWidget();
	if (image == backgroundImage) return;
	if (image != null) {
		gradientColors = null;
		gradientPercents = null;
	}
	backgroundImage = image;
	redrawTabArea(selectedIndex);
}
/**
 * Toggle the visibility of the border
 * 
 * @param show true if the border should be displayed
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setBorderVisible(boolean show) {
	checkWidget();
	if (showBorders == show) return;
	
	showBorders = show;
	if (showBorders) {
		if ((getStyle() & SWT.FLAT) != 0) {
			borderBottom = borderTop = borderLeft = borderRight = 1;
		} else {
			borderLeft = borderTop = 1;
			borderRight = borderBottom = 3;
		}
	} else {
		borderBottom = borderTop = borderLeft = borderRight = 0;
	}
	onClientAreaChange();
}
public void setFont(Font font) {
	checkWidget();
	if (font != null && font.equals(getFont())) return;
	int oldHeight = getTabHeight();
	super.setFont(font);
	if (oldHeight != getTabHeight()){
		onClientAreaChange();
	} else {
		setItemBounds();
		redraw();
	}
}
/**
 * Set the foreground color of the selected tab.
 * 
 * @param color the color of the text displayed in the selected tab
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelectionForeground (Color color) {
	checkWidget();
	if (selectionForeground == color) return;
	if (color == null) color = getForeground();
	selectionForeground = color;
	if (selectedIndex > -1) {
		redrawTabArea(selectedIndex);
	}
}
/**
 * Display an insert marker before or after the specified tab item. 
 * Null will clear the mark.
 * 
 * @param item the item with which the mark is associated or null
 * 
 * @param after true if the mark should be displayed after the specified item
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setInsertMark(CTabItem item, boolean after) {
	checkWidget();
	int index = -1;
	if (item != null) {
		index = indexOf(item);
	}
	setInsertMark(index, after);
}
/**
 * Display an insert marker before or after the specified tab item. 
 * -1 will clear the mark.
 * 
 * @param item the index of the item with which the mark is associated or null
 * 
 * @param after true if the mark should be displayed after the specified item
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setInsertMark(int index, boolean after) {
	checkWidget();
	if (index < -1 || index >= getItemCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	
	if (index == -1) {
		index = -2;
	} else {
		index = after ? index : --index;
	}
	
	if (insertionIndex == index) return;
	int oldIndex = insertionIndex;
	insertionIndex = index;
	if (index > -1)	redrawTabArea(index);
	if (oldIndex > 1) redrawTabArea(oldIndex);
}

/**
 * Set the selection to the tab at the specified index.
 * 
 * @param index the index of the tab item to be selected
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelection(int index) {
	checkWidget();
	if (index < 0 || index >= items.length) return;
	if (selectedIndex == index) return;
	
	int oldIndex = selectedIndex;
	selectedIndex = index;
	
	Control control = items[index].control;
	if (control != null && !control.isDisposed()) {
		control.setBounds(getClientArea());
		control.setVisible(true);
	}
	
	if (oldIndex != -1) {
		control = items[oldIndex].control;
		if (control != null && !control.isDisposed()) {
			control.setVisible(false);
		}		
	}
	showItem(items[selectedIndex]);
	setButtonBounds();
	redrawTabArea(-1);
}
/**
 * Shows the item.  If the item is already showing in the receiver,
 * this method simply returns.  Otherwise, the items are scrolled until
 * the item is visible.
 *
 * @param item the item to be shown
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see CTabFolder#showSelection()
 * 
 * @since 2.0
 */
public void showItem (CTabItem item) {
	checkWidget();
	if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	
	int index = indexOf(item);
	if (index < topTabIndex) {
		topTabIndex = index;
		setItemLocation();
		redrawTabArea(-1);
		return;
	}
	Rectangle area = getClientArea();
	if (area.width <= 0) {
		topTabIndex = index;
		return;
	}
	int rightEdge = area.x + area.width;
	if (scroll_leftVisible() || scroll_rightVisible()) {
		rightEdge -=  arrowBar.getSize().x;
	}
	if (item.x + item.width < rightEdge) return;
	setLastItem(index);
}
/**
 * Shows the selection.  If the selection is already showing in the receiver,
 * this method simply returns.  Otherwise, the items are scrolled until
 * the selection is visible.
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see CTabFolder#showItem(CTabItem)
 * 
 * @since 2.0
 * 
 */
public void showSelection () {
	checkWidget (); 
	if (selectedIndex != -1) {
		showItem(getSelection());
	}
}

char getMnemonic (String string) {
	int index = 0;
	int length = string.length ();
	do {
		while ((index < length) && (string.charAt (index) != '&')) index++;
		if (++index >= length) return '\0';
		if (string.charAt (index) != '&') return string.charAt (index);
		index++;
	} while (index < length);
 	return '\0';
}
/**
 * Set the selection to the tab at the specified item.
 * 
 * @param index the tab item to be selected
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *    <li>ERROR_NULL_ARGUMENT - if argument is null</li>
 * </ul>
 */
public void setSelection(CTabItem item) {
	checkWidget();
	if (item == null) 
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	int index = indexOf(item);
	setSelection(index);
}
/**
 * Set the selection to the tab at the specified index.
 */
private void setSelection(int index, boolean notify) {	
	int oldSelectedIndex = selectedIndex;
	setSelection(index);
	if (notify && selectedIndex != oldSelectedIndex && selectedIndex != -1) {
		Event event = new Event();
		event.item = getItem(selectedIndex);
		notifyListeners(SWT.Selection, event);
	}
}

private void updateCloseBar() {
	int imageHeight = getTabHeight() - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN - 6;
	if (imageHeight < 4) return;
	
	if (closeImage != null && closeImage.getBounds().height == imageHeight) return;
	
	if (closeBar != null) closeBar.dispose();
	closeBar = null;
	if (inactiveCloseBar != null) inactiveCloseBar.dispose();
	inactiveCloseBar = null;
	createCloseBar();
	
	ToolItem closeItem = closeBar.getItems()[0];
	ToolItem inactiveCloseItem = inactiveCloseBar.getItems()[0];
		
	if (closeImage != null) closeImage.dispose();
	
	Display display = getDisplay();
	Color foreground = getForeground();
	Color black = display.getSystemColor(SWT.COLOR_BLACK);
	Color background = getBackground();
	
	PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
	ImageData imageData = new ImageData(imageHeight, imageHeight, 4, palette);
	imageData.transparentPixel = 1;
	closeImage = new Image(display, imageData);
	GC gc = new GC(closeImage);
	gc.setBackground(background);
	gc.fillRectangle(0, 0, imageHeight, imageHeight);
	gc.setForeground(black);
	
	int h = (imageHeight /2 )* 2;
	gc.drawLine( 0, 0,     h - 2, h - 2);
	gc.drawLine( 1, 0,     h - 1, h - 2);
	gc.drawLine( 0, h - 2, h - 2, 0);
	gc.drawLine( 1, h - 2, h - 1, 0);
	
	gc.dispose();
	
	closeItem.setImage(closeImage);
	inactiveCloseItem.setImage(closeImage);
}
private void updateArrowBar() {
	
	int imageHeight = getTabHeight() - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN - 6;
	if (imageHeight < 4) return;
	
	if (arrowLeftImage != null && arrowLeftImage.getBounds().height == imageHeight) return;	
	
	if (arrowBar != null) arrowBar.dispose();
	arrowBar = null;
	if (arrowLeftImage != null) arrowLeftImage.dispose();
	if (arrowRightImage != null) arrowRightImage.dispose();
	
	createArrowBar();
	ToolItem[] items = arrowBar.getItems();
	ToolItem left  = items[0];
	ToolItem right = items[1];
	
	Display display = getDisplay();
	Color foreground = getForeground();
	Color black = display.getSystemColor(SWT.COLOR_BLACK);
	Color background = getBackground();
	
	PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
	ImageData imageData = new ImageData(imageHeight, imageHeight, 4, palette);
	imageData.transparentPixel = 1;
	arrowLeftImage = new Image(display, imageData);
	GC gc = new GC(arrowLeftImage);
	gc.setBackground(background);
	gc.fillRectangle(0, 0, imageHeight, imageHeight);
	gc.setBackground(black);
	int indent = 0;
	int midpoint = (imageHeight - 2*indent)/2;
	int height = 2 * midpoint;
	int[] pointArr = new int[] {indent, indent + midpoint, 
		                        indent + height, indent, 
		                        indent + height,  indent + height};
	gc.fillPolygon(pointArr);
	gc.dispose();
	
	palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
	imageData = new ImageData(imageHeight, imageHeight, 4, palette);
	imageData.transparentPixel = 1;
	arrowRightImage = new Image(display, imageData);
	gc = new GC(arrowRightImage);
	gc.setBackground(background);
	gc.fillRectangle(0, 0, imageHeight, imageHeight);
	gc.setBackground(black);
	pointArr = new int[] {indent, indent, 
		                  indent, indent + height,
		                  indent + height, indent + midpoint};
	gc.fillPolygon(pointArr);
	gc.dispose();
	
	left.setImage(arrowLeftImage);
	right.setImage(arrowRightImage);
}

private void onMouseDoubleClick(Event event) { 
	Event e = new Event();
	e.item = getItem(new Point(event.x, event.y));
	notifyListeners(SWT.DefaultSelection, e);
}
/** 
 * A mouse button was pressed down. 
 * If one of the tab scroll buttons was hit, scroll in the appropriate 
 * direction.
 * If a tab was hit select the tab.
 */
private void onMouseDown(Event event) {
	for (int i=0; i<items.length; i++) {
		if (items[i].getBounds().contains(new Point(event.x, event.y))) {
			setSelection(i, true);
			return;
		}
	}
}

private void onMouseExit(Event event) {
	Rectangle inactiveBounds = inactiveCloseBar.getBounds();
	if (inactiveBounds.contains(event.x, event.y)) return;
	inactiveCloseBar.setVisible(false);
	inactiveItem = null;
	
	showToolTip = false;
	toolTipItem = null;
	if (tip != null && !tip.isDisposed() && tip.isVisible()) tip.setVisible(false);
}

private void onMouseHover(Event event) {
	if (tip == null || tip.isDisposed()) return;
	showToolTip = true;
	showToolTip(event.x, event.y);
}
private void showToolTip (int x, int y) {
	CTabItem item = getItem(new Point (x, y));
	if (item != null) {
		if (item == toolTipItem) return;
		toolTipItem = item;
		String tooltip = item.getToolTipText();
		if (tooltip != null) {			
			Display display = tip.getDisplay();
			label.setForeground (display.getSystemColor (SWT.COLOR_INFO_FOREGROUND));
			label.setBackground (display.getSystemColor (SWT.COLOR_INFO_BACKGROUND));
			label.setText(tooltip);
			Point labelSize = label.computeSize(SWT.DEFAULT, SWT.DEFAULT);
			labelSize.x += 2; labelSize.y += 2;
			label.setSize(labelSize);
			tip.pack();
			/*
			 * On some platforms, there is a minimum size for a shell  
			 * which may be greater than the label size.
			 * To avoid having the background of the tip shell showing
			 * around the label, force the label to fill the entire client area.
			 */
			Rectangle area = tip.getClientArea();
			label.setSize(area.width, area.height);
			/*
			 * Position the tooltip and ensure that it is not located off
			 * the screen.
			 */
			Point pt = new Point(item.x + item.width / 4, item.y + item.height + 2);
			pt = toDisplay(pt);
			Rectangle rect = display.getBounds();
			Point tipSize = tip.getSize();
			pt.x = Math.max (0, Math.min (pt.x, rect.width - tipSize.x));
			pt.y = Math.max (0, Math.min (pt.y, rect.height - tipSize.y));
			tip.setLocation(pt);
			tip.setVisible(true);
			return;
		}
	}
	
	toolTipItem = null;
	if (tip != null && !tip.isDisposed() && tip.isVisible()) tip.setVisible(false);
}
private void onMouseMove(Event event) {
	if (showToolTip) {
		showToolTip(event.x, event.y);
	}
	
	if (!showClose) return;
	
	CTabItem item = null;
	for (int i=0; i<items.length; i++) {
		Rectangle rect = items[i].getBounds();
		if (rect.contains(new Point(event.x, event.y))) {
			item = items[i];
			break;
		}
	}
	if (item == inactiveItem) return;
	
	inactiveCloseBar.setVisible(false);
	inactiveItem = null;
		
	if (item == null || item == getSelection()) return;

	int toolbarHeight = getTabHeight() - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN + 2; // +2 to ignore gab between focus rectangle
	Point size = inactiveCloseBar.computeSize(SWT.DEFAULT, toolbarHeight);
	int x = item.x + item.width - size.x;
	int y = item.y + Math.max(0, (item.height - toolbarHeight)/2);		
			
	if (scroll_leftVisible() || scroll_rightVisible()) {
		Rectangle scrollArea = arrowBar.getBounds();
		scrollArea.width += borderRight;
		if (scrollArea.contains(x, y)) return;
	}
	
	inactiveCloseBar.setBounds(x, y, size.x, toolbarHeight);
	inactiveCloseBar.setVisible(true);
	inactiveItem = item;
}
private void onTraverse (Event event) {
	switch (event.detail) {
		case SWT.TRAVERSE_ESCAPE:
// TEMPORARY CODE See bug report 17372
//		case SWT.TRAVERSE_RETURN:
		case SWT.TRAVERSE_TAB_NEXT:
		case SWT.TRAVERSE_TAB_PREVIOUS:
			event.doit = true;
			break;
		case SWT.TRAVERSE_MNEMONIC:
			event.doit = onMnemonic(event);
			if (event.doit) event.detail = SWT.TRAVERSE_NONE;
			break;
		case SWT.TRAVERSE_PAGE_NEXT:
		case SWT.TRAVERSE_PAGE_PREVIOUS:
			event.doit = onPageTraversal(event);
			if (event.doit) event.detail = SWT.TRAVERSE_NONE;
			break;
	}
}

private boolean onPageTraversal(Event event) {
	int count = getItemCount ();
	if (count == 0) return false;
	int index = getSelectionIndex ();
	if (index == -1) {
		index = 0;
	} else {
		int offset = (event.detail == SWT.TRAVERSE_PAGE_NEXT) ? 1 : -1;
		index = (index + offset + count) % count;
	}
	setSelection (index, true);
	return true;
}

/**
 * Answer true if not all tabs can be visible in the receive
 * thus requiring the scroll buttons to be visible.
 */ 
private boolean scroll_leftVisible() {
	return topTabIndex > 0;
}

/**
 * Answer true if not all tabs can be visible in the receive
 * thus requiring the scroll buttons to be visible.
 */ 
private boolean scroll_rightVisible() {
	// only show Scroll buttons if there is more than one item
	// and if we are not already at the last item
	if (items.length < 2) return false;
	Rectangle area = getClientArea();
	int rightEdge = area.x + area.width;
	if (rightEdge <= 0) return false;
	if (topTabIndex > 0) {
		rightEdge -=  arrowBar.getSize().x;
	}
	CTabItem item = items[items.length-1];
	return (item.x + item.width > rightEdge);
}

/**
 * Scroll the tab items to the left.
 */
private void scroll_scrollLeft() {
	if (items.length == 0) return;
	setLastItem(topTabIndex - 1);
}

/**
 * Scroll the tab items to the right.
 */
private void scroll_scrollRight() {
	int lastIndex = getLastItem();
	topTabIndex = lastIndex + 1;
	setItemLocation();
	correctLastItem();
	redrawTabArea(-1);
}
private boolean correctLastItem() {
	Rectangle area = getClientArea();
	int rightEdge = area.x + area.width;
	if (rightEdge <= 0) return false;
	if (scroll_leftVisible() || scroll_rightVisible()) {
		rightEdge -= arrowBar.getSize().x;
	}
	CTabItem item = items[items.length - 1];
	if (item.x + item.width < rightEdge) {
		setLastItem(items.length - 1);
		return true;
	}
	return false;
}
/**
 * Specify a fixed height for the tab items.  If no height is specified,
 * the default height is the height of the text or the image, whichever 
 * is greater. Specifying a height of 0 will revert to the default height.
 * 
 * @param height the pixel value of the height or 0
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *    <li>ERROR_INVALID_ARGUMENT - if called with a height of less than 0</li>
 * </ul>
 */
public void setTabHeight(int height) {
	checkWidget();
	if (height < 0) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (fixedTabHeight == height) return;
	fixedTabHeight = height;
	setItemBounds();
	redraw();
	onClientAreaChange();
}
}
