/*******************************************************************************
 * Copyright (c) 2000, 2004 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.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Widget;

public class CTabItem extends Item {
    CTabFolder parent;

    int x, y, width, height = 0;

    String toolTipText;

    Control control; // the tab page

    private Image disabledImage;

    // internal constants
    static final int LEFT_MARGIN = 4;

    static final int RIGHT_MARGIN = 4;

    static final int TOP_MARGIN = 3;

    static final int BOTTOM_MARGIN = 3;

    private static final int INTERNAL_SPACING = 2;

    private static final String ellipsis = "..."; //$NON-NLS-1$

    String shortenedText;

    int shortenedTextWidth;

    /**
     * Constructs a new instance of this class given its parent
     * (which must be a <code>CTabFolder</code>) and a style value
     * describing its behavior and appearance. The item is added
     * to the end of the items maintained by its parent.
     * <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 CTabFolder which will be the parent of the new instance (cannot be null)
     * @param style the style of control 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
     * @see Widget#getStyle
     */
    public CTabItem(CTabFolder parent, int style) {
        this(parent, style, parent.getItemCount());
    }

    /**
     * Constructs a new instance of this class given its parent
     * (which must be a <code>CTabFolder</code>), a style value
     * describing its behavior and appearance, and the index
     * at which to place it in the items maintained by its parent.
     * <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 CTabFolder which will be the parent of the new instance (cannot be null)
     * @param style the style of control to construct
     * @param index the index to store the receiver in its parent
     *
     * @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
     * @see Widget#getStyle
     */
    public CTabItem(CTabFolder parent, int style, int index) {
        super(parent, checkStyle(style));
        parent.createItem(this, index);
    }

    private static int checkStyle(int style) {
        return SWT.NONE;
    }

    public void dispose() {
        if (isDisposed())
            return;
        parent.destroyItem(this);
        super.dispose();
        parent = null;
        control = null;
        toolTipText = null;
    }

    /**
     * Returns a rectangle describing the receiver's size and location
     * relative to its parent.
     *
     * @return the receiver's bounding column rectangle
     *
     * @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 Rectangle getBounds() {
        //checkWidget();
        return new Rectangle(x, y, width, height);
    }

    /**
     * Gets the control that is displayed in the content are of the tab item.
     *
     * @return the control
     *
     * @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
     *	when called from the wrong thread
     * @exception SWTError(ERROR_WIDGET_DISPOSED)
     *	when the widget has been disposed
     */
    public Control getControl() {
        checkWidget();
        return control;
    }

    public Display getDisplay() {
        if (parent == null)
            SWT.error(SWT.ERROR_WIDGET_DISPOSED);
        return parent.getDisplay();
    }

    /**
     * Get the image displayed in the tab if the tab is disabled.
     * 
     * @return the disabled image or null
     */
    public Image getDisabledImage() {
        //checkWidget();
        return disabledImage;
    }

    /**
     * Returns the receiver's parent, which must be a <code>CTabFolder</code>.
     *
     * @return the receiver's parent
     */
    public CTabFolder getParent() {
        //checkWidget();
        return parent;
    }

    /**
     * Returns the receiver's tool tip text, or null if it has
     * not been set.
     *
     * @return the receiver's tool tip text
     *
     * @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 String getToolTipText() {
        checkWidget();
        return toolTipText;
    }

    /**
     * Paint the receiver.
     */
    void onPaint(GC gc, boolean isSelected) {

        if (width == 0 || height == 0)
            return;

        Display display = getDisplay();
        Color highlightShadow = display
                .getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
        Color normalShadow = display
                .getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);

        int index = parent.indexOf(this);

        if (isSelected) {

            Rectangle bounds = null;
            if (!parent.onBottom) {
                if (index == parent.topTabIndex) {
                    bounds = new Rectangle(x + 1, y + 1, width - 2, height - 1);
                } else {
                    bounds = new Rectangle(x + 2, y + 1, width - 3, height - 1);
                }
            } else {
                if (index == parent.topTabIndex) {
                    bounds = new Rectangle(x + 1, y + 1, width - 2, height - 2);
                } else {
                    bounds = new Rectangle(x + 2, y + 1, width - 3, height - 2);
                }
            }
            if (parent.backgroundImage != null) {
                // draw a background image behind the text
                Rectangle imageRect = parent.backgroundImage.getBounds();
                gc.drawImage(parent.backgroundImage, 0, 0, imageRect.width,
                        imageRect.height, bounds.x, bounds.y, bounds.width,
                        bounds.height);
            } else if (parent.gradientColors != null) {
                // draw a gradient behind the text
                Color oldBackground = gc.getBackground();
                if (parent.gradientColors.length == 1) {
                    if (parent.gradientColors[0] != null)
                        gc.setBackground(parent.gradientColors[0]);
                    gc.fillRectangle(bounds.x, bounds.y, bounds.width,
                            bounds.height);
                } else {
                    Color oldForeground = gc.getForeground();
                    Color lastColor = parent.gradientColors[0];
                    if (lastColor == null)
                        lastColor = oldBackground;
                    for (int i = 0, pos = 0; i < parent.gradientPercents.length; ++i) {
                        gc.setForeground(lastColor);
                        lastColor = parent.gradientColors[i + 1];
                        if (lastColor == null)
                            lastColor = oldBackground;
                        gc.setBackground(lastColor);
                        int gradientWidth = (parent.gradientPercents[i]
                                * bounds.width / 100)
                                - pos;
                        gc.fillGradientRectangle(bounds.x + pos, bounds.y,
                                gradientWidth, bounds.height, false);
                        pos += gradientWidth;
                    }
                    gc.setForeground(oldForeground);
                }
                gc.setBackground(oldBackground);
            }

            // draw tab lines
            if (!parent.onBottom) {
                gc.setForeground(normalShadow);
                if (index != parent.topTabIndex) {
                    gc.drawLine(x + 1, y, x + 1, y);
                    gc.drawLine(x, y + 1, x, y + height - 2);
                    gc.drawLine(x, y + height - 1, x, y + height - 1);
                }
                gc.drawLine(x + width - 1, y, x + width - 1, y);
                gc.drawLine(x + width, y + 1, x + width, y + height - 2);
                gc.drawLine(x + width, y + height - 1, x + width, y + height
                        - 1);

                gc.setForeground(highlightShadow);
                if (index != parent.topTabIndex) {
                    gc.drawLine(x + 2, y, x + 2, y);
                    gc.drawLine(x + 1, y + 1, x + 1, y + height - 2);
                    gc.drawLine(x + 1, y + height - 1, x + 1, y + height - 1);
                } else {
                    gc.drawLine(x, y, x, y + height - 1);
                }

                gc.drawLine(x + width - 2, y, x + width - 2, y);
                gc
                        .drawLine(x + width - 1, y + 1, x + width - 1, y
                                + height - 2);
                gc.drawLine(x + width - 1, y + height - 1, x + width - 1, y
                        + height - 1);

                // light line across top
                if (index != parent.topTabIndex) {
                    gc.drawLine(x + 3, y, x + width - 3, y);
                } else {
                    gc.drawLine(x + 1, y, x + width - 3, y);
                }
            } else {
                gc.setForeground(normalShadow);
                if (index != parent.topTabIndex) {
                    gc.drawLine(x, y, x, y);
                    gc.drawLine(x, y + 1, x, y + height - 2);
                    gc.drawLine(x + 1, y + height - 1, x + 1, y + height - 1);
                }
                gc.drawLine(x + width, y, x + width, y);
                gc.drawLine(x + width, y + 1, x + width, y + height - 2);
                gc.drawLine(x + width - 1, y + height - 1, x + width - 1, y
                        + height - 1);

                gc.setForeground(highlightShadow);
                if (index != parent.topTabIndex) {
                    gc.drawLine(x + 1, y, x + 1, y);
                    gc.drawLine(x + 1, y + 1, x + 1, y + height - 2);
                    gc.drawLine(x + 2, y + height - 1, x + 2, y + height - 1);
                } else {
                    gc.drawLine(x, y, x, y + height - 1);
                }

                gc.drawLine(x + width - 1, y, x + width - 1, y);
                gc
                        .drawLine(x + width - 1, y + 1, x + width - 1, y
                                + height - 2);
                gc.drawLine(x + width - 2, y + height - 1, x + width - 2, y
                        + height - 1);

                // light line across top and bottom
                if (index != parent.topTabIndex) {
                    gc.drawLine(x + 1, y, x + width - 2, y);
                    gc.drawLine(x + 2, y + height - 1, x + width - 3, y
                            + height - 1);
                } else {
                    gc.drawLine(x + 1, y, x + width - 2, y);
                    gc.drawLine(x + 1, y + height - 1, x + width - 3, y
                            + height - 1);
                }
            }
            if (parent.isFocusControl()) {
                // draw a focus rectangle
                int x1, y1, width1, height1;
                if (!parent.onBottom) {
                    if (index == parent.topTabIndex) {
                        x1 = x + 1;
                        y1 = y + 1;
                        width1 = width - 2;
                        height1 = height - 1;
                    } else {
                        x1 = x + 2;
                        y1 = y + 1;
                        width1 = width - 3;
                        height1 = height - 1;
                    }
                } else {
                    if (index == parent.topTabIndex) {
                        x1 = x + 1;
                        y1 = y + 1;
                        width1 = width - 2;
                        height1 = height - 2;
                    } else {
                        x1 = x + 2;
                        y1 = y + 1;
                        width1 = width - 3;
                        height1 = height - 2;
                    }
                }
                gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
                gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
                gc.drawFocus(x1, y1, width1, height1);
            }
        } else {
            // draw tab lines for unselected items
            gc.setForeground(normalShadow);
            if (!parent.onBottom) {
                if (index != parent.topTabIndex
                        && index != parent.getSelectionIndex() + 1) {
                    gc.drawLine(x, y, x, y + (height / 2));
                }
            } else {
                if (index != parent.topTabIndex
                        && index != parent.getSelectionIndex() + 1) {
                    gc.drawLine(x, y + (height / 2), x, y + height - 1);
                }
            }

        }

        // draw Image
        int xDraw = x + LEFT_MARGIN;

        Image image = getImage();
        if (!isSelected && image != null) {
            Image temp = getDisabledImage();
            if (temp != null) {
                image = temp;
            }
        }
        if (image != null) {
            Rectangle imageBounds = image.getBounds();
            int imageX = xDraw;
            int imageHeight = Math.min(height - BOTTOM_MARGIN - TOP_MARGIN,
                    imageBounds.height);
            int imageY = y + (height - imageHeight) / 2;
            int imageWidth = imageBounds.width * imageHeight
                    / imageBounds.height;
            gc.drawImage(image, imageBounds.x, imageBounds.y,
                    imageBounds.width, imageBounds.height, imageX, imageY,
                    imageWidth, imageHeight);
            xDraw += imageWidth + INTERNAL_SPACING;
        }

        // draw Text
        int textWidth = x + width - xDraw - RIGHT_MARGIN;
        if (isSelected && parent.showClose) {
            textWidth = x + width - xDraw - parent.closeBar.getSize().x
                    - RIGHT_MARGIN;
        }
        if (shortenedText == null || shortenedTextWidth != textWidth) {
            shortenedText = shortenText(gc, getText(), textWidth);
            shortenedTextWidth = textWidth;
        }
        String text = shortenedText;

        if (isSelected && parent.selectionForeground != null) {
            gc.setForeground(parent.selectionForeground);
        } else {
            gc.setForeground(parent.getForeground());
        }
        int textY = y + (height - gc.textExtent(text, SWT.DRAW_MNEMONIC).y) / 2;
        gc.drawText(text, xDraw, textY, SWT.DRAW_TRANSPARENT
                | SWT.DRAW_MNEMONIC);

        gc.setForeground(parent.getForeground());
    }

    private static String shortenText(GC gc, String text, int width) {
        if (gc.textExtent(text, SWT.DRAW_MNEMONIC).x <= width)
            return text;

        int ellipseWidth = gc.textExtent(ellipsis, SWT.DRAW_MNEMONIC).x;
        int length = text.length();
        int end = length - 1;
        while (end > 0) {
            text = text.substring(0, end);
            int l1 = gc.textExtent(text, SWT.DRAW_MNEMONIC).x;
            if (l1 + ellipseWidth <= width) {
                return text + ellipsis;
            }
            end--;
        }
        return text + ellipsis;
    }

    /**
     * Answer the preferred height of the receiver for the GC.
     */
    int preferredHeight(GC gc) {
        Image image = getImage();
        int height = 0;
        if (image != null)
            height = image.getBounds().height;
        String text = getText();
        height = Math.max(height, gc.textExtent(text, SWT.DRAW_MNEMONIC).y);
        return height + TOP_MARGIN + BOTTOM_MARGIN;
    }

    /**
     * Answer the preferred width of the receiver for the GC.
     */
    int preferredWidth(GC gc) {
        int width = 0;
        Image image = getImage();
        if (image != null)
            width += image.getBounds().width;
        String text = getText();
        if (text != null) {
            if (image != null)
                width += INTERNAL_SPACING;
            width += gc.textExtent(text, SWT.DRAW_MNEMONIC).x;
        }
        if (parent.showClose)
            width += INTERNAL_SPACING + preferredHeight(gc); // closebar will be square and will fill preferred height
        return width + LEFT_MARGIN + RIGHT_MARGIN;
    }

    /**
     * Sets the control that is used to fill the client area of
     * the tab folder when the user selects the tab item.
     * <p>
     * @param control the new control (or null)
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 
     *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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>
     */
    public void setControl(Control control) {
        checkWidget();
        if (control != null) {
            if (control.isDisposed())
                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
            if (control.getParent() != parent)
                SWT.error(SWT.ERROR_INVALID_PARENT);
        }
        if (this.control != null && !this.control.isDisposed()) {
            this.control.setVisible(false);
        }
        this.control = control;
        if (this.control != null) {
            int index = parent.indexOf(this);
            if (index == parent.getSelectionIndex()) {
                this.control.setBounds(parent.getClientArea());
                this.control.setVisible(true);
            } else {
                this.control.setVisible(false);
            }
        }
    }

    public void setImage(Image image) {
        checkWidget();
        if (image != null && image.equals(getImage()))
            return;
        super.setImage(image);
        parent.resetTabSize(true);
    }

    /**
     * Sets the image that is displayed if the tab item is disabled.
     * Null will clear the image.
     * 
     * @param image the image to be displayed when the item is disabled 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>
     * </ul>
     */
    public void setDisabledImage(Image image) {
        checkWidget();
        if (image != null && image.equals(getDisabledImage()))
            return;
        disabledImage = image;
        parent.redraw();
    }

    /**
     * Set the widget text.
     * <p>
     * This method sets the widget label.  The label may include
     * mnemonic characters but must not contain line delimiters.
     *
     * @param string the new label for the widget
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the text 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>
     */
    public void setText(String string) {
        checkWidget();
        if (string.equals(getText()))
            return;
        super.setText(string);
        shortenedText = null;
        shortenedTextWidth = 0;
        parent.resetTabSize(false);
    }

    /**
     * Sets the receiver's tool tip text to the argument, which
     * may be null indicating that no tool tip text should be shown.
     *
     * @param string the new tool tip text (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>
     * </ul>
     */
    public void setToolTipText(String string) {
        checkWidget();
        toolTipText = string;
    }
}
