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