/*******************************************************************************
 * Copyright (c) 2000, 2005 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 API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.presentations.r21.widgets;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.TypedListener;

/**
 * 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;

    boolean fixedTabHeight;

    int tabHeight;

    /* 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;

    private Control topRight;

    // 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;

    private Font oldFont;

    // 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
        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 | SWT.LEFT_TO_RIGHT
                | SWT.RIGHT_TO_LEFT;
        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();
    }

    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 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;
            resetTabSize(true);
        } else {
            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);
            if (!fixedTabHeight) {
				tabHeight = 0;
			}
            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 && e.keyCode != SWT.ARROW_RIGHT) {
			return;
		}
        int leadKey = (getStyle() & SWT.MIRRORED) != 0 ? SWT.ARROW_RIGHT
                : SWT.ARROW_LEFT;
        if (e.keyCode == leadKey) {
            if (selectedIndex > 0) {
                setSelection(selectedIndex - 1, true);
            }
        } else {
            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 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
                    - tabHeight - 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();
        return tabHeight;
    }

    /**
     * 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;
		}
        Rectangle area = getClientArea();
        if (area.width <= 0) {
			return 0;
		}
        Rectangle toolspace = getToolSpace();
        if (toolspace.width == 0) {
			return items.length - 1;
		}
        int width = area.width - toolspace.width;
        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;
    }

    private Rectangle getToolSpace() {
        boolean showArrows = scroll_leftVisible() || scroll_rightVisible();
        if (!showArrows && topRight == null) {
			return new Rectangle(0, 0, 0, 0);
		}
        Rectangle toolspace;
        if (showArrows) {
            toolspace = arrowBar.getBounds();
            toolspace.width += borderRight;
            if (topRight != null) {
				toolspace.width += topRight.getSize().x;
			}
        } else {
            toolspace = topRight.getBounds();
            toolspace.width += borderRight;
        }
        return toolspace;
    }

    /**
     * Returns the control in the top right corner of the tab folder. 
     * Typically this is a close button or a composite with a menu and close button.
     *
     * @since 2.1
     *
     * @return the control in the top right corner of the tab folder or null
     * 
     * @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 Control getTopRight() {
        checkWidget();
        return topRight;
    }

    /**
     * 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; //$NON-NLS-1$
                        }
                    }
                }
                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"; //$NON-NLS-1$
                }
                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();

        Rectangle area = super.getClientArea();

        int offset = 0;
        if (topRight != null) {
            Point size = topRight.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;
            topRight.setBounds(x, y, size.x, size.y);
            offset = size.x;
        }
        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 - offset;
            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 gap 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);
                Rectangle toolspace = getToolSpace();
                Point folderSize = getSize();
                boolean visible = (toolspace.width == 0 || x < toolspace.x)
                        && x + size.x < folderSize.x - borderRight;
                closeBar.setVisible(visible);
            }
        }
    }

    private boolean setItemLocation() {
        if (items.length == 0) {
			return false;
		}
        Rectangle area = super.getClientArea();
        int x = area.x;
        int y = area.y + borderTop;
        if (onBottom) {
			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;
		}
        int maxWidth = area.width;
        Rectangle toolspace = getToolSpace();
        if (toolspace.width > 0) {
            maxWidth -= toolspace.width;
        }
        int tabWidth = items[index].width;
        while (index > 0) {
            tabWidth += items[index - 1].width;
            if (tabWidth > maxWidth) {
				break;
			}
            index--;
        }
        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();

        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) {
        Font font = getFont();
        if (oldFont == null || !oldFont.equals(font)) {
            oldFont = font;
            resetTabSize(true);
        }
        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 = tabHeight + 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 topRight control
        if (topRight != null) {
			topRight.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;
        }
        oldSize = null;
        notifyListeners(SWT.Resize, new Event());
    }

    public void setFont(Font font) {
        checkWidget();
        if (font != null && font.equals(getFont())) {
			return;
		}
        super.setFont(font);
        oldFont = getFont();
        resetTabSize(true);
    }

    /**
     * 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. 
     * 
     * A value of 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.
     * 
     * A value of -1 will clear the mark.
     * 
     * @param index 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);
    }

    /**
     * Set the control that appears in the top right corner of the tab folder.
     * Typically this is a close button or a composite with a Menu and close button. 
     * The topRight control is optional.  Setting the top right control to null will remove it from the tab folder.
     *
     * @since 2.1
     * 
     * @param control the control to be displayed in the top right corner or null
     *
     * @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 the control is not a child of this CTabFolder</li>
     * </ul>
     */
    public void setTopRight(Control control) {
        checkWidget();
        if (control != null && control.getParent() != this) {
            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
        }
        topRight = control;
        resetTabSize(true);
    }

    /**
     * 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;
        Rectangle rect = getToolSpace();
        if (rect.width > 0) {
            rightEdge -= rect.width;
        }
        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 item 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 Image scaleImage(Image image, int oldSize, int newSize) {
        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(newSize, newSize, 4, palette);
        imageData.transparentPixel = 1;
        Image temp = new Image(display, imageData);
        GC gc = new GC(temp);
        gc.setBackground(background);
        gc.fillRectangle(0, 0, newSize, newSize);
        gc.drawImage(image, 0, 0, oldSize, oldSize, 0, 0, newSize, newSize);
        gc.dispose();
        return temp;
    }

    private void updateCloseBar() {
        //Temporary code - need a better way to determine toolBar trim
        int toolbarTrim = 4;
        String platform = SWT.getPlatform();
        if ("photon".equals(platform)) { //$NON-NLS-1$
			toolbarTrim = 6;
		}
        if ("gtk".equals(platform)) { //$NON-NLS-1$
			toolbarTrim = 8;
		}

        int maxHeight = tabHeight - CTabItem.TOP_MARGIN
                - CTabItem.BOTTOM_MARGIN - toolbarTrim;
        if (maxHeight < 3) {
			return;
		}
        int imageHeight = (maxHeight < 9) ? 9 : maxHeight;

        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);

        //draw an 9x8 'x' centered in image
        int h = (imageHeight / 2) * 2;
        int inset = (h - 8) / 2;
        gc.drawLine(inset, inset, h - inset - 1, h - inset - 1);
        gc.drawLine(inset + 1, inset, h - inset, h - inset - 1);
        gc.drawLine(inset, h - inset - 1, h - inset - 1, inset);
        gc.drawLine(inset + 1, h - inset - 1, h - inset, inset);

        gc.dispose();

        if (maxHeight < imageHeight) {
            //rescale image
            Image temp = scaleImage(closeImage, imageHeight, maxHeight);
            closeImage.dispose();
            closeImage = temp;
        }
        closeItem.setImage(closeImage);
        inactiveCloseItem.setImage(closeImage);
    }

    private void updateArrowBar() {
        //Temporary code - need a better way to determine toolBar trim
        int toolbarTrim = 6; // Windows needs 6, photon needs 6, gtk needs 8
        String platform = SWT.getPlatform();
        if ("gtk".equals(platform)) { //$NON-NLS-1$
			toolbarTrim = 8;
		}

        int maxHeight = tabHeight - toolbarTrim;
        if (maxHeight < 3) {
			return;
		}
        int imageHeight = (maxHeight < 9) ? 9 : maxHeight;

        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(7, imageHeight, 4, palette);
        imageData.transparentPixel = 1;
        arrowLeftImage = new Image(display, imageData);
        GC gc = new GC(arrowLeftImage);
        gc.setBackground(background);
        gc.fillRectangle(0, 0, 7, imageHeight);
        gc.setBackground(black);
        //draw a 9x5 '<' centered vertically in image
        int h = (imageHeight / 2) * 2;
        int midpoint = h / 2 - 1;
        int[] pointArr = new int[] { 6, midpoint - 5, 1, midpoint, 6,
                midpoint + 5, };
        gc.fillPolygon(pointArr);
        gc.dispose();

        palette = new PaletteData(new RGB[] { foreground.getRGB(),
                background.getRGB(), black.getRGB() });
        imageData = new ImageData(7, imageHeight, 4, palette);
        imageData.transparentPixel = 1;
        arrowRightImage = new Image(display, imageData);
        gc = new GC(arrowRightImage);
        gc.setBackground(background);
        gc.fillRectangle(0, 0, 7, imageHeight);
        gc.setBackground(black);
        //draw a 9x5 '>' centered vertically in image
        pointArr = new int[] { 1, midpoint - 5, 6, midpoint, 1, midpoint + 5, };
        gc.fillPolygon(pointArr);
        gc.dispose();

        if (maxHeight < imageHeight) {
            //rescale image
            Image leftTemp = scaleImage(arrowLeftImage, imageHeight, maxHeight);
            arrowLeftImage.dispose();
            arrowLeftImage = leftTemp;

            Image rightTemp = scaleImage(arrowRightImage, imageHeight,
                    maxHeight);
            arrowRightImage.dispose();
            arrowRightImage = rightTemp;
        }
        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 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))) {
                if (i == selectedIndex) {
                    showSelection();
                    return;
                }
                forceFocus();
                setSelection(i, true);
                if (isFocusControl()) {
					setFocus();
				}
                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 && tooltip.length() > 0) {
                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 = tabHeight - CTabItem.TOP_MARGIN
                - CTabItem.BOTTOM_MARGIN + 2; // +2 to ignore gap between focus rectangle
        Point size = inactiveCloseBar.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);
        Rectangle toolspace = getToolSpace();
        Point folderSize = getSize();
        if ((toolspace.width == 0 || x < toolspace.x)
                && x + size.x < folderSize.x - borderRight) {
            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;
        }
        if (topRight != null) {
            rightEdge -= topRight.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;
		}
        Rectangle toolspace = getToolSpace();
        if (toolspace.width > 0) {
            rightEdge -= toolspace.width;
        }
        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);
        }
        fixedTabHeight = true;
        if (tabHeight == height) {
			return;
		}
        tabHeight = height;
        oldSize = null;
        notifyListeners(SWT.Resize, new Event());
    }

    void resetTabSize(boolean checkHeight) {
        int oldHeight = tabHeight;
        if (!fixedTabHeight && checkHeight) {
            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();
            if (topRight != null) {
				tempHeight = Math.max(tempHeight, topRight.computeSize(
                        SWT.DEFAULT, SWT.DEFAULT).y);
			}
            tabHeight = tempHeight;
        }

        if (tabHeight != oldHeight) {
            oldSize = null;
            notifyListeners(SWT.Resize, new Event());
        } else {
            setItemBounds();
            redraw();
        }
    }

    /**
     * 
     * @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 the position value is not either SWT.TOP or SWT.BOTTOM</li>
     * </ul>
     * 
     * UNDER CONSTRUCTION
     * @since 3.0
     */
    public void setTabPosition(int position) {
        checkWidget();
        if (position != SWT.TOP && position != SWT.BOTTOM) {
            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
        }
        if (onBottom != (position == SWT.BOTTOM)) {
            onBottom = position == SWT.BOTTOM;
            setBorderVisible(showBorders);
            resetTabSize(true);
            //		updateTabHeight(true);
            //		Rectangle rectBefore = getClientArea();
            //		updateItems();
            //		Rectangle rectAfter = getClientArea();
            //		if (!rectBefore.equals(rectAfter)) {
            //			notifyListeners(SWT.Resize, new Event());
            //		}
            //		setItemBounds();
            //		redrawTabArea(-1);
            //		redraw();
        }
    }

    public int getTabPosition() {
        if (onBottom) {
			return SWT.BOTTOM;
		}
        return SWT.TOP;
    }

}
