blob: 265df47d86b1db3de43e950c8a33d57554a4b8d2 [file] [log] [blame]
package org.eclipse.swt.custom;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
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 = "...";
/**
* Construct a CTabItem with the specified parent and style.
*/
public CTabItem (CTabFolder parent, int style) {
this(parent, style, parent.getItemCount());
}
/**
* Construct a CTabItem with the specified parent and style, inserted at
* the specified index.
*/
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;
super.dispose();
parent.destroyItem(this);
parent = null;
control = null;
toolTipText = null;
}
/**
* Return the bounds of the CTabItem.
*/
public Rectangle getBounds () {
return new Rectangle(x, y, width, height);
}
/**
* Gets the control.
* <p>
* @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 () {
return control;
}
/**
* Answer the display of the receiver's parent widget.
*/
public Display getDisplay() {
if (parent == null) SWT.error(SWT.ERROR_WIDGET_DISPOSED);
return parent.getDisplay();
}
public Image getDisabledImage(){
return disabledImage;
}
/**
* Return the parent of the CTabItem.
*/
public CTabFolder getParent () {
return parent;
}
/**
* Gets the tool tip text.
* <p>
* @return the tool tip text.
*
* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
* when called from the wrong thread
* @exception SWTError(ERROR_WIDGET_DISPOSED)
* when the widget has been disposed
*/
public String getToolTipText () {
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;
}
String text = shortenText(gc, getText(), textWidth);
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 "";
}
/**
* 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.
* <p>
* @param control the new 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 void setControl (Control control) {
if (control != null && 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);
}
}
}
/**
* Sets the image.
* <p>
* @param image the new image (or null)
*
* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
* when called from the wrong thread
* @exception SWTError(ERROR_WIDGET_DISPOSED)
* when the widget has been disposed
*/
public void setImage (Image image) {
if (image != null && image.equals(getImage())) return;
int oldHeight = parent.getTabHeight();
super.setImage(image);
if (oldHeight != parent.getTabHeight()) {
parent.onClientAreaChange();
} else {
parent.layoutItems();
parent.redraw();
}
}
public void setDisabledImage (Image image) {
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
* the mnemonic characters but must not contain line delimiters.
*
* @param string the new label for the widget
*
*/
public void setText (String string) {
if (string.equals(getText())) return;
super.setText(string);
parent.layoutItems();
parent.redraw();
}
/**
* Sets the tool tip text.
* <p>
* @param string the new tool tip text (or null)
*
* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
* when called from the wrong thread
* @exception SWTError(ERROR_WIDGET_DISPOSED)
* when the widget has been disposed
*/
public void setToolTipText (String string) {
toolTipText = string;
}
}