blob: db93a6b6d147b9b582b304f5e59bef563316b13e [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
private static final int LEFT_MARGIN = 3;
private static final int RIGHT_MARGIN = 3;
static final int TOP_MARGIN = 2;
static final int BOTTOM_MARGIN = 2;
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;
}
private int imageHeight() {
int imageHeight = 0;
if (parent.getImageHeight() != -1) {
imageHeight = parent.getImageHeight();
} else {
Image image = getImage();
if (image != null) {
imageHeight = image.getBounds().height;
}
}
return imageHeight;
}
private int imageWidth() {
int imageWidth = 0;
Image image = getImage();
if (image != null) {
imageWidth = image.getBounds().width;
}
return imageWidth;
}
/**
* 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) {
// draw a background image behind the text
if (parent.backgroundImage != null) {
if (index == parent.topTabIndex){
Rectangle imageRect = parent.backgroundImage.getBounds();
gc.drawImage(parent.backgroundImage, 0, 0, imageRect.width, imageRect.height,
x + 1, y, width - 3, height);
} else {
Rectangle imageRect = parent.backgroundImage.getBounds();
gc.drawImage(parent.backgroundImage, 0, 0, imageRect.width, imageRect.height,
x + 2, y, width - 4, height);
}
}
// 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 - 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);
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 - 3, y, x + width - 3, y);
gc.drawLine(x + width - 2, y + 1, x + width - 2, y + height - 2);
gc.drawLine(x + width - 2, y + height - 1, x + width - 2, y + height - 1);
// light line across top
if (index != parent.topTabIndex) {
gc.drawLine(x + 3, y, x + width - 4, y);
} else {
gc.drawLine(x + 1, y, x + width - 4, 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 - 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);
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 - 2, y, x + width - 2, y);
gc.drawLine(x + width - 2, y + 1, x + width - 2, y + height - 2);
gc.drawLine(x + width - 3, y + height - 1, x + width - 3, 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 - 4, y + height - 1);
} else {
gc.drawLine(x + 1, y, x + width - 2, y);
gc.drawLine(x + 1, y + height - 1, x + width - 4, 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 imageHeight = imageHeight();
int imageY = y + (height - parent.getImageHeight()) / 2;
gc.drawImage(image,
imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height,
xDraw, imageY, imageBounds.width, imageHeight);
xDraw += imageBounds.width + 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 - textHeight(gc)) / 2;
gc.drawString(text, xDraw, textY, true);
gc.setForeground(parent.getForeground());
}
private String shortenText(GC gc, String text, int width) {
if (gc.textExtent(text).x <= width) return text;
int ellipseWidth = gc.textExtent(ellipsis).x;
int length = text.length();
int end = length - 1;
while (end > 0) {
text = text.substring(0, end);
int l1 = gc.textExtent(text).x;
if (l1 + ellipseWidth <= width) {
return text + ellipsis;
}
end--;
}
return "";
}
/**
* Answer the preferred height of the receiver for the GC.
*/
int preferredHeight(GC gc) {
return Math.max(textHeight(gc), imageHeight()) + TOP_MARGIN + BOTTOM_MARGIN;
}
/**
* Answer the preferred width of the receiver for the GC.
*/
int preferredWidth(GC gc) {
int tabWidth = LEFT_MARGIN + RIGHT_MARGIN;
Image image = getImage();
if (image != null) tabWidth += imageWidth() + INTERNAL_SPACING;
tabWidth += textWidth(gc);
if (parent.showClose) tabWidth += parent.closeBar.getSize().x;
return tabWidth;
}
/**
* 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) {
Image oldImage = getImage();
super.setImage(image);
if (image == null || !image.equals(oldImage)) {
parent.itemChanged(this);
}
}
public void setDisabledImage (Image image) {
Image oldImage = getDisabledImage();
disabledImage = image;
if (disabledImage == null || !disabledImage.equals(oldImage)) {
parent.itemChanged(this);
}
}
/**
* 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) {
String oldText = getText();
super.setText(string);
if (!string.equals(oldText)) {
parent.itemChanged(this);
}
}
/**
* 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;
}
/**
* Answer the text height.
*/
private int textHeight(GC gc) {
int textHeight = 0;
if (isDisposed()) return textHeight;
String text = getText();
if (text != null) {
textHeight = gc.stringExtent(text).y;
}
return textHeight;
}
/**
* Answer the text width.
*/
private int textWidth(GC gc) {
int textWidth = 0;
if (isDisposed()) return 0;
String text = getText();
if (text != null) {
textWidth = gc.stringExtent(text).x;
}
return textWidth;
}
}