/*******************************************************************************
 * 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))toolbarTrim = 6; //$NON-NLS-1$
        if ("gtk".equals(platform))toolbarTrim = 8; //$NON-NLS-1$

        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))toolbarTrim = 8; //$NON-NLS-1$

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

}
