summaryrefslogtreecommitdiffstats
path: root/bundles
diff options
context:
space:
mode:
authorBogdan Gheorghe <gheorghe>2010-02-12 16:17:39 +0000
committerBogdan Gheorghe <gheorghe>2010-02-12 16:17:39 +0000
commit803bd538f4c4c40e1d60df10cb6937bfea9dab26 (patch)
treeaf03e9236d18cb54bf52b4c75e1580105dd6620a /bundles
parent810eb254cbe71a3e1637e56f044fa70b981eb39d (diff)
downloadeclipse.platform.swt-803bd538f4c4c40e1d60df10cb6937bfea9dab26.tar.gz
eclipse.platform.swt-803bd538f4c4c40e1d60df10cb6937bfea9dab26.tar.xz
eclipse.platform.swt-803bd538f4c4c40e1d60df10cb6937bfea9dab26.zip
CTabFolder renderer work
Diffstat (limited to 'bundles')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java1294
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java20
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderRenderer.java1618
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java628
4 files changed, 1914 insertions, 1646 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
index e9c5af2c84..81203034ea 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
@@ -107,15 +107,16 @@ public class CTabFolder extends Composite {
public static RGB borderOutsideRGB = new RGB (171, 168, 165);
/* sizing, positioning */
- int xClient, yClient;
boolean onBottom = false;
boolean single = false;
boolean simple = true;
int fixedTabHeight = SWT.DEFAULT;
int tabHeight;
int minChars = 20;
+ boolean borderVisible = false;
/* item management */
+ CTabFolderRenderer renderer;
CTabItem items[] = new CTabItem[0];
int firstIndex = -1; // index of the left most visible tab.
int selectedIndex = -1;
@@ -127,7 +128,7 @@ public class CTabFolder extends Composite {
/* External Listener management */
CTabFolder2Listener[] folderListeners = new CTabFolder2Listener[0];
// support for deprecated listener mechanism
- CTabFolderListener[] tabListeners = new CTabFolderListener[0];
+ CTabFolderListener[] tabListeners = new CTabFolderListener[0];
/* Selected item appearance */
Image selectionBgImage;
@@ -135,68 +136,37 @@ public class CTabFolder extends Composite {
int[] selectionGradientPercents;
boolean selectionGradientVertical;
Color selectionForeground;
- Color selectionBackground; //selection fade end
- Color selectionFadeStart;
-
- Color selectionHighlightGradientBegin = null; //null == no highlight
- //Although we are given new colours all the time to show different states (active, etc),
- //some of which may have a highlight and some not, we'd like to retain the highlight colours
- //as a cache so that we can reuse them if we're again told to show the highlight.
- //We are relying on the fact that only one tab state usually gets a highlight, so only
- //a single cache is required. If that happens to not be true, cache simply becomes less effective,
- //but we don't leak colours.
- Color[] selectionHighlightGradientColorsCache = null; //null is a legal value, check on access
-
- /* Colors for anti-aliasing */
- Color selectedOuterColor = null;
- Color selectedInnerColor = null;
- Color tabAreaColor = null;
+ Color selectionBackground;
/* Unselected item appearance */
- Color[] gradientColors;
+ Color[] gradientColors;
int[] gradientPercents;
boolean gradientVertical;
boolean showUnselectedImage = true;
// close, min/max and chevron buttons
- Color fillColor;
boolean showClose = false;
boolean showUnselectedClose = true;
Rectangle chevronRect = new Rectangle(0, 0, 0, 0);
- int chevronImageState = NORMAL;
+ int chevronImageState = SWT.NONE;
boolean showChevron = false;
Menu showMenu;
boolean showMin = false;
Rectangle minRect = new Rectangle(0, 0, 0, 0);
boolean minimized = false;
- int minImageState = NORMAL;
+ int minImageState = SWT.NONE;
boolean showMax = false;
Rectangle maxRect = new Rectangle(0, 0, 0, 0);
boolean maximized = false;
- int maxImageState = NORMAL;
+ int maxImageState = SWT.NONE;
Control topRight;
Rectangle topRightRect = new Rectangle(0, 0, 0, 0);
int topRightAlignment = SWT.RIGHT;
- // borders and shapes
- int borderLeft = 0;
- int borderRight = 0;
- int borderTop = 0;
- int borderBottom = 0;
-
- int highlight_margin = 0;
- int highlight_header = 0;
-
- int[] curve;
- int[] topCurveHighlightStart;
- int[] topCurveHighlightEnd;
- int curveWidth = 0;
- int curveIndent = 0;
-
// when disposing CTabFolder, don't try to layout the items or
// change the selection as each child is destroyed.
boolean inDispose = false;
@@ -205,63 +175,22 @@ public class CTabFolder extends Composite {
// on Resize
Point oldSize;
Font oldFont;
- /*
- * Border color that was used in computing the cached anti-alias Colors.
- * We have to recompute the colors if the border color changes
- */
- Color lastBorderColor = null;
// internal constants
static final int DEFAULT_WIDTH = 64;
static final int DEFAULT_HEIGHT = 64;
- static final int BUTTON_SIZE = 18;
-
- static final int[] TOP_LEFT_CORNER = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
-
- //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom)
- //so can fade in same direction as right swoop curve
- static final int[] TOP_LEFT_CORNER_HILITE = new int[] {5,2, 4,2, 3,3, 2,4, 2,5, 1,6};
-
- static final int[] TOP_RIGHT_CORNER = new int[] {-6,0, -5,1, -4,1, -1,4, -1,5, 0,6};
- static final int[] BOTTOM_LEFT_CORNER = new int[] {0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0};
- static final int[] BOTTOM_RIGHT_CORNER = new int[] {-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6};
-
- static final int[] SIMPLE_TOP_LEFT_CORNER = new int[] {0,2, 1,1, 2,0};
- static final int[] SIMPLE_TOP_RIGHT_CORNER = new int[] {-2,0, -1,1, 0,2};
- static final int[] SIMPLE_BOTTOM_LEFT_CORNER = new int[] {0,-2, 1,-1, 2,0};
- static final int[] SIMPLE_BOTTOM_RIGHT_CORNER = new int[] {-2,0, -1,-1, 0,-2};
- static final int[] SIMPLE_UNSELECTED_INNER_CORNER = new int[] {0,0};
-
- static final int[] TOP_LEFT_CORNER_BORDERLESS = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
- static final int[] TOP_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -6,1, -5,1, -2,4, -2,5, -1,6};
- static final int[] BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0};
- static final int[] BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6};
-
- static final int[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = new int[] {0,2, 1,1, 2,0};
- static final int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= new int[] {-3,0, -2,1, -1,2};
- static final int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-3, 1,-2, 2,-1, 3,0};
- static final int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-4,0, -3,-1, -2,-2, -1,-3};
-
+
static final int SELECTION_FOREGROUND = SWT.COLOR_LIST_FOREGROUND;
static final int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND;
- static final int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+
static final int FOREGROUND = SWT.COLOR_WIDGET_FOREGROUND;
static final int BACKGROUND = SWT.COLOR_WIDGET_BACKGROUND;
- static final int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW;
- static final int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND;
-
- static final int NONE = 0;
- static final int NORMAL = 1;
- static final int HOT = 2;
- static final int SELECTED = 3;
- static final RGB CLOSE_FILL = new RGB(252, 160, 160);
static final int CHEVRON_CHILD_ID = 0;
static final int MINIMIZE_CHILD_ID = 1;
static final int MAXIMIZE_CHILD_ID = 2;
static final int EXTRA_CHILD_ID_COUNT = 3;
-
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
@@ -307,15 +236,12 @@ void init(int style) {
// showMin = (style2 & SWT.MIN) != 0; - conflicts with SWT.TOP
// showMax = (style2 & SWT.MAX) != 0; - conflicts with SWT.BOTTOM
single = (style2 & SWT.SINGLE) != 0;
- borderLeft = borderRight = (style & SWT.BORDER) != 0 ? 1 : 0;
- borderTop = onBottom ? borderLeft : 0;
- borderBottom = onBottom ? 0 : borderLeft;
- highlight_header = (style & SWT.FLAT) != 0 ? 1 : 3;
- highlight_margin = (style & SWT.FLAT) != 0 ? 0 : 2;
+ borderVisible = (style & SWT.BORDER) != 0;
//set up default colors
Display display = getDisplay();
selectionForeground = display.getSystemColor(SELECTION_FOREGROUND);
selectionBackground = display.getSystemColor(SELECTION_BACKGROUND);
+ renderer = new CTabFolderRenderer(this);
updateTabHeight(false);
// Add all listeners
@@ -396,16 +322,7 @@ static int checkStyle (Composite parent, int style) {
return style | SWT.NO_BACKGROUND;
}
-static void fillRegion(GC gc, Region region) {
- // NOTE: region passed in to this function will be modified
- Region clipping = new Region();
- gc.getClipping(clipping);
- region.intersect(clipping);
- gc.setClipping(region);
- gc.fillRectangle(region.getBounds());
- gc.setClipping(clipping);
- clipping.dispose();
-}
+
/**
*
* Adds the listener to the collection of listeners who will
@@ -505,49 +422,7 @@ public void addSelectionListener(SelectionListener listener) {
addListener(SWT.Selection, typedListener);
addListener(SWT.DefaultSelection, typedListener);
}
-void antialias (int[] shape, Color innerColor, Color outerColor, GC gc){
- // Don't perform anti-aliasing on Mac and WPF because the platform
- // already does it. The simple style also does not require anti-aliasing.
- if (simple) return;
- String platform = SWT.getPlatform();
- if ("cocoa".equals(platform)) return; //$NON-NLS-1$
- if ("carbon".equals(platform)) return; //$NON-NLS-1$
- if ("wpf".equals(platform)) return; //$NON-NLS-1$
- // Don't perform anti-aliasing on low resolution displays
- if (getDisplay().getDepth() < 15) return;
- if (outerColor != null) {
- int index = 0;
- boolean left = true;
- int oldY = onBottom ? 0 : getSize().y;
- int[] outer = new int[shape.length];
- for (int i = 0; i < shape.length/2; i++) {
- if (left && (index + 3 < shape.length)) {
- left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
- oldY = shape[index+1];
- }
- outer[index] = shape[index++] + (left ? -1 : +1);
- outer[index] = shape[index++];
- }
- gc.setForeground(outerColor);
- gc.drawPolyline(outer);
- }
- if (innerColor != null) {
- int[] inner = new int[shape.length];
- int index = 0;
- boolean left = true;
- int oldY = onBottom ? 0 : getSize().y;
- for (int i = 0; i < shape.length/2; i++) {
- if (left && (index + 3 < shape.length)) {
- left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
- oldY = shape[index+1];
- }
- inner[index] = shape[index++] + (left ? +1 : -1);
- inner[index] = shape[index++];
- }
- gc.setForeground(innerColor);
- gc.drawPolyline(inner);
- }
-}
+
/*
* This class was not intended to be subclassed but this restriction
* cannot be enforced without breaking backward compatibility.
@@ -561,17 +436,7 @@ void antialias (int[] shape, Color innerColor, Color outerColor, GC gc){
//}
public Rectangle computeTrim (int x, int y, int width, int height) {
checkWidget();
- int trimX = x - marginWidth - highlight_margin - borderLeft;
- int trimWidth = width + borderLeft + borderRight + 2*marginWidth + 2*highlight_margin;
- if (minimized) {
- int trimY = onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop;
- int trimHeight = borderTop + borderBottom + tabHeight + highlight_header;
- return new Rectangle (trimX, trimY, trimWidth, trimHeight);
- } else {
- int trimY = onBottom ? y - marginHeight - highlight_margin - borderTop: y - marginHeight - highlight_header - tabHeight - borderTop;
- int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + highlight_header + highlight_margin;
- return new Rectangle (trimX, trimY, trimWidth, trimHeight);
- }
+ return renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, x, y, width, height);
}
void createItem (CTabItem item, int index) {
if (0 > index || index > getItemCount ())SWT.error (SWT.ERROR_INVALID_RANGE);
@@ -617,7 +482,9 @@ void destroyItem (CTabItem item) {
control.setVisible(false);
}
setToolTipText(null);
- setButtonBounds();
+ GC gc = new GC(this);
+ setButtonBounds(gc);
+ gc.dispose();
redraw();
return;
}
@@ -651,518 +518,7 @@ void destroyItem (CTabItem item) {
updateItems();
redrawTabs();
}
-void drawBackground(GC gc, int[] shape, boolean selected) {
- Color defaultBackground = selected ? selectionBackground : getBackground();
- Image image = selected ? selectionBgImage : null;
- Color[] colors = selected ? selectionGradientColors : gradientColors;
- int[] percents = selected ? selectionGradientPercents : gradientPercents;
- boolean vertical = selected ? selectionGradientVertical : gradientVertical;
- Point size = getSize();
- int width = size.x;
- int height = tabHeight + highlight_header;
- int x = 0;
- if (borderLeft > 0) {
- x += 1; width -= 2;
- }
- int y = onBottom ? size.y - borderBottom - height : borderTop;
- drawBackground(gc, shape, x, y, width, height, defaultBackground, image, colors, percents, vertical);
-}
-void drawBackground(GC gc, int[] shape, int x, int y, int width, int height, Color defaultBackground, Image image, Color[] colors, int[] percents, boolean vertical) {
- Region clipping = new Region();
- gc.getClipping(clipping);
- Region region = new Region();
- region.add(shape);
- region.intersect(clipping);
- gc.setClipping(region);
-
- if (image != null) {
- // draw the background image in shape
- gc.setBackground(defaultBackground);
- gc.fillRectangle(x, y, width, height);
- Rectangle imageRect = image.getBounds();
- gc.drawImage(image, imageRect.x, imageRect.y, imageRect.width, imageRect.height, x, y, width, height);
- } else if (colors != null) {
- // draw gradient
- if (colors.length == 1) {
- Color background = colors[0] != null ? colors[0] : defaultBackground;
- gc.setBackground(background);
- gc.fillRectangle(x, y, width, height);
- } else {
- if (vertical) {
- if (onBottom) {
- int pos = 0;
- if (percents[percents.length - 1] < 100) {
- pos = (100 - percents[percents.length - 1]) * height / 100;
- gc.setBackground(defaultBackground);
- gc.fillRectangle(x, y, width, pos);
- }
- Color lastColor = colors[colors.length-1];
- if (lastColor == null) lastColor = defaultBackground;
- for (int i = percents.length-1; i >= 0; i--) {
- gc.setForeground(lastColor);
- lastColor = colors[i];
- if (lastColor == null) lastColor = defaultBackground;
- gc.setBackground(lastColor);
- int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
- int gradientHeight = percentage * height / 100;
- gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
- pos += gradientHeight;
- }
- } else {
- Color lastColor = colors[0];
- if (lastColor == null) lastColor = defaultBackground;
- int pos = 0;
- for (int i = 0; i < percents.length; i++) {
- gc.setForeground(lastColor);
- lastColor = colors[i + 1];
- if (lastColor == null) lastColor = defaultBackground;
- gc.setBackground(lastColor);
- int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
- int gradientHeight = percentage * height / 100;
- gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
- pos += gradientHeight;
- }
- if (pos < height) {
- gc.setBackground(defaultBackground);
- gc.fillRectangle(x, pos, width, height-pos+1);
- }
- }
- } else { //horizontal gradient
- y = 0;
- height = getSize().y;
- Color lastColor = colors[0];
- if (lastColor == null) lastColor = defaultBackground;
- int pos = 0;
- for (int i = 0; i < percents.length; ++i) {
- gc.setForeground(lastColor);
- lastColor = colors[i + 1];
- if (lastColor == null) lastColor = defaultBackground;
- gc.setBackground(lastColor);
- int gradientWidth = (percents[i] * width / 100) - pos;
- gc.fillGradientRectangle(x+pos, y, gradientWidth, height, false);
- pos += gradientWidth;
- }
- if (pos < width) {
- gc.setBackground(defaultBackground);
- gc.fillRectangle(x+pos, y, width-pos, height);
- }
- }
- }
- } else {
- // draw a solid background using default background in shape
- if ((getStyle() & SWT.NO_BACKGROUND) != 0 || !defaultBackground.equals(getBackground())) {
- gc.setBackground(defaultBackground);
- gc.fillRectangle(x, y, width, height);
- }
- }
- gc.setClipping(clipping);
- clipping.dispose();
- region.dispose();
-}
-void drawBody(Event event) {
- GC gc = event.gc;
- Point size = getSize();
-
- // fill in body
- if (!minimized){
- int width = size.x - borderLeft - borderRight - 2*highlight_margin;
- int height = size.y - borderTop - borderBottom - tabHeight - highlight_header - highlight_margin;
- // Draw highlight margin
- if (highlight_margin > 0) {
- int[] shape = null;
- if (onBottom) {
- int x1 = borderLeft;
- int y1 = borderTop;
- int x2 = size.x - borderRight;
- int y2 = size.y - borderBottom - tabHeight - highlight_header;
- shape = new int[] {x1,y1, x2,y1, x2,y2, x2-highlight_margin,y2,
- x2-highlight_margin, y1+highlight_margin, x1+highlight_margin,y1+highlight_margin,
- x1+highlight_margin,y2, x1,y2};
- } else {
- int x1 = borderLeft;
- int y1 = borderTop + tabHeight + highlight_header;
- int x2 = size.x - borderRight;
- int y2 = size.y - borderBottom;
- shape = new int[] {x1,y1, x1+highlight_margin,y1, x1+highlight_margin,y2-highlight_margin,
- x2-highlight_margin,y2-highlight_margin, x2-highlight_margin,y1,
- x2,y1, x2,y2, x1,y2};
- }
- // If horizontal gradient, show gradient across the whole area
- if (selectedIndex != -1 && selectionGradientColors != null && selectionGradientColors.length > 1 && !selectionGradientVertical) {
- drawBackground(gc, shape, true);
- } else if (selectedIndex == -1 && gradientColors != null && gradientColors.length > 1 && !gradientVertical) {
- drawBackground(gc, shape, false);
- } else {
- gc.setBackground(selectedIndex == -1 ? getBackground() : selectionBackground);
- gc.fillPolygon(shape);
- }
- }
- //Draw client area
- if ((getStyle() & SWT.NO_BACKGROUND) != 0) {
- gc.setBackground(getBackground());
- gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, width, height);
- }
- } else {
- if ((getStyle() & SWT.NO_BACKGROUND) != 0) {
- int height = borderTop + tabHeight + highlight_header + borderBottom;
- if (size.y > height) {
- gc.setBackground(getParent().getBackground());
- gc.fillRectangle(0, height, size.x, size.y - height);
- }
- }
- }
-
- //draw 1 pixel border around outside
- if (borderLeft > 0) {
- gc.setForeground(getDisplay().getSystemColor(BORDER1_COLOR));
- int x1 = borderLeft - 1;
- int x2 = size.x - borderRight;
- int y1 = onBottom ? borderTop - 1 : borderTop + tabHeight;
- int y2 = onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom;
- gc.drawLine(x1, y1, x1, y2); // left
- gc.drawLine(x2, y1, x2, y2); // right
- if (onBottom) {
- gc.drawLine(x1, y1, x2, y1); // top
- } else {
- gc.drawLine(x1, y2, x2, y2); // bottom
- }
- }
-}
-void drawChevron(GC gc) {
- if (chevronRect.width == 0 || chevronRect.height == 0) return;
- // draw chevron (10x7)
- Display display = getDisplay();
- Point dpi = display.getDPI();
- int fontHeight = 72 * 10 / dpi.y;
- FontData fd = getFont().getFontData()[0];
- fd.setHeight(fontHeight);
- Font f = new Font(display, fd);
- int fHeight = f.getFontData()[0].getHeight() * dpi.y / 72;
- int indent = Math.max(2, (chevronRect.height - fHeight - 4) /2);
- int x = chevronRect.x + 2;
- int y = chevronRect.y + indent;
- int count;
- if (single) {
- count = selectedIndex == -1 ? items.length : items.length - 1;
- } else {
- int showCount = 0;
- while (showCount < priority.length && items[priority[showCount]].showing) {
- showCount++;
- }
- count = items.length - showCount;
- }
- String chevronString = count > 99 ? "99+" : String.valueOf(count); //$NON-NLS-1$
- switch (chevronImageState) {
- case NORMAL: {
- Color chevronBorder = single ? getSelectionForeground() : getForeground();
- gc.setForeground(chevronBorder);
- gc.setFont(f);
- gc.drawLine(x,y, x+2,y+2);
- gc.drawLine(x+2,y+2, x,y+4);
- gc.drawLine(x+1,y, x+3,y+2);
- gc.drawLine(x+3,y+2, x+1,y+4);
- gc.drawLine(x+4,y, x+6,y+2);
- gc.drawLine(x+6,y+2, x+5,y+4);
- gc.drawLine(x+5,y, x+7,y+2);
- gc.drawLine(x+7,y+2, x+4,y+4);
- gc.drawString(chevronString, x+7, y+3, true);
- break;
- }
- case HOT: {
- gc.setForeground(display.getSystemColor(BUTTON_BORDER));
- gc.setBackground(display.getSystemColor(BUTTON_FILL));
- gc.setFont(f);
- gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
- gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
- gc.drawLine(x,y, x+2,y+2);
- gc.drawLine(x+2,y+2, x,y+4);
- gc.drawLine(x+1,y, x+3,y+2);
- gc.drawLine(x+3,y+2, x+1,y+4);
- gc.drawLine(x+4,y, x+6,y+2);
- gc.drawLine(x+6,y+2, x+5,y+4);
- gc.drawLine(x+5,y, x+7,y+2);
- gc.drawLine(x+7,y+2, x+4,y+4);
- gc.drawString(chevronString, x+7, y+3, true);
- break;
- }
- case SELECTED: {
- gc.setForeground(display.getSystemColor(BUTTON_BORDER));
- gc.setBackground(display.getSystemColor(BUTTON_FILL));
- gc.setFont(f);
- gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
- gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
- gc.drawLine(x+1,y+1, x+3,y+3);
- gc.drawLine(x+3,y+3, x+1,y+5);
- gc.drawLine(x+2,y+1, x+4,y+3);
- gc.drawLine(x+4,y+3, x+2,y+5);
- gc.drawLine(x+5,y+1, x+7,y+3);
- gc.drawLine(x+7,y+3, x+6,y+5);
- gc.drawLine(x+6,y+1, x+8,y+3);
- gc.drawLine(x+8,y+3, x+5,y+5);
- gc.drawString(chevronString, x+8, y+4, true);
- break;
- }
- }
- f.dispose();
-}
-void drawMaximize(GC gc) {
- if (maxRect.width == 0 || maxRect.height == 0) return;
- Display display = getDisplay();
- // 5x4 or 7x9
- int x = maxRect.x + (CTabFolder.BUTTON_SIZE - 10)/2;
- int y = maxRect.y + 3;
-
- gc.setForeground(display.getSystemColor(BUTTON_BORDER));
- gc.setBackground(display.getSystemColor(BUTTON_FILL));
-
- switch (maxImageState) {
- case NORMAL: {
- if (!maximized) {
- gc.fillRectangle(x, y, 9, 9);
- gc.drawRectangle(x, y, 9, 9);
- gc.drawLine(x+1, y+2, x+8, y+2);
- } else {
- gc.fillRectangle(x, y+3, 5, 4);
- gc.fillRectangle(x+2, y, 5, 4);
- gc.drawRectangle(x, y+3, 5, 4);
- gc.drawRectangle(x+2, y, 5, 4);
- gc.drawLine(x+3, y+1, x+6, y+1);
- gc.drawLine(x+1, y+4, x+4, y+4);
- }
- break;
- }
- case HOT: {
- gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
- gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
- if (!maximized) {
- gc.fillRectangle(x, y, 9, 9);
- gc.drawRectangle(x, y, 9, 9);
- gc.drawLine(x+1, y+2, x+8, y+2);
- } else {
- gc.fillRectangle(x, y+3, 5, 4);
- gc.fillRectangle(x+2, y, 5, 4);
- gc.drawRectangle(x, y+3, 5, 4);
- gc.drawRectangle(x+2, y, 5, 4);
- gc.drawLine(x+3, y+1, x+6, y+1);
- gc.drawLine(x+1, y+4, x+4, y+4);
- }
- break;
- }
- case SELECTED: {
- gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
- gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
- if (!maximized) {
- gc.fillRectangle(x+1, y+1, 9, 9);
- gc.drawRectangle(x+1, y+1, 9, 9);
- gc.drawLine(x+2, y+3, x+9, y+3);
- } else {
- gc.fillRectangle(x+1, y+4, 5, 4);
- gc.fillRectangle(x+3, y+1, 5, 4);
- gc.drawRectangle(x+1, y+4, 5, 4);
- gc.drawRectangle(x+3, y+1, 5, 4);
- gc.drawLine(x+4, y+2, x+7, y+2);
- gc.drawLine(x+2, y+5, x+5, y+5);
- }
- break;
- }
- }
-}
-void drawMinimize(GC gc) {
- if (minRect.width == 0 || minRect.height == 0) return;
- Display display = getDisplay();
- // 5x4 or 9x3
- int x = minRect.x + (BUTTON_SIZE - 10)/2;
- int y = minRect.y + 3;
-
- gc.setForeground(display.getSystemColor(BUTTON_BORDER));
- gc.setBackground(display.getSystemColor(BUTTON_FILL));
-
- switch (minImageState) {
- case NORMAL: {
- if (!minimized) {
- gc.fillRectangle(x, y, 9, 3);
- gc.drawRectangle(x, y, 9, 3);
- } else {
- gc.fillRectangle(x, y+3, 5, 4);
- gc.fillRectangle(x+2, y, 5, 4);
- gc.drawRectangle(x, y+3, 5, 4);
- gc.drawRectangle(x+2, y, 5, 4);
- gc.drawLine(x+3, y+1, x+6, y+1);
- gc.drawLine(x+1, y+4, x+4, y+4);
- }
- break;
- }
- case HOT: {
- gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
- gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
- if (!minimized) {
- gc.fillRectangle(x, y, 9, 3);
- gc.drawRectangle(x, y, 9, 3);
- } else {
- gc.fillRectangle(x, y+3, 5, 4);
- gc.fillRectangle(x+2, y, 5, 4);
- gc.drawRectangle(x, y+3, 5, 4);
- gc.drawRectangle(x+2, y, 5, 4);
- gc.drawLine(x+3, y+1, x+6, y+1);
- gc.drawLine(x+1, y+4, x+4, y+4);
- }
- break;
- }
- case SELECTED: {
- gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
- gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
- if (!minimized) {
- gc.fillRectangle(x+1, y+1, 9, 3);
- gc.drawRectangle(x+1, y+1, 9, 3);
- } else {
- gc.fillRectangle(x+1, y+4, 5, 4);
- gc.fillRectangle(x+3, y+1, 5, 4);
- gc.drawRectangle(x+1, y+4, 5, 4);
- gc.drawRectangle(x+3, y+1, 5, 4);
- gc.drawLine(x+4, y+2, x+7, y+2);
- gc.drawLine(x+2, y+5, x+5, y+5);
- }
- break;
- }
- }
-}
-void drawTabArea(Event event) {
- GC gc = event.gc;
- Point size = getSize();
- int[] shape = null;
- Color borderColor = getDisplay().getSystemColor(BORDER1_COLOR);
-
- if (tabHeight == 0) {
- int style = getStyle();
- if ((style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) return;
- int x1 = borderLeft - 1;
- int x2 = size.x - borderRight;
- int y1 = onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header;
- int y2 = onBottom ? size.y - borderBottom : borderTop;
- if (borderLeft > 0 && onBottom) y2 -= 1;
-
- shape = new int[] {x1, y1, x1,y2, x2,y2, x2,y1};
-
- // If horizontal gradient, show gradient across the whole area
- if (selectedIndex != -1 && selectionGradientColors != null && selectionGradientColors.length > 1 && !selectionGradientVertical) {
- drawBackground(gc, shape, true);
- } else if (selectedIndex == -1 && gradientColors != null && gradientColors.length > 1 && !gradientVertical) {
- drawBackground(gc, shape, false);
- } else {
- gc.setBackground(selectedIndex == -1 ? getBackground() : selectionBackground);
- gc.fillPolygon(shape);
- }
-
- //draw 1 pixel border
- if (borderLeft > 0) {
- gc.setForeground(borderColor);
- gc.drawPolyline(shape);
- }
- return;
- }
-
- int x = Math.max(0, borderLeft - 1);
- int y = onBottom ? size.y - borderBottom - tabHeight : borderTop;
- int width = size.x - borderLeft - borderRight + 1;
- int height = tabHeight - 1;
-
- // Draw Tab Header
- if (onBottom) {
- int[] left, right;
- if ((getStyle() & SWT.BORDER) != 0) {
- left = simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER;
- right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER : BOTTOM_RIGHT_CORNER;
- } else {
- left = simple ? SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS : BOTTOM_LEFT_CORNER_BORDERLESS;
- right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS : BOTTOM_RIGHT_CORNER_BORDERLESS;
- }
- shape = new int[left.length + right.length + 4];
- int index = 0;
- shape[index++] = x;
- shape[index++] = y-highlight_header;
- for (int i = 0; i < left.length/2; i++) {
- shape[index++] = x+left[2*i];
- shape[index++] = y+height+left[2*i+1];
- if (borderLeft == 0) shape[index-1] += 1;
- }
- for (int i = 0; i < right.length/2; i++) {
- shape[index++] = x+width+right[2*i];
- shape[index++] = y+height+right[2*i+1];
- if (borderLeft == 0) shape[index-1] += 1;
- }
- shape[index++] = x+width;
- shape[index++] = y-highlight_header;
- } else {
- int[] left, right;
- if ((getStyle() & SWT.BORDER) != 0) {
- left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
- right = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER;
- } else {
- left = simple ? SIMPLE_TOP_LEFT_CORNER_BORDERLESS : TOP_LEFT_CORNER_BORDERLESS;
- right = simple ? SIMPLE_TOP_RIGHT_CORNER_BORDERLESS : TOP_RIGHT_CORNER_BORDERLESS;
- }
- shape = new int[left.length + right.length + 4];
- int index = 0;
- shape[index++] = x;
- shape[index++] = y+height+highlight_header + 1;
- for (int i = 0; i < left.length/2; i++) {
- shape[index++] = x+left[2*i];
- shape[index++] = y+left[2*i+1];
- }
- for (int i = 0; i < right.length/2; i++) {
- shape[index++] = x+width+right[2*i];
- shape[index++] = y+right[2*i+1];
- }
- shape[index++] = x+width;
- shape[index++] = y+height+highlight_header + 1;
- }
- // Fill in background
- boolean bkSelected = single && selectedIndex != -1;
- drawBackground(gc, shape, bkSelected);
- // Fill in parent background for non-rectangular shape
- Region r = new Region();
- r.add(new Rectangle(x, y, width + 1, height + 1));
- r.subtract(shape);
- gc.setBackground(getParent().getBackground());
- fillRegion(gc, r);
- r.dispose();
-
- // Draw the unselected tabs.
- if (!single) {
- for (int i=0; i < items.length; i++) {
- if (i != selectedIndex && event.getBounds().intersects(items[i].getBounds())) {
- items[i].onPaint(gc, false);
- }
- }
- }
-
- // Draw selected tab
- if (selectedIndex != -1) {
- CTabItem item = items[selectedIndex];
- item.onPaint(gc, true);
- } else {
- // if no selected tab - draw line across bottom of all tabs
- int x1 = borderLeft;
- int y1 = (onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight;
- int x2 = size.x - borderRight;
- gc.setForeground(borderColor);
- gc.drawLine(x1, y1, x2, y1);
- }
-
- // Draw Buttons
- drawChevron(gc);
- drawMinimize(gc);
- drawMaximize(gc);
-
- // Draw border line
- if (borderLeft > 0) {
- if (! borderColor.equals(lastBorderColor)) createAntialiasColors();
- antialias(shape, null, tabAreaColor, gc);
- gc.setForeground(borderColor);
- gc.drawPolyline(shape);
- }
-}
/**
* Returns <code>true</code> if the receiver's border is visible.
*
@@ -1177,23 +533,18 @@ void drawTabArea(Event event) {
*/
public boolean getBorderVisible() {
checkWidget();
- return borderLeft == 1;
+ return borderVisible;
}
public Rectangle getClientArea() {
checkWidget();
- if (minimized) return new Rectangle(xClient, yClient, 0, 0);
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+ if (minimized) return new Rectangle(-trim.x, -trim.y, 0, 0);
Point size = getSize();
- int width = size.x - borderLeft - borderRight - 2*marginWidth - 2*highlight_margin;
- int height = size.y - borderTop - borderBottom - 2*marginHeight - highlight_margin - highlight_header;
- height -= tabHeight;
- return new Rectangle(xClient, yClient, width, height);
-}
-Color getFillColor() {
- if (fillColor == null) {
- fillColor = new Color(getDisplay(), CTabFolder.CLOSE_FILL);
- }
- return fillColor;
+ int width = size.x - trim.width;
+ int height = size.y - trim.height;
+ return new Rectangle(-trim.x, -trim.y, width, height);
}
+
/**
* Return the tab that is located at the specified index.
*
@@ -1229,7 +580,8 @@ public CTabItem getItem (Point pt) {
//checkWidget();
if (items.length == 0) return null;
Point size = getSize();
- if (size.x <= borderLeft + borderRight) return null;
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0);
+ if (size.x <= trim.width) return null;
if (showChevron && chevronRect.contains(pt)) return null;
for (int i = 0; i < priority.length; i++) {
CTabItem item = items[priority[i]];
@@ -1268,6 +620,7 @@ public CTabItem [] getItems() {
System.arraycopy(items, 0, tabItems, 0, items.length);
return tabItems;
}
+
/*
* Return the lowercase of the first non-'&' character following
* an '&' character in the given string. If there are no '&'
@@ -1343,6 +696,7 @@ public int getMinimumCharacters() {
checkWidget();
return minChars;
}
+
/**
* Returns <code>true</code> if the receiver is maximized.
* <p>
@@ -1410,11 +764,16 @@ public boolean getMRUVisible() {
checkWidget();
return mru;
}
-int getRightItemEdge (){
- int x = getSize().x - borderRight - 3;
- if (showMin) x -= BUTTON_SIZE;
- if (showMax) x -= BUTTON_SIZE;
- if (showChevron) x -= 3*BUTTON_SIZE/2;
+/*public*/ CTabFolderRenderer getRenderer() {
+ checkWidget();
+ return renderer;
+}
+int getRightItemEdge (GC gc){
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0);
+ int x = getSize().x - (trim.width + trim.x) - 3; //TODO: add setter for spacing?
+ if (showMin) x -= renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc).x;
+ if (showMax) x -= renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc).x;;
+ if (showChevron) x -= renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc).x;
if (topRight != null && topRightAlignment != SWT.FILL) {
Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT);
x -= rightSize.x + 3;
@@ -1514,7 +873,7 @@ public int getStyle() {
style |= onBottom ? SWT.BOTTOM : SWT.TOP;
style &= ~(SWT.SINGLE | SWT.MULTI);
style |= single ? SWT.SINGLE : SWT.MULTI;
- if (borderLeft != 0) style |= SWT.BORDER;
+ if (borderVisible) style |= SWT.BORDER;
style &= ~SWT.CLOSE;
if (showClose) style |= SWT.CLOSE;
return style;
@@ -1532,7 +891,7 @@ public int getStyle() {
public int getTabHeight(){
checkWidget();
if (fixedTabHeight != SWT.DEFAULT) return fixedTabHeight;
- return tabHeight - 1; // -1 for line drawn across top of tab
+ return tabHeight - 1; // -1 for line drawn across top of tab //TODO: replace w/ computeTrim of tab area?
}
/**
* Returns the position of the tab. Possible values are SWT.TOP or SWT.BOTTOM.
@@ -1566,6 +925,23 @@ public Control getTopRight() {
return topRight;
}
/**
+ * Returns the alignment of the top right control.
+ *
+ * @return the alignment of the top right control which is either
+ * <code>SWT.RIGHT</code> or <code>SWT.FILL</code>
+ *
+ * @exception SWTException <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>
+ *
+ * @since 3.6
+ */
+public int getTopRightAlignment() {
+ checkWidget();
+ return topRightAlignment;
+}
+/**
* Returns <code>true</code> if the close button appears
* when the user hovers over an unselected tabs.
*
@@ -1892,10 +1268,7 @@ void onDispose(Event event) {
items[i].dispose();
}
}
- if (fillColor != null) {
- fillColor.dispose();
- fillColor = null;
- }
+
selectionGradientColors = null;
selectionGradientPercents = null;
@@ -1904,8 +1277,8 @@ void onDispose(Event event) {
selectionBackground = null;
selectionForeground = null;
- disposeSelectionHighlightGradientColors();
- disposeAntialiasColors();
+ if (renderer != null) renderer.dispose();
+ renderer = null;
}
void onDragDetect(Event event) {
boolean consume = false;
@@ -1969,26 +1342,26 @@ void onMouse(Event event) {
break;
}
case SWT.MouseExit: {
- if (minImageState != NORMAL) {
- minImageState = NORMAL;
+ if (minImageState != SWT.NONE) {
+ minImageState = SWT.NONE;
redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
}
- if (maxImageState != NORMAL) {
- maxImageState = NORMAL;
+ if (maxImageState != SWT.NONE) {
+ maxImageState = SWT.NONE;
redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
}
- if (chevronImageState != NORMAL) {
- chevronImageState = NORMAL;
+ if (chevronImageState != SWT.NONE) {
+ chevronImageState = SWT.NONE;
redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
}
for (int i=0; i<items.length; i++) {
CTabItem item = items[i];
- if (i != selectedIndex && item.closeImageState != NONE) {
- item.closeImageState = NONE;
+ if (i != selectedIndex && item.closeImageState != SWT.BACKGROUND) {
+ item.closeImageState = SWT.BACKGROUND;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
- if (i == selectedIndex && item.closeImageState != NORMAL) {
- item.closeImageState = NORMAL;
+ if (i == selectedIndex && item.closeImageState != SWT.NONE) {
+ item.closeImageState = SWT.NONE;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
}
@@ -1997,22 +1370,22 @@ void onMouse(Event event) {
case SWT.MouseDown: {
if (event.button != 1) return;
if (minRect.contains(x, y)) {
- minImageState = SELECTED;
+ minImageState = SWT.SELECTED;
redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
update();
return;
}
if (maxRect.contains(x, y)) {
- maxImageState = SELECTED;
+ maxImageState = SWT.SELECTED;
redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
update();
return;
}
if (chevronRect.contains(x, y)) {
- if (chevronImageState != HOT) {
- chevronImageState = HOT;
+ if (chevronImageState != SWT.HOT) {
+ chevronImageState = SWT.HOT;
} else {
- chevronImageState = SELECTED;
+ chevronImageState = SWT.SELECTED;
}
redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
update();
@@ -2036,7 +1409,7 @@ void onMouse(Event event) {
}
if (item != null) {
if (item.closeRect.contains(x,y)){
- item.closeImageState = SELECTED;
+ item.closeImageState = SWT.SELECTED;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
update();
return;
@@ -2059,35 +1432,35 @@ void onMouse(Event event) {
boolean close = false, minimize = false, maximize = false, chevron = false;
if (minRect.contains(x, y)) {
minimize = true;
- if (minImageState != SELECTED && minImageState != HOT) {
- minImageState = HOT;
+ if (minImageState != SWT.SELECTED && minImageState != SWT.HOT) {
+ minImageState = SWT.HOT;
redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
}
}
if (maxRect.contains(x, y)) {
maximize = true;
- if (maxImageState != SELECTED && maxImageState != HOT) {
- maxImageState = HOT;
+ if (maxImageState != SWT.SELECTED && maxImageState != SWT.HOT) {
+ maxImageState = SWT.HOT;
redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
}
}
if (chevronRect.contains(x, y)) {
chevron = true;
- if (chevronImageState != SELECTED && chevronImageState != HOT) {
- chevronImageState = HOT;
+ if (chevronImageState != SWT.SELECTED && chevronImageState != SWT.HOT) {
+ chevronImageState = SWT.HOT;
redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
}
}
- if (minImageState != NORMAL && !minimize) {
- minImageState = NORMAL;
+ if (minImageState != SWT.NONE && !minimize) {
+ minImageState = SWT.NONE;
redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
}
- if (maxImageState != NORMAL && !maximize) {
- maxImageState = NORMAL;
+ if (maxImageState != SWT.NONE && !maximize) {
+ maxImageState = SWT.NONE;
redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
}
- if (chevronImageState != NORMAL && !chevron) {
- chevronImageState = NORMAL;
+ if (chevronImageState != SWT.NONE && !chevron) {
+ chevronImageState = SWT.NONE;
redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
}
for (int i=0; i<items.length; i++) {
@@ -2096,23 +1469,23 @@ void onMouse(Event event) {
if (item.getBounds().contains(x, y)) {
close = true;
if (item.closeRect.contains(x, y)) {
- if (item.closeImageState != SELECTED && item.closeImageState != HOT) {
- item.closeImageState = HOT;
+ if (item.closeImageState != SWT.SELECTED && item.closeImageState != SWT.HOT) {
+ item.closeImageState = SWT.HOT;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
} else {
- if (item.closeImageState != NORMAL) {
- item.closeImageState = NORMAL;
+ if (item.closeImageState != SWT.NONE) {
+ item.closeImageState = SWT.NONE;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
}
}
- if (i != selectedIndex && item.closeImageState != NONE && !close) {
- item.closeImageState = NONE;
+ if (i != selectedIndex && item.closeImageState != SWT.BACKGROUND && !close) {
+ item.closeImageState = SWT.BACKGROUND;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
- if (i == selectedIndex && item.closeImageState != NORMAL && !close) {
- item.closeImageState = NORMAL;
+ if (i == selectedIndex && item.closeImageState != SWT.NONE && !close) {
+ item.closeImageState = SWT.NONE;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
}
}
@@ -2121,7 +1494,7 @@ void onMouse(Event event) {
case SWT.MouseUp: {
if (event.button != 1) return;
if (chevronRect.contains(x, y)) {
- boolean selected = chevronImageState == SELECTED;
+ boolean selected = chevronImageState == SWT.SELECTED;
if (!selected) return;
CTabFolderEvent e = new CTabFolderEvent(this);
e.widget = this;
@@ -2140,8 +1513,8 @@ void onMouse(Event event) {
return;
}
if (minRect.contains(x, y)) {
- boolean selected = minImageState == SELECTED;
- minImageState = HOT;
+ boolean selected = minImageState == SWT.SELECTED;
+ minImageState = SWT.HOT;
redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
if (!selected) return;
CTabFolderEvent e = new CTabFolderEvent(this);
@@ -2157,8 +1530,8 @@ void onMouse(Event event) {
return;
}
if (maxRect.contains(x, y)) {
- boolean selected = maxImageState == SELECTED;
- maxImageState = HOT;
+ boolean selected = maxImageState == SWT.SELECTED;
+ maxImageState = SWT.HOT;
redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
if (!selected) return;
CTabFolderEvent e = new CTabFolderEvent(this);
@@ -2191,8 +1564,8 @@ void onMouse(Event event) {
}
if (item != null) {
if (item.closeRect.contains(x,y)) {
- boolean selected = item.closeImageState == SELECTED;
- item.closeImageState = HOT;
+ boolean selected = item.closeImageState == SWT.SELECTED;
+ item.closeImageState = SWT.HOT;
redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
if (!selected) return;
CTabFolderEvent e = new CTabFolderEvent(this);
@@ -2216,13 +1589,13 @@ void onMouse(Event event) {
CTabItem nextItem = getItem(pt);
if (nextItem != null) {
if (nextItem.closeRect.contains(pt)) {
- if (nextItem.closeImageState != SELECTED && nextItem.closeImageState != HOT) {
- nextItem.closeImageState = HOT;
+ if (nextItem.closeImageState != SWT.SELECTED && nextItem.closeImageState != SWT.HOT) {
+ nextItem.closeImageState = SWT.HOT;
redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
}
} else {
- if (nextItem.closeImageState != NORMAL) {
- nextItem.closeImageState = NORMAL;
+ if (nextItem.closeImageState != SWT.NONE) {
+ nextItem.closeImageState = SWT.NONE;
redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
}
}
@@ -2303,17 +1676,48 @@ void onPaint(Event event) {
//gc.fillRectangle(-10, -10, size.x + 20, size.y+20);
//}
- drawBody(event);
-
+ Point size = getSize();
+ Rectangle bodyRect = new Rectangle(0, 0, size.x, size.y);
+ renderer.draw(CTabFolderRenderer.PART_BODY, SWT.BACKGROUND | SWT.FOREGROUND, bodyRect, gc);
+
gc.setFont(gcFont);
gc.setForeground(gcForeground);
gc.setBackground(gcBackground);
- drawTabArea(event);
+ renderer.draw(CTabFolderRenderer.PART_HEADER, SWT.BACKGROUND | SWT.FOREGROUND, bodyRect, gc);
+
+ gc.setFont(gcFont);
+ gc.setForeground(gcForeground);
+ gc.setBackground(gcBackground);
+
+ if (!single) {
+ for (int i=0; i < items.length; i++) {
+ Rectangle itemBounds = items[i].getBounds();
+ if (i != selectedIndex && event.getBounds().intersects(itemBounds)) {
+ renderer.draw(i, SWT.BACKGROUND | SWT.FOREGROUND, itemBounds, gc);
+ }
+ }
+ }
+
+ gc.setFont(gcFont);
+ gc.setForeground(gcForeground);
+ gc.setBackground(gcBackground);
+
+ if (selectedIndex != -1) {
+ renderer.draw(selectedIndex, SWT.SELECTED | SWT.BACKGROUND | SWT.FOREGROUND, items[selectedIndex].getBounds(), gc);
+ }
gc.setFont(gcFont);
gc.setForeground(gcForeground);
gc.setBackground(gcBackground);
+
+ renderer.draw(CTabFolderRenderer.PART_MAX_BUTTON, maxImageState, maxRect, gc);
+ renderer.draw(CTabFolderRenderer.PART_MIN_BUTTON, minImageState, minRect, gc);
+ renderer.draw(CTabFolderRenderer.PART_CHEVRON_BUTTON, chevronImageState, chevronRect, gc);
+
+ gc.setFont(gcFont);
+ gc.setForeground(gcForeground);
+ gc.setBackground(gcBackground);
}
void onResize() {
@@ -2327,10 +1731,11 @@ void onResize() {
redraw();
} else {
int x1 = Math.min(size.x, oldSize.x);
- if (size.x != oldSize.x) x1 -= borderRight + highlight_margin + 2;
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+ if (size.x != oldSize.x) x1 -= trim.width + trim.x - marginWidth + 2;
if (!simple) x1 -= 5; // rounded top right corner
int y1 = Math.min(size.y, oldSize.y);
- if (size.y != oldSize.y) y1 -= borderBottom + highlight_margin;
+ if (size.y != oldSize.y) y1 -= trim.height + trim.y - marginHeight;
int x2 = Math.max(size.x, oldSize.x);
int y2 = Math.max(size.y, oldSize.y);
redraw(0, y1, x2, y2 - y1, false);
@@ -2377,10 +1782,12 @@ void onTraverse (Event event) {
}
void redrawTabs() {
Point size = getSize();
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
if (onBottom) {
- redraw(0, size.y - borderBottom - tabHeight - highlight_header - 1, size.x, borderBottom + tabHeight + highlight_header + 1, false);
+ int h = trim.height + trim.y - marginHeight;
+ redraw(0, size.y - h - 1, size.x, h + 1, false);
} else {
- redraw(0, 0, size.x, borderTop + tabHeight + highlight_header + 1, false);
+ redraw(0, 0, size.x, -trim.y - marginHeight + 1, false);
}
}
/**
@@ -2494,7 +1901,7 @@ public void reskin(int flags) {
public void setBackground (Color color) {
super.setBackground(color);
- createAntialiasColors();
+ renderer.createAntialiasColors(); //TODO: need better caching strategy
redraw();
}
/**
@@ -2621,7 +2028,7 @@ void setBackground(Color[] colors, int[] percents, boolean vertical) {
}
public void setBackgroundImage(Image image) {
super.setBackgroundImage(image);
- createAntialiasColors();
+ renderer.createAntialiasColors(); //TODO: need better caching strategy
redraw();
}
/**
@@ -2636,10 +2043,8 @@ public void setBackgroundImage(Image image) {
*/
public void setBorderVisible(boolean show) {
checkWidget();
- if ((borderLeft == 1) == show) return;
- borderLeft = borderRight = show ? 1 : 0;
- borderTop = onBottom ? borderLeft : 0;
- borderBottom = onBottom ? 0 : borderLeft;
+ if (borderVisible == show) return;
+ this.borderVisible = show;
Rectangle rectBefore = getClientArea();
updateItems();
Rectangle rectAfter = getClientArea();
@@ -2648,9 +2053,15 @@ public void setBorderVisible(boolean show) {
}
redraw();
}
-void setButtonBounds() {
+void setButtonBounds(GC gc) {
Point size = getSize();
int oldX, oldY, oldWidth, oldHeight;
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+ int borderRight = trim.width + trim.x;
+ int borderLeft = -trim.x;
+ int borderBottom = trim.height + trim.y;
+ int borderTop = -trim.y;
+
// max button
oldX = maxRect.x;
oldY = maxRect.y;
@@ -2658,11 +2069,12 @@ void setButtonBounds() {
oldHeight = maxRect.height;
maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0;
if (showMax) {
- maxRect.x = size.x - borderRight - BUTTON_SIZE - 3;
+ Point maxSize = renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc);
+ maxRect.x = size.x - borderRight - maxSize.x - 3;
if (borderRight > 0) maxRect.x += 1;
- maxRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
- maxRect.width = BUTTON_SIZE;
- maxRect.height = BUTTON_SIZE;
+ maxRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - maxSize.y)/2: borderTop + (tabHeight - maxSize.y)/2;
+ maxRect.width = maxSize.x;
+ maxRect.height = maxSize.y;
}
if (oldX != maxRect.x || oldWidth != maxRect.width ||
oldY != maxRect.y || oldHeight != maxRect.height) {
@@ -2671,7 +2083,7 @@ void setButtonBounds() {
int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
redraw(left, top, right - left, tabHeight, false);
}
-
+
// min button
oldX = minRect.x;
oldY = minRect.y;
@@ -2679,11 +2091,12 @@ void setButtonBounds() {
oldHeight = minRect.height;
minRect.x = minRect.y = minRect.width = minRect.height = 0;
if (showMin) {
- minRect.x = size.x - borderRight - maxRect.width - BUTTON_SIZE - 3;
+ Point minSize = renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc);
+ minRect.x = size.x - borderRight - maxRect.width - minSize.x - 3;
if (borderRight > 0) minRect.x += 1;
- minRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
- minRect.width = BUTTON_SIZE;
- minRect.height = BUTTON_SIZE;
+ minRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - minSize.y)/2: borderTop + (tabHeight - minSize.y)/2;
+ minRect.width = minSize.x;
+ minRect.height = minSize.y;
}
if (oldX != minRect.x || oldWidth != minRect.width ||
oldY != minRect.y || oldHeight != minRect.height) {
@@ -2711,8 +2124,9 @@ void setButtonBounds() {
} else {
// fill size is 0 if item compressed
CTabItem item = items[selectedIndex];
- if (item.x + item.width + 7 + 3*BUTTON_SIZE/2 >= rightEdge) break;
- topRightRect.x = item.x + item.width + 7 + 3*BUTTON_SIZE/2;
+ int chevronWidth = renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc).x;
+ if (item.x + item.width + 7 + chevronWidth >= rightEdge) break;
+ topRightRect.x = item.x + item.width + 7 + chevronWidth;
topRightRect.width = rightEdge - topRightRect.x;
}
} else {
@@ -2721,9 +2135,9 @@ void setButtonBounds() {
if (items.length == 0) {
topRightRect.x = borderLeft + 3;
} else {
- CTabItem item = items[items.length - 1];
- topRightRect.x = item.x + item.width;
- if (!simple && items.length - 1 == selectedIndex) topRightRect.x += curveWidth - curveIndent;
+ int lastIndex = items.length - 1;
+ CTabItem lastItem = items[lastIndex];
+ topRightRect.x = lastItem.x + lastItem.width;
}
topRightRect.width = Math.max(0, rightEdge - topRightRect.x);
}
@@ -2757,10 +2171,11 @@ void setButtonBounds() {
oldWidth = chevronRect.width;
oldHeight = chevronRect.height;
chevronRect.x = chevronRect.y = chevronRect.height = chevronRect.width = 0;
+ Point chevronSize = renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc);
if (single) {
if (selectedIndex == -1 || items.length > 1) {
- chevronRect.width = 3*BUTTON_SIZE/2;
- chevronRect.height = BUTTON_SIZE;
+ chevronRect.width = chevronSize.x;
+ chevronRect.height = chevronSize.y;
chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2;
if (selectedIndex == -1) {
chevronRect.x = size.x - borderRight - 3 - minRect.width - maxRect.width - topRightRect.width - chevronRect.width;
@@ -2774,8 +2189,8 @@ void setButtonBounds() {
}
} else {
if (showChevron) {
- chevronRect.width = 3*BUTTON_SIZE/2;
- chevronRect.height = BUTTON_SIZE;
+ chevronRect.width = chevronSize.x;
+ chevronRect.height = chevronSize.y;
int i = 0, lastIndex = -1;
while (i < priority.length && items[priority[i]].showing) {
lastIndex = Math.max(lastIndex, priority[i++]);
@@ -2783,8 +2198,8 @@ void setButtonBounds() {
if (lastIndex == -1) lastIndex = firstIndex;
CTabItem lastItem = items[lastIndex];
int w = lastItem.x + lastItem.width + 3;
- if (!simple && lastIndex == selectedIndex) w += curveWidth - 2*curveIndent;
- chevronRect.x = Math.min(w, getRightItemEdge());
+ if (!simple && lastIndex == selectedIndex) w -= renderer.curveIndent; //TODO: fix chevron position
+ chevronRect.x = Math.min(w, getRightItemEdge(gc));
chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2;
}
}
@@ -2850,11 +2265,16 @@ public void setInsertMark(int index, boolean after) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
}
-boolean setItemLocation() {
+boolean setItemLocation(GC gc) {
boolean changed = false;
if (items.length == 0) return false;
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+ int borderLeft = -trim.x;
+ int borderBottom = trim.height + trim.y;
+ int borderTop = -trim.y;
Point size = getSize();
int y = onBottom ? Math.max(borderBottom, size.y - borderBottom - tabHeight) : borderTop;
+ Point closeButtonSize = renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, 0, gc);
if (single) {
int defaultX = getDisplay().getBounds().width + 10; // off screen
for (int i = 0; i < items.length; i++) {
@@ -2866,8 +2286,8 @@ boolean setItemLocation() {
item.y = y;
item.showing = true;
if (showClose || item.showClose) {
- item.closeRect.x = borderLeft + CTabItem.LEFT_MARGIN;
- item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+ item.closeRect.x = borderLeft - renderer.computeTrim(i, SWT.NONE, 0, 0, 0, 0).x;
+ item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - closeButtonSize.y)/2: borderTop + (tabHeight - closeButtonSize.y)/2;
}
if (item.x != oldX || item.y != oldY) changed = true;
} else {
@@ -2876,14 +2296,13 @@ boolean setItemLocation() {
}
}
} else {
- int rightItemEdge = getRightItemEdge();
+ int rightItemEdge = getRightItemEdge(gc);
int maxWidth = rightItemEdge - borderLeft;
int width = 0;
for (int i = 0; i < priority.length; i++) {
CTabItem item = items[priority[i]];
width += item.width;
item.showing = i == 0 ? true : item.width > 0 && width <= maxWidth;
- if (!simple && priority[i] == selectedIndex) width += curveWidth - 2*curveIndent;
}
int x = 0;
int defaultX = getDisplay().getBounds().width + 10; // off screen
@@ -2898,40 +2317,35 @@ boolean setItemLocation() {
if (item.x != x || item.y != y) changed = true;
item.x = x;
item.y = y;
- if (i == selectedIndex) {
- int edge = Math.min(item.x + item.width, rightItemEdge);
- item.closeRect.x = edge - CTabItem.RIGHT_MARGIN - BUTTON_SIZE;
- } else {
- item.closeRect.x = item.x + item.width - CTabItem.RIGHT_MARGIN - BUTTON_SIZE;
- }
- item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+ int state = SWT.NONE;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ Rectangle edgeTrim = renderer.computeTrim(i, state, 0, 0, 0, 0);
+ item.closeRect.x = item.x + item.width - (edgeTrim.width + edgeTrim.x) - closeButtonSize.x;
+ item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - closeButtonSize.y)/2: borderTop + (tabHeight - closeButtonSize.y)/2;
x = x + item.width;
- if (!simple && i == selectedIndex) x += curveWidth - 2*curveIndent;
+ if (!simple && i == selectedIndex) x -= renderer.curveIndent; //TODO: fix next item position
}
}
}
return changed;
}
-boolean setItemSize() {
+boolean setItemSize(GC gc) {
boolean changed = false;
if (isDisposed()) return changed;
Point size = getSize();
if (size.x <= 0 || size.y <= 0) return changed;
- xClient = borderLeft + marginWidth + highlight_margin;
- if (onBottom) {
- yClient = borderTop + highlight_margin + marginHeight;
- } else {
- yClient = borderTop + tabHeight + highlight_header + marginHeight;
- }
+
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0);
+ int borderRight = trim.width + trim.x;
+ int borderLeft = -trim.x;
+
showChevron = false;
if (single) {
showChevron = true;
if (selectedIndex != -1) {
CTabItem tab = items[selectedIndex];
- GC gc = new GC(this);
- int width = tab.preferredWidth(gc, true, false);
- gc.dispose();
- width = Math.min(width, getRightItemEdge() - borderLeft);
+ int width = renderer.computeSize(selectedIndex, SWT.SELECTED, gc).x;
+ width = Math.min(width, getRightItemEdge(gc) - borderLeft);
if (tab.height != tabHeight || tab.width != width) {
changed = true;
tab.shortenedText = null;
@@ -2940,8 +2354,9 @@ boolean setItemSize() {
tab.width = width;
tab.closeRect.width = tab.closeRect.height = 0;
if (showClose || tab.showClose) {
- tab.closeRect.width = BUTTON_SIZE;
- tab.closeRect.height = BUTTON_SIZE;
+ Point closeSize = renderer.computeSize(selectedIndex, SWT.SELECTED, gc);
+ tab.closeRect.width = closeSize.x;
+ tab.closeRect.height = closeSize.y;
}
}
}
@@ -2951,30 +2366,30 @@ boolean setItemSize() {
if (items.length == 0) return changed;
int[] widths;
- GC gc = new GC(this);
int tabAreaWidth = size.x - borderLeft - borderRight - 3;
- if (showMin) tabAreaWidth -= BUTTON_SIZE;
- if (showMax) tabAreaWidth -= BUTTON_SIZE;
+ if (showMin) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc).x;
+ if (showMax) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc).x;
if (topRightAlignment == SWT.RIGHT && topRight != null) {
Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
tabAreaWidth -= rightSize.x + 3;
}
- if (!simple) tabAreaWidth -= curveWidth - 2*curveIndent;
tabAreaWidth = Math.max(0, tabAreaWidth);
-
+
// First, try the minimum tab size at full compression.
int minWidth = 0;
int[] minWidths = new int[items.length];
for (int i = 0; i < priority.length; i++) {
int index = priority[i];
- minWidths[index] = items[index].preferredWidth(gc, index == selectedIndex, true);
+ int state = CTabFolderRenderer.MINIMUM_SIZE;
+ if (index == selectedIndex) state |= SWT.SELECTED;
+ minWidths[index] = renderer.computeSize(index, state, gc).x;
minWidth += minWidths[index];
if (minWidth > tabAreaWidth) break;
}
if (minWidth > tabAreaWidth) {
// full compression required and a chevron
showChevron = items.length > 1;
- if (showChevron) tabAreaWidth -= 3*BUTTON_SIZE/2;
+ if (showChevron) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc).x;
widths = minWidths;
int index = selectedIndex != -1 ? selectedIndex : 0;
if (tabAreaWidth < widths[index]) {
@@ -2984,7 +2399,9 @@ boolean setItemSize() {
int maxWidth = 0;
int[] maxWidths = new int[items.length];
for (int i = 0; i < items.length; i++) {
- maxWidths[i] = items[i].preferredWidth(gc, i == selectedIndex, false);
+ int state = 0;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ maxWidths[i] = renderer.computeSize(i, state, gc).x;
maxWidth += maxWidths[i];
}
if (maxWidth <= tabAreaWidth) {
@@ -3016,7 +2433,6 @@ boolean setItemSize() {
}
}
}
- gc.dispose();
for (int i = 0; i < items.length; i++) {
CTabItem tab = items[i];
@@ -3030,8 +2446,9 @@ boolean setItemSize() {
tab.closeRect.width = tab.closeRect.height = 0;
if (showClose || tab.showClose) {
if (i == selectedIndex || showUnselectedClose) {
- tab.closeRect.width = BUTTON_SIZE;
- tab.closeRect.height = BUTTON_SIZE;
+ Point closeSize = renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, SWT.NONE, gc);
+ tab.closeRect.width = closeSize.x;
+ tab.closeRect.height = closeSize.y;
}
}
}
@@ -3202,6 +2619,16 @@ public void setMRUVisible(boolean show) {
if (updateItems()) redrawTabs();
}
}
+/*public*/ void setRenderer(CTabFolderRenderer renderer) {
+ checkWidget();
+ if (this.renderer != null) {
+ this.renderer.dispose();
+ }
+ if (renderer == null) {
+ renderer = new CTabFolderRenderer(this);
+ }
+ this.renderer = renderer;
+}
/**
* Set the selection to the tab at the specified item.
*
@@ -3244,9 +2671,9 @@ public void setSelection(int index) {
int oldIndex = selectedIndex;
selectedIndex = index;
if (oldIndex != -1) {
- items[oldIndex].closeImageState = NONE;
+ items[oldIndex].closeImageState = SWT.BACKGROUND;
}
- selection.closeImageState = NORMAL;
+ selection.closeImageState = SWT.NONE;
selection.showing = false;
Control newControl = selection.control;
@@ -3299,7 +2726,7 @@ public void setSelectionBackground (Color color) {
if (selectionBackground == color) return;
if (color == null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
selectionBackground = color;
- createAntialiasColors();
+ renderer.createAntialiasColors(); //TODO: need better caching strategy
if (selectedIndex > -1) redraw();
}
/**
@@ -3450,58 +2877,8 @@ public void setSelectionBackground(Color[] colors, int[] percents, boolean verti
* Set the color for the highlight start for selected tabs.
* Update the cache of highlight gradient colors if required.
*/
-
void setSelectionHighlightGradientColor(Color start) {
- //Set to null to match all the early return cases.
- //For early returns, don't realloc the cache, we may get a cache hit next time we're given the highlight
- selectionHighlightGradientBegin = null;
-
- if(start == null)
- return;
-
- //don't bother on low colour
- if (getDisplay().getDepth() < 15)
- return;
-
- //don't bother if we don't have a background gradient
- if(selectionGradientColors.length < 2)
- return;
-
- //OK we know its a valid gradient now
- selectionHighlightGradientBegin = start;
-
- if(! isSelectionHighlightColorsCacheHit(start))
- createSelectionHighlightGradientColors(start); //if no cache hit then compute new ones
-}
-
-/*
- * Return true if given start color, the cache of highlight colors we have
- * would match the highlight colors we'd compute.
- */
-boolean isSelectionHighlightColorsCacheHit(Color start) {
-
- if(selectionHighlightGradientColorsCache == null)
- return false;
-
- //this case should never happen but check to be safe before accessing array indexes
- if(selectionHighlightGradientColorsCache.length < 2)
- return false;
-
- Color highlightBegin = selectionHighlightGradientColorsCache[0];
- Color highlightEnd = selectionHighlightGradientColorsCache[selectionHighlightGradientColorsCache.length - 1];
-
- if(! highlightBegin.equals(start))
- return false;
-
- //Compare number of colours we have vs. we'd compute
- if(selectionHighlightGradientColorsCache.length != tabHeight)
- return false;
-
- //Compare existing highlight end to what it would be (selectionBackground)
- if(! highlightEnd.equals(selectionBackground))
- return false;
-
- return true;
+ renderer.setSelectionHighlightGradientColor(start); //TODO: need better caching strategy
}
/**
@@ -3522,10 +2899,10 @@ public void setSelectionBackground(Image image) {
if (image != null) {
selectionGradientColors = null;
selectionGradientPercents = null;
- disposeSelectionHighlightGradientColors();
+ renderer.disposeSelectionHighlightGradientColors(); //TODO: need better caching strategy
}
selectionBgImage = image;
- createAntialiasColors();
+ renderer.createAntialiasColors(); //TODO: need better caching strategy
if (selectedIndex > -1) redraw();
}
/**
@@ -3546,59 +2923,6 @@ public void setSelectionForeground (Color color) {
if (selectedIndex > -1) redraw();
}
-/*
- * Allocate colors for the highlight line.
- * Colours will be a gradual blend ranging from to.
- * Blend length will be tab height.
- * Recompute this if tab height changes.
- * Could remain null if there'd be no gradient (start=end or low colour display)
- */
-void createSelectionHighlightGradientColors(Color start) {
- disposeSelectionHighlightGradientColors(); //dispose if existing
-
- if(start == null) //shouldn't happen but just to be safe
- return;
-
- //alloc colours for entire height to ensure it matches wherever we stop drawing
- int fadeGradientSize = tabHeight;
-
- RGB from = start.getRGB();
- RGB to = selectionBackground.getRGB();
-
- selectionHighlightGradientColorsCache = new Color[fadeGradientSize];
- int denom = fadeGradientSize - 1;
-
- for (int i = 0; i < fadeGradientSize; i++) {
- int propFrom = denom - i;
- int propTo = i;
- int red = (to.red * propTo + from.red * propFrom) / denom;
- int green = (to.green * propTo + from.green * propFrom) / denom;
- int blue = (to.blue * propTo + from.blue * propFrom) / denom;
- selectionHighlightGradientColorsCache[i] = new Color(getDisplay(), red, green, blue);
- }
-}
-
-void disposeSelectionHighlightGradientColors() {
- if(selectionHighlightGradientColorsCache == null)
- return;
- for (int i = 0; i < selectionHighlightGradientColorsCache.length; i++) {
- selectionHighlightGradientColorsCache[i].dispose();
- }
- selectionHighlightGradientColorsCache = null;
-}
-
-/*
- * Return the gradient start color for selected tabs, which is the start of the tab fade
- * (end is selectionBackground).
- */
-Color getSelectionBackgroundGradientBegin() {
- if (selectionGradientColors == null)
- return getSelectionBackground();
- if (selectionGradientColors.length == 0)
- return getSelectionBackground();
- return selectionGradientColors[0];
-}
-
/**
* Sets the shape that the CTabFolder will use to render itself.
*
@@ -3642,8 +2966,8 @@ public void setSingle(boolean single) {
this.single = single;
if (!single) {
for (int i = 0; i < items.length; i++) {
- if (i != selectedIndex && items[i].closeImageState == NORMAL) {
- items[i].closeImageState = NONE;
+ if (i != selectedIndex && items[i].closeImageState == SWT.NONE) {
+ items[i].closeImageState = SWT.BACKGROUND;
}
}
}
@@ -3698,8 +3022,6 @@ public void setTabPosition(int position) {
}
if (onBottom != (position == SWT.BOTTOM)) {
onBottom = position == SWT.BOTTOM;
- borderTop = onBottom ? borderLeft : 0;
- borderBottom = onBottom ? 0 : borderRight;
updateTabHeight(true);
Rectangle rectBefore = getClientArea();
updateItems();
@@ -3917,24 +3239,29 @@ boolean updateItems() {
}
boolean updateItems(int showIndex) {
+ GC gc = new GC(this);
if (!single && !mru && showIndex != -1) {
// make sure selected item will be showing
int firstIndex = showIndex;
if (priority[0] < showIndex) {
- int maxWidth = getRightItemEdge() - borderLeft;
- if (!simple) maxWidth -= curveWidth - 2*curveIndent;
+ Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0);
+ int borderLeft = -trim.x;
+ int maxWidth = getRightItemEdge(gc) - borderLeft;
int width = 0;
int[] widths = new int[items.length];
- GC gc = new GC(this);
for (int i = priority[0]; i <= showIndex; i++) {
- widths[i] = items[i].preferredWidth(gc, i == selectedIndex, true);
+ int state = CTabFolderRenderer.MINIMUM_SIZE;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ widths[i] = renderer.computeSize(i, state, gc).x;
width += widths[i];
if (width > maxWidth) break;
}
if (width > maxWidth) {
width = 0;
for (int i = showIndex; i >= 0; i--) {
- if (widths[i] == 0) widths[i] = items[i].preferredWidth(gc, i == selectedIndex, true);
+ int state = CTabFolderRenderer.MINIMUM_SIZE;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc).x;
width += widths[i];
if (width > maxWidth) break;
firstIndex = i;
@@ -3942,20 +3269,24 @@ boolean updateItems(int showIndex) {
} else {
firstIndex = priority[0];
for (int i = showIndex + 1; i < items.length; i++) {
- widths[i] = items[i].preferredWidth(gc, i == selectedIndex, true);
+ int state = CTabFolderRenderer.MINIMUM_SIZE;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ widths[i] = renderer.computeSize(i, state, gc).x;
width += widths[i];
if (width >= maxWidth) break;
}
if (width < maxWidth) {
for (int i = priority[0] - 1; i >= 0; i--) {
- if (widths[i] == 0) widths[i] = items[i].preferredWidth(gc, i == selectedIndex, true);
+ int state = CTabFolderRenderer.MINIMUM_SIZE;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc).x;
width += widths[i];
if (width > maxWidth) break;
firstIndex = i;
}
}
}
- gc.dispose();
+
}
if (firstIndex != priority[0]) {
int index = 0;
@@ -3969,72 +3300,25 @@ boolean updateItems(int showIndex) {
}
boolean oldShowChevron = showChevron;
- boolean changed = setItemSize();
- changed |= setItemLocation();
- setButtonBounds();
+ boolean changed = setItemSize(gc);
+ changed |= setItemLocation(gc);
+ setButtonBounds(gc);
changed |= showChevron != oldShowChevron;
if (changed && getToolTipText() != null) {
Point pt = getDisplay().getCursorLocation();
pt = toControl(pt);
_setToolTipText(pt.x, pt.y);
}
+ gc.dispose();
return changed;
}
boolean updateTabHeight(boolean force){
- int style = getStyle();
- if (fixedTabHeight == 0 && (style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) highlight_header = 0;
int oldHeight = tabHeight;
- if (fixedTabHeight != SWT.DEFAULT) {
- tabHeight = fixedTabHeight == 0 ? 0 : fixedTabHeight + 1; // +1 for line drawn across top of tab
- } else {
- int tempHeight = 0;
- GC gc = new GC(this);
- if (items.length == 0) {
- tempHeight = gc.textExtent("Default", CTabItem.FLAGS).y + CTabItem.TOP_MARGIN + CTabItem.BOTTOM_MARGIN; //$NON-NLS-1$
- } else {
- for (int i=0; i < items.length; i++) {
- tempHeight = Math.max(tempHeight, items[i].preferredHeight(gc));
- }
- }
- gc.dispose();
- tabHeight = tempHeight;
- }
+ GC gc = new GC(this);
+ tabHeight = renderer.computeSize(CTabFolderRenderer.PART_HEADER, SWT.NONE, gc).y;
+ gc.dispose();
if (!force && tabHeight == oldHeight) return false;
-
oldSize = null;
- if (onBottom) {
- int d = tabHeight - 12;
- curve = new int[]{0,13+d, 0,12+d, 2,12+d, 3,11+d, 5,11+d, 6,10+d, 7,10+d, 9,8+d, 10,8+d,
- 11,7+d, 11+d,7,
- 12+d,6, 13+d,6, 15+d,4, 16+d,4, 17+d,3, 19+d,3, 20+d,2, 22+d,2, 23+d,1};
- curveWidth = 26+d;
- curveIndent = curveWidth/3;
- } else {
- int d = tabHeight - 12;
- curve = new int[]{0,0, 0,1, 2,1, 3,2, 5,2, 6,3, 7,3, 9,5, 10,5,
- 11,6, 11+d,6+d,
- 12+d,7+d, 13+d,7+d, 15+d,9+d, 16+d,9+d, 17+d,10+d, 19+d,10+d, 20+d,11+d, 22+d,11+d, 23+d,12+d};
- curveWidth = 26+d;
- curveIndent = curveWidth/3;
-
- //this could be static but since values depend on curve, better to keep in one place
- topCurveHighlightStart = new int[] {
- 0, 2, 1, 2, 2, 2,
- 3, 3, 4, 3, 5, 3,
- 6, 4, 7, 4,
- 8, 5,
- 9, 6, 10, 6};
-
- //also, by adding in 'd' here we save some math cost when drawing the curve
- topCurveHighlightEnd = new int[] {
- 10+d, 6+d,
- 11+d, 7+d,
- 12+d, 8+d, 13+d, 8+d,
- 14+d, 9+d,
- 15+d, 10+d, 16+d, 10+d,
- 17+d, 11+d, 18+d, 11+d, 19+d, 11+d,
- 20+d, 12+d, 21+d, 12+d, 22+d, 12+d };
- }
notifyListeners(SWT.Resize, new Event());
return true;
}
@@ -4050,52 +3334,4 @@ String _getToolTip(int x, int y) {
}
return item.getToolTipText();
}
-void createAntialiasColors() {
- disposeAntialiasColors();
- lastBorderColor = getDisplay().getSystemColor(BORDER1_COLOR);
- RGB lineRGB = lastBorderColor.getRGB();
- /* compute the selected color */
- RGB innerRGB = selectionBackground.getRGB();
- if (selectionBgImage != null ||
- (selectionGradientColors != null && selectionGradientColors.length > 1)) {
- innerRGB = null;
- }
- RGB outerRGB = getBackground().getRGB();
- if (gradientColors != null && gradientColors.length > 1) {
- outerRGB = null;
- }
- if (outerRGB != null) {
- RGB from = lineRGB;
- RGB to = outerRGB;
- int red = from.red + 2*(to.red - from.red)/3;
- int green = from.green + 2*(to.green - from.green)/3;
- int blue = from.blue + 2*(to.blue - from.blue)/3;
- selectedOuterColor = new Color(getDisplay(), red, green, blue);
- }
- if (innerRGB != null) {
- RGB from = lineRGB;
- RGB to = innerRGB;
- int red = from.red + 2*(to.red - from.red)/3;
- int green = from.green + 2*(to.green - from.green)/3;
- int blue = from.blue + 2*(to.blue - from.blue)/3;
- selectedInnerColor = new Color(getDisplay(), red, green, blue);
- }
- /* compute the tabArea color */
- outerRGB = getParent().getBackground().getRGB();
- if (outerRGB != null) {
- RGB from = lineRGB;
- RGB to = outerRGB;
- int red = from.red + 2*(to.red - from.red)/3;
- int green = from.green + 2*(to.green - from.green)/3;
- int blue = from.blue + 2*(to.blue - from.blue)/3;
- tabAreaColor = new Color(getDisplay(), red, green, blue);
- }
-}
-
-void disposeAntialiasColors() {
- if (tabAreaColor != null) tabAreaColor.dispose();
- if (selectedInnerColor != null) selectedInnerColor.dispose();
- if (selectedOuterColor != null) selectedOuterColor.dispose();
- tabAreaColor = selectedInnerColor = selectedOuterColor = null;
-}
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java
index e01fac6e55..2bba73a552 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java
@@ -23,26 +23,32 @@ class CTabFolderLayout extends Layout {
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
CTabFolder folder = (CTabFolder)composite;
CTabItem[] items = folder.items;
+ CTabFolderRenderer renderer = folder.renderer;
// preferred width of tab area to show all tabs
int tabW = 0;
+ int selectedIndex = folder.selectedIndex;
+ if (selectedIndex == -1) selectedIndex = 0;
GC gc = new GC(folder);
for (int i = 0; i < items.length; i++) {
if (folder.single) {
- tabW = Math.max(tabW, items[i].preferredWidth(gc, true, false));
+ tabW = Math.max(tabW, renderer.computeSize(i, SWT.SELECTED, gc).x);
} else {
- tabW += items[i].preferredWidth(gc, i == folder.selectedIndex, false);
+ int state = 0;
+ if (i == selectedIndex) state |= SWT.SELECTED;
+ tabW += renderer.computeSize(i, state, gc).x;
}
}
- gc.dispose();
tabW += 3;
- if (folder.showMax) tabW += CTabFolder.BUTTON_SIZE;
- if (folder.showMin) tabW += CTabFolder.BUTTON_SIZE;
- if (folder.single) tabW += 3*CTabFolder.BUTTON_SIZE/2; //chevron
+
+ if (folder.showMax) tabW += renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc).x;
+ if (folder.showMin) tabW += renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc).x;
+ if (folder.single) tabW += renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc).x;
if (folder.topRight != null) {
Point pt = folder.topRight.computeSize(SWT.DEFAULT, folder.tabHeight, flushCache);
tabW += 3 + pt.x;
}
- if (!folder.single && !folder.simple) tabW += folder.curveWidth - 2*folder.curveIndent;
+
+ gc.dispose();
int controlW = 0;
int controlH = 0;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderRenderer.java
new file mode 100644
index 0000000000..61d54b0600
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderRenderer.java
@@ -0,0 +1,1618 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/*public*/ class CTabFolderRenderer {
+
+ protected CTabFolder parent;
+
+ // borders and shapes
+ int highlight_margin = 0;
+ int highlight_header = 0;
+
+ int[] curve;
+ int[] topCurveHighlightStart;
+ int[] topCurveHighlightEnd;
+ int curveWidth = 0;
+ int curveIndent = 0;
+ int lastTabHeight = -1;
+
+ Color fillColor;
+ /* Selected item appearance */
+ Color selectionHighlightGradientBegin = null; //null == no highlight
+ //Although we are given new colours all the time to show different states (active, etc),
+ //some of which may have a highlight and some not, we'd like to retain the highlight colours
+ //as a cache so that we can reuse them if we're again told to show the highlight.
+ //We are relying on the fact that only one tab state usually gets a highlight, so only
+ //a single cache is required. If that happens to not be true, cache simply becomes less effective,
+ //but we don't leak colours.
+ Color[] selectionHighlightGradientColorsCache = null; //null is a legal value, check on access
+ /* Colors for anti-aliasing */
+ Color selectedOuterColor = null;
+ Color selectedInnerColor = null;
+ Color tabAreaColor = null;
+ /*
+ * Border color that was used in computing the cached anti-alias Colors.
+ * We have to recompute the colors if the border color changes
+ */
+ Color lastBorderColor = null;
+
+ //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom)
+ //so can fade in same direction as right swoop curve
+ static final int[] TOP_LEFT_CORNER_HILITE = new int[] {5,2, 4,2, 3,3, 2,4, 2,5, 1,6};
+
+ static final int[] TOP_LEFT_CORNER = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
+ static final int[] TOP_RIGHT_CORNER = new int[] {-6,0, -5,1, -4,1, -1,4, -1,5, 0,6};
+ static final int[] BOTTOM_LEFT_CORNER = new int[] {0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0};
+ static final int[] BOTTOM_RIGHT_CORNER = new int[] {-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6};
+
+ static final int[] SIMPLE_TOP_LEFT_CORNER = new int[] {0,2, 1,1, 2,0};
+ static final int[] SIMPLE_TOP_RIGHT_CORNER = new int[] {-2,0, -1,1, 0,2};
+ static final int[] SIMPLE_BOTTOM_LEFT_CORNER = new int[] {0,-2, 1,-1, 2,0};
+ static final int[] SIMPLE_BOTTOM_RIGHT_CORNER = new int[] {-2,0, -1,-1, 0,-2};
+ static final int[] SIMPLE_UNSELECTED_INNER_CORNER = new int[] {0,0};
+
+ static final int[] TOP_LEFT_CORNER_BORDERLESS = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
+ static final int[] TOP_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -6,1, -5,1, -2,4, -2,5, -1,6};
+ static final int[] BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0};
+ static final int[] BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6};
+
+ static final int[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = new int[] {0,2, 1,1, 2,0};
+ static final int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= new int[] {-3,0, -2,1, -1,2};
+ static final int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-3, 1,-2, 2,-1, 3,0};
+ static final int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-4,0, -3,-1, -2,-2, -1,-3};
+
+ static final RGB CLOSE_FILL = new RGB(252, 160, 160);
+
+ static final int BUTTON_SIZE = 18;
+
+ static final int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW;
+ static final int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND;
+ static final int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+
+ static final int ITEM_TOP_MARGIN = 2;
+ static final int ITEM_BOTTOM_MARGIN = 2;
+ static final int ITEM_LEFT_MARGIN = 4;
+ static final int ITEM_RIGHT_MARGIN = 4;
+ static final int INTERNAL_SPACING = 4;
+ static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC;
+ static final String ELLIPSIS = "..."; //$NON-NLS-1$
+
+ //Part constants
+ public static final int PART_BODY = -1;
+ public static final int PART_HEADER = -2;
+ public static final int PART_BORDER = -3;
+ public static final int PART_MAX_BUTTON = -4;
+ public static final int PART_MIN_BUTTON = -5;
+ public static final int PART_CHEVRON_BUTTON = -6;
+ public static final int PART_CLOSE_BUTTON = -7;
+
+ public static final int MINIMUM_SIZE = 1 << 24; //TODO: Should this be a state?
+
+ protected CTabFolderRenderer(CTabFolder parent) {
+ this.parent = parent;
+ int style = parent.getStyle();
+ highlight_header = (style & SWT.FLAT) != 0 ? 1 : 3;
+ highlight_margin = (style & SWT.FLAT) != 0 ? 0 : 2;
+ }
+
+ void antialias (int[] shape, Color innerColor, Color outerColor, GC gc){
+ // Don't perform anti-aliasing on Mac and WPF because the platform
+ // already does it. The simple style also does not require anti-aliasing.
+ if (parent.simple) return;
+ String platform = SWT.getPlatform();
+ if ("cocoa".equals(platform)) return; //$NON-NLS-1$
+ if ("carbon".equals(platform)) return; //$NON-NLS-1$
+ if ("wpf".equals(platform)) return; //$NON-NLS-1$
+ // Don't perform anti-aliasing on low resolution displays
+ if (parent.getDisplay().getDepth() < 15) return;
+ if (outerColor != null) {
+ int index = 0;
+ boolean left = true;
+ int oldY = parent.onBottom ? 0 : parent.getSize().y;
+ int[] outer = new int[shape.length];
+ for (int i = 0; i < shape.length/2; i++) {
+ if (left && (index + 3 < shape.length)) {
+ left = parent.onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+ oldY = shape[index+1];
+ }
+ outer[index] = shape[index++] + (left ? -1 : +1);
+ outer[index] = shape[index++];
+ }
+ gc.setForeground(outerColor);
+ gc.drawPolyline(outer);
+ }
+ if (innerColor != null) {
+ int[] inner = new int[shape.length];
+ int index = 0;
+ boolean left = true;
+ int oldY = parent.onBottom ? 0 : parent.getSize().y;
+ for (int i = 0; i < shape.length/2; i++) {
+ if (left && (index + 3 < shape.length)) {
+ left = parent.onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+ oldY = shape[index+1];
+ }
+ inner[index] = shape[index++] + (left ? +1 : -1);
+ inner[index] = shape[index++];
+ }
+ gc.setForeground(innerColor);
+ gc.drawPolyline(inner);
+ }
+ }
+
+ protected Point computeSize (int part, int state, GC gc) {
+ int width = 0, height = 0;
+ switch (part) {
+ case PART_HEADER:
+ if (parent.fixedTabHeight != SWT.DEFAULT) {
+ height = parent.fixedTabHeight == 0 ? 0 : parent.fixedTabHeight + 1; // +1 for line drawn across top of tab
+ } else {
+ CTabItem[] items = parent.items;
+ if (items.length == 0) {
+ height = gc.textExtent("Default", FLAGS).y + ITEM_TOP_MARGIN + ITEM_BOTTOM_MARGIN; //$NON-NLS-1$
+ } else {
+ for (int i=0; i < items.length; i++) {
+ height = Math.max(height, computeSize(i, SWT.NONE, gc).y);
+ }
+ }
+ gc.dispose();
+ }
+ break;
+ case PART_MAX_BUTTON:
+ case PART_MIN_BUTTON:
+ case PART_CLOSE_BUTTON:
+ width = height = BUTTON_SIZE;
+ break;
+ case PART_CHEVRON_BUTTON:
+ width = 3*BUTTON_SIZE/2;
+ height = BUTTON_SIZE;
+ break;
+ default:
+ if (0 <= part && part < parent.getItemCount()) {
+ updateCurves();
+ CTabItem item = parent.items[part];
+ if (item.isDisposed()) return new Point(0,0);
+ Image image = item.getImage();
+ if (image != null) {
+ Rectangle bounds = image.getBounds();
+ if ((state & SWT.SELECTED) != 0 || parent.showUnselectedImage) {
+ width += bounds.width;
+ }
+ height = bounds.height;
+ }
+ String text = null;
+ if ((state & MINIMUM_SIZE) != 0) {
+ int minChars = parent.minChars;
+ text = minChars == 0 ? null : item.getText();
+ if (text != null && text.length() > minChars) {
+ if (useEllipses()) {
+ int end = minChars < ELLIPSIS.length() + 1 ? minChars : minChars - ELLIPSIS.length();
+ text = text.substring(0, end);
+ if (minChars > ELLIPSIS.length() + 1) text += ELLIPSIS;
+ } else {
+ int end = minChars;
+ text = text.substring(0, end);
+ }
+ }
+ } else {
+ text = item.getText();
+ }
+ if (text != null) {
+ if (width > 0) width += INTERNAL_SPACING;
+ if (item.font == null) {
+ Point size = gc.textExtent(text, FLAGS);
+ width += size.x;
+ height = Math.max(height, size.y);
+ } else {
+ Font gcFont = gc.getFont();
+ gc.setFont(item.font);
+ Point size = gc.textExtent(text, FLAGS);
+ width += size.x;
+ height = Math.max(height, size.y);
+ gc.setFont(gcFont);
+ }
+ }
+ if (parent.showClose || item.showClose) {
+ if ((state & SWT.SELECTED) != 0 || parent.showUnselectedClose) {
+ if (width > 0) width += INTERNAL_SPACING;
+ width += computeSize(PART_CLOSE_BUTTON, SWT.NONE, gc).x;
+ }
+ }
+ }
+ break;
+ }
+ Rectangle trim = computeTrim(part, state, 0, 0, width, height);
+ width = trim.width;
+ height = trim.height;
+ return new Point(width, height);
+ }
+
+ protected Rectangle computeTrim (int part, int state, int x, int y, int width, int height) {
+ int borderLeft = parent.borderVisible ? 1 : 0;
+ int borderRight = borderLeft;
+ int borderTop = parent.onBottom ? borderLeft : 0;
+ int borderBottom = parent.onBottom ? 0 : borderLeft;
+ int tabHeight = parent.tabHeight;
+ switch (part) {
+ case PART_BODY:
+ int highlight_header = this.highlight_header;
+ int style = parent.getStyle();
+ if (parent.fixedTabHeight == 0 && (style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) {
+ highlight_header = 0;
+ }
+ int marginWidth = parent.marginWidth;
+ int marginHeight = parent.marginHeight;
+ x = x - marginWidth - highlight_margin - borderLeft;
+ width = width + borderLeft + borderRight + 2*marginWidth + 2*highlight_margin;
+ if (parent.minimized) {
+ y = parent.onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop;
+ height = borderTop + borderBottom + tabHeight + highlight_header;
+ } else {
+ y = parent.onBottom ? y - marginHeight - highlight_margin - borderTop: y - marginHeight - highlight_header - tabHeight - borderTop;
+ height = height + borderTop + borderBottom + 2*marginHeight + tabHeight + highlight_header + highlight_margin;
+ }
+ break;
+ case PART_HEADER:
+ x = x - borderLeft;
+ width = width + borderLeft + borderRight;
+ break;
+ case PART_BORDER:
+ x = x - borderLeft;
+ width = width + borderLeft + borderRight;
+ y = y - borderTop;
+ height = height + borderTop + borderBottom;
+ break;
+ default:
+ if (0 <= part && part < parent.getItemCount()) {
+ updateCurves();
+ x = x - ITEM_LEFT_MARGIN;
+ width = width + ITEM_LEFT_MARGIN + ITEM_RIGHT_MARGIN;
+ if (!parent.simple && !parent.single && (state & SWT.SELECTED) != 0) {
+ width += curveWidth - curveIndent;
+ }
+ y = y - ITEM_TOP_MARGIN;
+ height = height + ITEM_TOP_MARGIN + ITEM_BOTTOM_MARGIN;
+ }
+ break;
+ }
+ return new Rectangle(x, y, width, height);
+ }
+
+ void createAntialiasColors() {
+ disposeAntialiasColors();
+ lastBorderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+ RGB lineRGB = lastBorderColor.getRGB();
+ /* compute the selected color */
+ RGB innerRGB = parent.selectionBackground.getRGB();
+ if (parent.selectionBgImage != null ||
+ (parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1)) {
+ innerRGB = null;
+ }
+ RGB outerRGB = parent.getBackground().getRGB();
+ if (parent.gradientColors != null && parent.gradientColors.length > 1) {
+ outerRGB = null;
+ }
+ if (outerRGB != null) {
+ RGB from = lineRGB;
+ RGB to = outerRGB;
+ int red = from.red + 2*(to.red - from.red)/3;
+ int green = from.green + 2*(to.green - from.green)/3;
+ int blue = from.blue + 2*(to.blue - from.blue)/3;
+ selectedOuterColor = new Color(parent.getDisplay(), red, green, blue);
+ }
+ if (innerRGB != null) {
+ RGB from = lineRGB;
+ RGB to = innerRGB;
+ int red = from.red + 2*(to.red - from.red)/3;
+ int green = from.green + 2*(to.green - from.green)/3;
+ int blue = from.blue + 2*(to.blue - from.blue)/3;
+ selectedInnerColor = new Color(parent.getDisplay(), red, green, blue);
+ }
+ /* compute the tabArea color */
+ outerRGB = parent.getParent().getBackground().getRGB();
+ if (outerRGB != null) {
+ RGB from = lineRGB;
+ RGB to = outerRGB;
+ int red = from.red + 2*(to.red - from.red)/3;
+ int green = from.green + 2*(to.green - from.green)/3;
+ int blue = from.blue + 2*(to.blue - from.blue)/3;
+ tabAreaColor = new Color(parent.getDisplay(), red, green, blue);
+ }
+ }
+
+ /*
+ * Allocate colors for the highlight line.
+ * Colours will be a gradual blend ranging from to.
+ * Blend length will be tab height.
+ * Recompute this if tab height changes.
+ * Could remain null if there'd be no gradient (start=end or low colour display)
+ */
+ void createSelectionHighlightGradientColors(Color start) {
+ disposeSelectionHighlightGradientColors(); //dispose if existing
+
+ if(start == null) //shouldn't happen but just to be safe
+ return;
+
+ //alloc colours for entire height to ensure it matches wherever we stop drawing
+ int fadeGradientSize = parent.tabHeight;
+
+ RGB from = start.getRGB();
+ RGB to = parent.selectionBackground.getRGB();
+
+ selectionHighlightGradientColorsCache = new Color[fadeGradientSize];
+ int denom = fadeGradientSize - 1;
+
+ for (int i = 0; i < fadeGradientSize; i++) {
+ int propFrom = denom - i;
+ int propTo = i;
+ int red = (to.red * propTo + from.red * propFrom) / denom;
+ int green = (to.green * propTo + from.green * propFrom) / denom;
+ int blue = (to.blue * propTo + from.blue * propFrom) / denom;
+ selectionHighlightGradientColorsCache[i] = new Color(parent.getDisplay(), red, green, blue);
+ }
+ }
+
+ protected void dispose() {
+ disposeAntialiasColors();
+ disposeSelectionHighlightGradientColors();
+ if (fillColor != null) {
+ fillColor.dispose();
+ fillColor = null;
+ }
+ }
+
+ void disposeAntialiasColors() {
+ if (tabAreaColor != null) tabAreaColor.dispose();
+ if (selectedInnerColor != null) selectedInnerColor.dispose();
+ if (selectedOuterColor != null) selectedOuterColor.dispose();
+ tabAreaColor = selectedInnerColor = selectedOuterColor = null;
+ }
+
+ void disposeSelectionHighlightGradientColors() {
+ if(selectionHighlightGradientColorsCache == null)
+ return;
+ for (int i = 0; i < selectionHighlightGradientColorsCache.length; i++) {
+ selectionHighlightGradientColorsCache[i].dispose();
+ }
+ selectionHighlightGradientColorsCache = null;
+ }
+
+ protected void draw (int part, int state, Rectangle bounds, GC gc) {
+ switch (part) {
+ case PART_BODY:
+ drawBody(gc, bounds, state);
+ break;
+ case PART_HEADER:
+ drawTabArea(gc, bounds, state);
+ break;
+ case PART_MAX_BUTTON:
+ drawMaximize(gc, bounds, state);
+ break;
+ case PART_MIN_BUTTON:
+ drawMinimize(gc, bounds, state);
+ break;
+ case PART_CHEVRON_BUTTON:
+ drawChevron(gc, bounds, state);
+ break;
+ default:
+ if (0 <= part && part < parent.getItemCount()) {
+ if (bounds.width == 0 || bounds.height == 0) return;
+ if ((state & SWT.SELECTED) != 0 ) {
+ drawSelected(part, gc, bounds, state);
+ } else {
+ drawUnselected(part, gc, bounds, state);
+ }
+ }
+ break;
+ }
+ }
+
+ void drawBackground(GC gc, int[] shape, boolean selected) {
+ Color defaultBackground = selected ? parent.selectionBackground : parent.getBackground();
+ Image image = selected ? parent.selectionBgImage : null;
+ Color[] colors = selected ? parent.selectionGradientColors : parent.gradientColors;
+ int[] percents = selected ? parent.selectionGradientPercents : parent.gradientPercents;
+ boolean vertical = selected ? parent.selectionGradientVertical : parent.gradientVertical;
+ Point size = parent.getSize();
+ int width = size.x;
+ int height = parent.tabHeight + highlight_header;
+ int x = 0;
+
+ int borderLeft = parent.borderVisible ? 1 : 0;
+ int borderTop = parent.onBottom ? borderLeft : 0;
+ int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+ if (borderLeft > 0) {
+ x += 1; width -= 2;
+ }
+ int y = parent.onBottom ? size.y - borderBottom - height : borderTop;
+ drawBackground(gc, shape, x, y, width, height, defaultBackground, image, colors, percents, vertical);
+ }
+
+ void drawBackground(GC gc, int[] shape, int x, int y, int width, int height, Color defaultBackground, Image image, Color[] colors, int[] percents, boolean vertical) {
+ Region clipping = new Region();
+ gc.getClipping(clipping);
+ Region region = new Region();
+ region.add(shape);
+ region.intersect(clipping);
+ gc.setClipping(region);
+
+ if (image != null) {
+ // draw the background image in shape
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x, y, width, height);
+ Rectangle imageRect = image.getBounds();
+ gc.drawImage(image, imageRect.x, imageRect.y, imageRect.width, imageRect.height, x, y, width, height);
+ } else if (colors != null) {
+ // draw gradient
+ if (colors.length == 1) {
+ Color background = colors[0] != null ? colors[0] : defaultBackground;
+ gc.setBackground(background);
+ gc.fillRectangle(x, y, width, height);
+ } else {
+ if (vertical) {
+ if (parent.onBottom) {
+ int pos = 0;
+ if (percents[percents.length - 1] < 100) {
+ pos = (100 - percents[percents.length - 1]) * height / 100;
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x, y, width, pos);
+ }
+ Color lastColor = colors[colors.length-1];
+ if (lastColor == null) lastColor = defaultBackground;
+ for (int i = percents.length-1; i >= 0; i--) {
+ gc.setForeground(lastColor);
+ lastColor = colors[i];
+ if (lastColor == null) lastColor = defaultBackground;
+ gc.setBackground(lastColor);
+ int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
+ int gradientHeight = percentage * height / 100;
+ gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
+ pos += gradientHeight;
+ }
+ } else {
+ Color lastColor = colors[0];
+ if (lastColor == null) lastColor = defaultBackground;
+ int pos = 0;
+ for (int i = 0; i < percents.length; i++) {
+ gc.setForeground(lastColor);
+ lastColor = colors[i + 1];
+ if (lastColor == null) lastColor = defaultBackground;
+ gc.setBackground(lastColor);
+ int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
+ int gradientHeight = percentage * height / 100;
+ gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
+ pos += gradientHeight;
+ }
+ if (pos < height) {
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x, pos, width, height-pos+1);
+ }
+ }
+ } else { //horizontal gradient
+ y = 0;
+ height = parent.getSize().y;
+ Color lastColor = colors[0];
+ if (lastColor == null) lastColor = defaultBackground;
+ int pos = 0;
+ for (int i = 0; i < percents.length; ++i) {
+ gc.setForeground(lastColor);
+ lastColor = colors[i + 1];
+ if (lastColor == null) lastColor = defaultBackground;
+ gc.setBackground(lastColor);
+ int gradientWidth = (percents[i] * width / 100) - pos;
+ gc.fillGradientRectangle(x+pos, y, gradientWidth, height, false);
+ pos += gradientWidth;
+ }
+ if (pos < width) {
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x+pos, y, width-pos, height);
+ }
+ }
+ }
+ } else {
+ // draw a solid background using default background in shape
+ if ((parent.getStyle() & SWT.NO_BACKGROUND) != 0 || !defaultBackground.equals(parent.getBackground())) {
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x, y, width, height);
+ }
+ }
+ gc.setClipping(clipping);
+ clipping.dispose();
+ region.dispose();
+ }
+
+ /*
+ * Draw the border of the tab
+ *
+ * @param gc
+ * @param shape
+ */
+ void drawBorder(GC gc, int[] shape) {
+
+ gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+ gc.drawPolyline(shape);
+ }
+
+ void drawBody(GC gc, Rectangle bounds, int state) {
+ Point size = new Point(bounds.width, bounds.height);
+ int selectedIndex = parent.selectedIndex;
+ int tabHeight = parent.tabHeight;
+
+ int borderLeft = parent.borderVisible ? 1 : 0;
+ int borderRight = borderLeft;
+ int borderTop = parent.onBottom ? borderLeft : 0;
+ int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+ // fill in body
+ if (!parent.minimized){
+ int width = size.x - borderLeft - borderRight - 2*highlight_margin;
+ int height = size.y - borderTop - borderBottom - tabHeight - highlight_header - highlight_margin;
+ // Draw highlight margin
+ if (highlight_margin > 0) {
+ int[] shape = null;
+ if (parent.onBottom) {
+ int x1 = borderLeft;
+ int y1 = borderTop;
+ int x2 = size.x - borderRight;
+ int y2 = size.y - borderBottom - tabHeight - highlight_header;
+ shape = new int[] {x1,y1, x2,y1, x2,y2, x2-highlight_margin,y2,
+ x2-highlight_margin, y1+highlight_margin, x1+highlight_margin,y1+highlight_margin,
+ x1+highlight_margin,y2, x1,y2};
+ } else {
+ int x1 = borderLeft;
+ int y1 = borderTop + tabHeight + highlight_header;
+ int x2 = size.x - borderRight;
+ int y2 = size.y - borderBottom;
+ shape = new int[] {x1,y1, x1+highlight_margin,y1, x1+highlight_margin,y2-highlight_margin,
+ x2-highlight_margin,y2-highlight_margin, x2-highlight_margin,y1,
+ x2,y1, x2,y2, x1,y2};
+ }
+ // If horizontal gradient, show gradient across the whole area
+ if (selectedIndex != -1 && parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1 && !parent.selectionGradientVertical) {
+ drawBackground(gc, shape, true);
+ } else if (selectedIndex == -1 && parent.gradientColors != null && parent.gradientColors.length > 1 && !parent.gradientVertical) {
+ drawBackground(gc, shape, false);
+ } else {
+ gc.setBackground(selectedIndex == -1 ? parent.getBackground() : parent.selectionBackground);
+ gc.fillPolygon(shape);
+ }
+ }
+ //Draw client area
+ if ((parent.getStyle() & SWT.NO_BACKGROUND) != 0) {
+ gc.setBackground(parent.getBackground());
+ int marginWidth = parent.marginWidth;
+ int marginHeight = parent.marginHeight;
+ int xClient = borderLeft + marginWidth + highlight_margin, yClient;
+ if (parent.onBottom) {
+ yClient = borderTop + highlight_margin + marginHeight;
+ } else {
+ yClient = borderTop + tabHeight + highlight_header + marginHeight;
+ }
+ gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, width, height);
+ }
+ } else {
+ if ((parent.getStyle() & SWT.NO_BACKGROUND) != 0) {
+ int height = borderTop + tabHeight + highlight_header + borderBottom;
+ if (size.y > height) {
+ gc.setBackground(parent.getParent().getBackground());
+ gc.fillRectangle(0, height, size.x, size.y - height);
+ }
+ }
+ }
+
+ //draw 1 pixel border around outside
+ if (borderLeft > 0) {
+ gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+ int x1 = borderLeft - 1;
+ int x2 = size.x - borderRight;
+ int y1 = parent.onBottom ? borderTop - 1 : borderTop + tabHeight;
+ int y2 = parent.onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom;
+ gc.drawLine(x1, y1, x1, y2); // left
+ gc.drawLine(x2, y1, x2, y2); // right
+ if (parent.onBottom) {
+ gc.drawLine(x1, y1, x2, y1); // top
+ } else {
+ gc.drawLine(x1, y2, x2, y2); // bottom
+ }
+ }
+ }
+
+ void drawClose(GC gc, Rectangle closeRect, int closeImageState) {
+ if (closeRect.width == 0 || closeRect.height == 0) return;
+ Display display = parent.getDisplay();
+
+ // draw X 9x9
+ int x = closeRect.x + Math.max(1, (closeRect.width-9)/2);
+ int y = closeRect.y + Math.max(1, (closeRect.height-9)/2);
+ y += parent.onBottom ? -1 : 1;
+
+ Color closeBorder = display.getSystemColor(BUTTON_BORDER);
+ switch (closeImageState & (SWT.HOT | SWT.SELECTED | SWT.BACKGROUND)) {
+ case SWT.NONE: {
+ int[] shape = new int[] {x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
+ x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
+ x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
+ x,y+7, x+2,y+5, x+2,y+4, x,y+2};
+ gc.setBackground(display.getSystemColor(BUTTON_FILL));
+ gc.fillPolygon(shape);
+ gc.setForeground(closeBorder);
+ gc.drawPolygon(shape);
+ break;
+ }
+ case SWT.HOT: {
+ int[] shape = new int[] {x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
+ x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
+ x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
+ x,y+7, x+2,y+5, x+2,y+4, x,y+2};
+ gc.setBackground(getFillColor());
+ gc.fillPolygon(shape);
+ gc.setForeground(closeBorder);
+ gc.drawPolygon(shape);
+ break;
+ }
+ case SWT.SELECTED: {
+ int[] shape = new int[] {x+1,y+1, x+3,y+1, x+5,y+3, x+6,y+3, x+8,y+1, x+10,y+1,
+ x+10,y+3, x+8,y+5, x+8,y+6, x+10,y+8, x+10,y+10,
+ x+8,y+10, x+6,y+8, x+5,y+8, x+3,y+10, x+1,y+10,
+ x+1,y+8, x+3,y+6, x+3,y+5, x+1,y+3};
+ gc.setBackground(getFillColor());
+ gc.fillPolygon(shape);
+ gc.setForeground(closeBorder);
+ gc.drawPolygon(shape);
+ break;
+ }
+ case SWT.BACKGROUND: {
+ int[] shape = new int[] {x,y, x+10,y, x+10,y+10, x,y+10};
+ if (parent.gradientColors != null && !parent.gradientVertical) {
+ drawBackground(gc, shape, false);
+ } else {
+ Color defaultBackground = parent.getBackground();
+ Color[] colors = parent.gradientColors;
+ int[] percents = parent.gradientPercents;
+ boolean vertical = parent.gradientVertical;
+ drawBackground(gc, shape, x, y, 10, 10, defaultBackground, null, colors, percents, vertical);
+ }
+ break;
+ }
+ }
+ }
+
+ void drawChevron(GC gc, Rectangle chevronRect, int chevronImageState) {
+ if (chevronRect.width == 0 || chevronRect.height == 0) return;
+ int selectedIndex = parent.selectedIndex;
+ // draw chevron (10x7)
+ Display display = parent.getDisplay();
+ Point dpi = display.getDPI();
+ int fontHeight = 72 * 10 / dpi.y;
+ FontData fd = parent.getFont().getFontData()[0];
+ fd.setHeight(fontHeight);
+ Font f = new Font(display, fd);
+ int fHeight = f.getFontData()[0].getHeight() * dpi.y / 72;
+ int indent = Math.max(2, (chevronRect.height - fHeight - 4) /2);
+ int x = chevronRect.x + 2;
+ int y = chevronRect.y + indent;
+ int count;
+ int itemCount = parent.getItemCount();
+ if (parent.single) {
+ count = selectedIndex == -1 ? itemCount : itemCount - 1;
+ } else {
+ int showCount = 0;
+ while (showCount < parent.priority.length && parent.items[parent.priority[showCount]].showing) {
+ showCount++;
+ }
+ count = itemCount - showCount;
+ }
+ String chevronString = count > 99 ? "99+" : String.valueOf(count); //$NON-NLS-1$
+ switch (chevronImageState & (SWT.HOT | SWT.SELECTED)) {
+ case SWT.NONE: {
+ Color chevronBorder = parent.single ? parent.getSelectionForeground() : parent.getForeground();
+ gc.setForeground(chevronBorder);
+ gc.setFont(f);
+ gc.drawLine(x,y, x+2,y+2);
+ gc.drawLine(x+2,y+2, x,y+4);
+ gc.drawLine(x+1,y, x+3,y+2);
+ gc.drawLine(x+3,y+2, x+1,y+4);
+ gc.drawLine(x+4,y, x+6,y+2);
+ gc.drawLine(x+6,y+2, x+5,y+4);
+ gc.drawLine(x+5,y, x+7,y+2);
+ gc.drawLine(x+7,y+2, x+4,y+4);
+ gc.drawString(chevronString, x+7, y+3, true);
+ break;
+ }
+ case SWT.HOT: {
+ gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+ gc.setBackground(display.getSystemColor(BUTTON_FILL));
+ gc.setFont(f);
+ gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
+ gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
+ gc.drawLine(x,y, x+2,y+2);
+ gc.drawLine(x+2,y+2, x,y+4);
+ gc.drawLine(x+1,y, x+3,y+2);
+ gc.drawLine(x+3,y+2, x+1,y+4);
+ gc.drawLine(x+4,y, x+6,y+2);
+ gc.drawLine(x+6,y+2, x+5,y+4);
+ gc.drawLine(x+5,y, x+7,y+2);
+ gc.drawLine(x+7,y+2, x+4,y+4);
+ gc.drawString(chevronString, x+7, y+3, true);
+ break;
+ }
+ case SWT.SELECTED: {
+ gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+ gc.setBackground(display.getSystemColor(BUTTON_FILL));
+ gc.setFont(f);
+ gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
+ gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
+ gc.drawLine(x+1,y+1, x+3,y+3);
+ gc.drawLine(x+3,y+3, x+1,y+5);
+ gc.drawLine(x+2,y+1, x+4,y+3);
+ gc.drawLine(x+4,y+3, x+2,y+5);
+ gc.drawLine(x+5,y+1, x+7,y+3);
+ gc.drawLine(x+7,y+3, x+6,y+5);
+ gc.drawLine(x+6,y+1, x+8,y+3);
+ gc.drawLine(x+8,y+3, x+5,y+5);
+ gc.drawString(chevronString, x+8, y+4, true);
+ break;
+ }
+ }
+ f.dispose();
+ }
+
+ /*
+ * Draw a highlight effect along the left, top, and right edges of the tab.
+ * Only for curved tabs, on top.
+ * Do not draw if insufficient colors.
+ */
+ void drawHighlight(GC gc, Rectangle bounds, int state, int rightEdge) {
+ //only draw for curvy tabs and only draw for top tabs
+ if(parent.simple || parent.onBottom)
+ return;
+
+ if(selectionHighlightGradientBegin == null)
+ return;
+
+ Color[] gradients = selectionHighlightGradientColorsCache;
+ if(gradients == null)
+ return;
+ int gradientsSize = gradients.length;
+ if(gradientsSize == 0)
+ return; //shouldn't happen but just to be tidy
+
+ int x = bounds.x;
+ int y = bounds.y;
+
+ gc.setForeground(gradients[0]);
+
+ //draw top horizontal line
+ gc.drawLine(
+ TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve
+ 1 + y,
+ rightEdge - curveIndent,
+ 1 + y);
+
+ int[] leftHighlightCurve = TOP_LEFT_CORNER_HILITE;
+
+ int d = parent.tabHeight - topCurveHighlightEnd.length /2;
+
+ int lastX = 0;
+ int lastY = 0;
+ int lastColorIndex = 0;
+
+ //draw upper left curve highlight
+ for (int i = 0; i < leftHighlightCurve.length /2; i++) {
+ int rawX = leftHighlightCurve[i * 2];
+ int rawY = leftHighlightCurve[i * 2 + 1];
+ lastX = rawX + x;
+ lastY = rawY + y;
+ lastColorIndex = rawY - 1;
+ gc.setForeground(gradients[lastColorIndex]);
+ gc.drawPoint(lastX, lastY);
+ }
+ //draw left vertical line highlight
+ for(int i = lastColorIndex; i < gradientsSize; i++) {
+ gc.setForeground(gradients[i]);
+ gc.drawPoint(lastX, 1 + lastY++);
+ }
+
+ int rightEdgeOffset = rightEdge - curveIndent;
+
+ //draw right swoop highlight up to diagonal portion
+ for (int i = 0; i < topCurveHighlightStart.length /2; i++) {
+ int rawX = topCurveHighlightStart[i * 2];
+ int rawY = topCurveHighlightStart[i * 2 + 1];
+ lastX = rawX + rightEdgeOffset;
+ lastY = rawY + y;
+ lastColorIndex = rawY - 1;
+ if(lastColorIndex >= gradientsSize)
+ break; //can happen if tabs are unusually short and cut off the curve
+ gc.setForeground(gradients[lastColorIndex]);
+ gc.drawPoint(lastX, lastY);
+ }
+ //draw right diagonal line highlight
+ for(int i = lastColorIndex; i < lastColorIndex + d; i++) {
+ if(i >= gradientsSize)
+ break; //can happen if tabs are unusually short and cut off the curve
+ gc.setForeground(gradients[i]);
+ gc.drawPoint(1 + lastX++, 1 + lastY++);
+ }
+
+ //draw right swoop highlight from diagonal portion to end
+ for (int i = 0; i < topCurveHighlightEnd.length /2; i++) {
+ int rawX = topCurveHighlightEnd[i * 2]; //d is already encoded in this value
+ int rawY = topCurveHighlightEnd[i * 2 + 1]; //d already encoded
+ lastX = rawX + rightEdgeOffset;
+ lastY = rawY + y;
+ lastColorIndex = rawY - 1;
+ if(lastColorIndex >= gradientsSize)
+ break; //can happen if tabs are unusually short and cut off the curve
+ gc.setForeground(gradients[lastColorIndex]);
+ gc.drawPoint(lastX, lastY);
+ }
+ }
+
+ /*
+ * Draw the unselected border for the receiver on the left.
+ *
+ * @param gc
+ */
+ void drawLeftUnselectedBorder(GC gc, Rectangle bounds, int state) {
+ int x = bounds.x;
+ int y = bounds.y;
+ int height = bounds.height;
+
+ int[] shape = null;
+ if (parent.onBottom) {
+ int[] left = parent.simple
+ ? SIMPLE_UNSELECTED_INNER_CORNER
+ : BOTTOM_LEFT_CORNER;
+
+ shape = new int[left.length + 2];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y - 1;
+ for (int i = 0; i < left.length / 2; i++) {
+ shape[index++] = x + left[2 * i];
+ shape[index++] = y + height + left[2 * i + 1] - 1;
+ }
+ } else {
+ int[] left = parent.simple
+ ? SIMPLE_UNSELECTED_INNER_CORNER
+ : TOP_LEFT_CORNER;
+
+ shape = new int[left.length + 2];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y + height;
+ for (int i = 0; i < left.length / 2; i++) {
+ shape[index++] = x + left[2 * i];
+ shape[index++] = y + left[2 * i + 1];
+ }
+
+ }
+
+ drawBorder(gc, shape);
+ }
+
+ void drawMaximize(GC gc, Rectangle maxRect, int maxImageState) {
+ if (maxRect.width == 0 || maxRect.height == 0) return;
+ Display display = parent.getDisplay();
+ // 5x4 or 7x9
+ int x = maxRect.x + (maxRect.width - 10)/2;
+ int y = maxRect.y + 3;
+
+ gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+ gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+ switch (maxImageState & (SWT.HOT | SWT.SELECTED)) {
+ case SWT.NONE: {
+ if (!parent.getMaximized()) {
+ gc.fillRectangle(x, y, 9, 9);
+ gc.drawRectangle(x, y, 9, 9);
+ gc.drawLine(x+1, y+2, x+8, y+2);
+ } else {
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.drawRectangle(x, y+3, 5, 4);
+ gc.drawRectangle(x+2, y, 5, 4);
+ gc.drawLine(x+3, y+1, x+6, y+1);
+ gc.drawLine(x+1, y+4, x+4, y+4);
+ }
+ break;
+ }
+ case SWT.HOT: {
+ gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
+ gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
+ if (!parent.getMaximized()) {
+ gc.fillRectangle(x, y, 9, 9);
+ gc.drawRectangle(x, y, 9, 9);
+ gc.drawLine(x+1, y+2, x+8, y+2);
+ } else {
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.drawRectangle(x, y+3, 5, 4);
+ gc.drawRectangle(x+2, y, 5, 4);
+ gc.drawLine(x+3, y+1, x+6, y+1);
+ gc.drawLine(x+1, y+4, x+4, y+4);
+ }
+ break;
+ }
+ case SWT.SELECTED: {
+ gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
+ gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
+ if (!parent.getMaximized()) {
+ gc.fillRectangle(x+1, y+1, 9, 9);
+ gc.drawRectangle(x+1, y+1, 9, 9);
+ gc.drawLine(x+2, y+3, x+9, y+3);
+ } else {
+ gc.fillRectangle(x+1, y+4, 5, 4);
+ gc.fillRectangle(x+3, y+1, 5, 4);
+ gc.drawRectangle(x+1, y+4, 5, 4);
+ gc.drawRectangle(x+3, y+1, 5, 4);
+ gc.drawLine(x+4, y+2, x+7, y+2);
+ gc.drawLine(x+2, y+5, x+5, y+5);
+ }
+ break;
+ }
+ }
+ }
+ void drawMinimize(GC gc, Rectangle minRect, int minImageState) {
+ if (minRect.width == 0 || minRect.height == 0) return;
+ Display display = parent.getDisplay();
+ // 5x4 or 9x3
+ int x = minRect.x + (minRect.width - 10)/2;
+ int y = minRect.y + 3;
+
+ gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+ gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+ switch (minImageState & (SWT.HOT | SWT.SELECTED)) {
+ case SWT.NONE: {
+ if (!parent.getMinimized()) {
+ gc.fillRectangle(x, y, 9, 3);
+ gc.drawRectangle(x, y, 9, 3);
+ } else {
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.drawRectangle(x, y+3, 5, 4);
+ gc.drawRectangle(x+2, y, 5, 4);
+ gc.drawLine(x+3, y+1, x+6, y+1);
+ gc.drawLine(x+1, y+4, x+4, y+4);
+ }
+ break;
+ }
+ case SWT.HOT: {
+ gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
+ gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
+ if (!parent.getMinimized()) {
+ gc.fillRectangle(x, y, 9, 3);
+ gc.drawRectangle(x, y, 9, 3);
+ } else {
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.drawRectangle(x, y+3, 5, 4);
+ gc.drawRectangle(x+2, y, 5, 4);
+ gc.drawLine(x+3, y+1, x+6, y+1);
+ gc.drawLine(x+1, y+4, x+4, y+4);
+ }
+ break;
+ }
+ case SWT.SELECTED: {
+ gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
+ gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
+ if (!parent.getMinimized()) {
+ gc.fillRectangle(x+1, y+1, 9, 3);
+ gc.drawRectangle(x+1, y+1, 9, 3);
+ } else {
+ gc.fillRectangle(x+1, y+4, 5, 4);
+ gc.fillRectangle(x+3, y+1, 5, 4);
+ gc.drawRectangle(x+1, y+4, 5, 4);
+ gc.drawRectangle(x+3, y+1, 5, 4);
+ gc.drawLine(x+4, y+2, x+7, y+2);
+ gc.drawLine(x+2, y+5, x+5, y+5);
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Draw the unselected border for the receiver on the right.
+ *
+ * @param gc
+ */
+ void drawRightUnselectedBorder(GC gc, Rectangle bounds, int state) {
+ int x = bounds.x;
+ int y = bounds.y;
+ int width = bounds.width;
+ int height = bounds.height;
+
+ int[] shape = null;
+ int startX = x + width - 1;
+
+ if (parent.onBottom) {
+ int[] right = parent.simple
+ ? SIMPLE_UNSELECTED_INNER_CORNER
+ : BOTTOM_RIGHT_CORNER;
+
+ shape = new int[right.length + 2];
+ int index = 0;
+
+ for (int i = 0; i < right.length / 2; i++) {
+ shape[index++] = startX + right[2 * i];
+ shape[index++] = y + height + right[2 * i + 1] - 1;
+ }
+ shape[index++] = startX;
+ shape[index++] = y - 1;
+ } else {
+ int[] right = parent.simple
+ ? SIMPLE_UNSELECTED_INNER_CORNER
+ : TOP_RIGHT_CORNER;
+
+ shape = new int[right.length + 2];
+ int index = 0;
+
+ for (int i = 0; i < right.length / 2; i++) {
+ shape[index++] = startX + right[2 * i];
+ shape[index++] = y + right[2 * i + 1];
+ }
+
+ shape[index++] = startX;
+ shape[index++] = y + height;
+
+ }
+
+ drawBorder(gc, shape);
+
+ }
+
+ void drawSelected(int itemIndex, GC gc, Rectangle bounds, int state ) {
+ CTabItem item = parent.items[itemIndex];
+ int x = bounds.x;
+ int y = bounds.y;
+ int height = bounds.height;
+ int width = bounds.width;
+ if (!parent.simple && !parent.single) width -= (curveWidth - curveIndent);
+ int borderLeft = parent.borderVisible ? 1 : 0;
+ int borderRight = borderLeft;
+ int borderTop = parent.onBottom ? borderLeft : 0;
+ int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+ Point size = parent.getSize();
+
+ int rightEdge = Math.min (x + width, parent.getRightItemEdge(gc));
+ // Draw selection border across all tabs
+
+ if ((state & SWT.BACKGROUND) != 0) {
+ int xx = borderLeft;
+ int yy = parent.onBottom ? size.y - borderBottom - parent.tabHeight - highlight_header : borderTop + parent.tabHeight + 1;
+ int ww = size.x - borderLeft - borderRight;
+ int hh = highlight_header - 1;
+ int[] shape = new int[] {xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh};
+ if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
+ drawBackground(gc, shape, true);
+ } else {
+ gc.setBackground(parent.selectionBackground);
+ gc.fillRectangle(xx, yy, ww, hh);
+ }
+
+ if (parent.single) {
+ if (!item.showing) return;
+ } else {
+ // if selected tab scrolled out of view or partially out of view
+ // just draw bottom line
+ if (!item.showing){
+ int x1 = Math.max(0, borderLeft - 1);
+ int y1 = (parent.onBottom) ? y - 1 : y + height;
+ int x2 = size.x - borderRight;
+ gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+ gc.drawLine(x1, y1, x2, y1);
+ return;
+ }
+
+ // draw selected tab background and outline
+ shape = null;
+ if (parent.onBottom) {
+ int[] left = parent.simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER;
+ int[] right = parent.simple ? SIMPLE_BOTTOM_RIGHT_CORNER : curve;
+ if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+ left = new int[]{x, y+height};
+ }
+ shape = new int[left.length+right.length+8];
+ int index = 0;
+ shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
+ shape[index++] = y - 1;
+ shape[index++] = x;
+ shape[index++] = y - 1;
+ for (int i = 0; i < left.length/2; i++) {
+ shape[index++] = x + left[2*i];
+ shape[index++] = y + height + left[2*i+1] - 1;
+ }
+ for (int i = 0; i < right.length/2; i++) {
+ shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - curveIndent + right[2*i];
+ shape[index++] = parent.simple ? y + height + right[2*i+1] - 1 : y + right[2*i+1] - 2;
+ }
+ shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+ shape[index++] = y - 1;
+ shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+ shape[index++] = y - 1;
+ } else {
+ int[] left = parent.simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
+ int[] right = parent.simple ? SIMPLE_TOP_RIGHT_CORNER : curve;
+ if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+ left = new int[]{x, y};
+ }
+ shape = new int[left.length+right.length+8];
+ int index = 0;
+ shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
+ shape[index++] = y + height + 1;
+ shape[index++] = x;
+ shape[index++] = y + height + 1;
+ for (int i = 0; i < left.length/2; i++) {
+ shape[index++] = x + left[2*i];
+ shape[index++] = y + left[2*i+1];
+ }
+ for (int i = 0; i < right.length/2; i++) {
+ shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - curveIndent + right[2*i];
+ shape[index++] = y + right[2*i+1];
+ }
+ shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+ shape[index++] = y + height + 1;
+ shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+ shape[index++] = y + height + 1;
+ }
+
+ Rectangle clipping = gc.getClipping();
+ Rectangle clipBounds = item.getBounds();
+ clipBounds.height += 1;
+ if (parent.onBottom) clipBounds.y -= 1;
+ boolean tabInPaint = clipping.intersects(clipBounds);
+
+ if (tabInPaint) {
+ // fill in tab background
+ if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
+ drawBackground(gc, shape, true);
+ } else {
+ Color defaultBackground = parent.selectionBackground;
+ Image image = parent.selectionBgImage;
+ Color[] colors = parent.selectionGradientColors;
+ int[] percents = parent.selectionGradientPercents;
+ boolean vertical = parent.selectionGradientVertical;
+ xx = x;
+ yy = parent.onBottom ? y -1 : y + 1;
+ ww = width;
+ hh = height;
+ if (!parent.single && !parent.simple) ww += curveWidth - curveIndent;
+ drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical);
+ }
+ }
+
+ //Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop)
+ //otherwise the curve looks jagged
+ drawHighlight(gc, bounds, state, rightEdge);
+
+ // draw outline
+ shape[0] = Math.max(0, borderLeft - 1);
+ if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+ shape[1] = parent.onBottom ? y + height - 1 : y;
+ shape[5] = shape[3] = shape[1];
+ }
+ shape[shape.length - 2] = size.x - borderRight + 1;
+ for (int i = 0; i < shape.length/2; i++) {
+ if (shape[2*i + 1] == y + height + 1) shape[2*i + 1] -= 1;
+ }
+ Color borderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+ if (! borderColor.equals(lastBorderColor)) createAntialiasColors();
+ antialias(shape, selectedInnerColor, selectedOuterColor, gc);
+ gc.setForeground(borderColor);
+ gc.drawPolyline(shape);
+
+ if (!tabInPaint) return;
+ }
+ }
+
+ if ((state & SWT.FOREGROUND) != 0) {
+ // draw Image
+ Rectangle trim = computeTrim(itemIndex, SWT.NONE, 0, 0, 0, 0);
+ int xDraw = x - trim.x;
+ if (parent.single && (parent.showClose || item.showClose)) xDraw += item.closeRect.width;
+ Image image = item.getImage();
+ if (image != null) {
+ Rectangle imageBounds = image.getBounds();
+ // only draw image if it won't overlap with close button
+ int maxImageWidth = rightEdge - xDraw - (trim.width + trim.x);
+ if (!parent.single && item.closeRect.width > 0) maxImageWidth -= item.closeRect.width + INTERNAL_SPACING;
+ if (imageBounds.width < maxImageWidth) {
+ int imageX = xDraw;
+ int imageY = y + (height - imageBounds.height) / 2;
+ imageY += parent.onBottom ? -1 : 1;
+ gc.drawImage(image, imageX, imageY);
+ xDraw += imageBounds.width + INTERNAL_SPACING;
+ }
+ }
+
+ // draw Text
+ int textWidth = rightEdge - xDraw - (trim.width + trim.x);
+ if (!parent.single && item.closeRect.width > 0) textWidth -= item.closeRect.width + INTERNAL_SPACING;
+ if (textWidth > 0) {
+ Font gcFont = gc.getFont();
+ gc.setFont(item.font == null ? parent.getFont() : item.font);
+
+ if (item.shortenedText == null || item.shortenedTextWidth != textWidth) {
+ item.shortenedText = shortenText(gc, item.getText(), textWidth);
+ item.shortenedTextWidth = textWidth;
+ }
+ Point extent = gc.textExtent(item.shortenedText, FLAGS);
+ int textY = y + (height - extent.y) / 2;
+ textY += parent.onBottom ? -1 : 1;
+
+ gc.setForeground(parent.selectionForeground);
+ gc.drawText(item.shortenedText, xDraw, textY, FLAGS);
+ gc.setFont(gcFont);
+
+ // draw a Focus rectangle
+ if (parent.isFocusControl()) {
+ Display display = parent.getDisplay();
+ if (parent.simple || parent.single) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.drawFocus(xDraw-1, textY-1, extent.x+2, extent.y+2);
+ } else {
+ gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+ gc.drawLine(xDraw, textY+extent.y+1, xDraw+extent.x+1, textY+extent.y+1);
+ }
+ }
+ }
+ if (parent.showClose || item.showClose) drawClose(gc, item.closeRect, item.closeImageState);
+ }
+ }
+
+ void drawTabArea(GC gc, Rectangle bounds, int state) {
+ Point size = parent.getSize();
+ int[] shape = null;
+ Color borderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+ int tabHeight = parent.tabHeight;
+ int style = parent.getStyle();
+
+ int borderLeft = parent.borderVisible ? 1 : 0;
+ int borderRight = borderLeft;
+ int borderTop = parent.onBottom ? borderLeft : 0;
+ int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+ int selectedIndex = parent.selectedIndex;
+ if (tabHeight == 0) {
+ if ((style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) return;
+ int x1 = borderLeft - 1;
+ int x2 = size.x - borderRight;
+ int y1 = parent.onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header;
+ int y2 = parent.onBottom ? size.y - borderBottom : borderTop;
+ if (borderLeft > 0 && parent.onBottom) y2 -= 1;
+
+ shape = new int[] {x1, y1, x1,y2, x2,y2, x2,y1};
+
+ // If horizontal gradient, show gradient across the whole area
+ if (selectedIndex != -1 && parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1 && !parent.selectionGradientVertical) {
+ drawBackground(gc, shape, true);
+ } else if (selectedIndex == -1 && parent.gradientColors != null && parent.gradientColors.length > 1 && !parent.gradientVertical) {
+ drawBackground(gc, shape, false);
+ } else {
+ gc.setBackground(selectedIndex == -1 ? parent.getBackground() : parent.selectionBackground);
+ gc.fillPolygon(shape);
+ }
+
+ //draw 1 pixel border
+ if (borderLeft > 0) {
+ gc.setForeground(borderColor);
+ gc.drawPolyline(shape);
+ }
+ return;
+ }
+
+ int x = Math.max(0, borderLeft - 1);
+ int y = parent.onBottom ? size.y - borderBottom - tabHeight : borderTop;
+ int width = size.x - borderLeft - borderRight + 1;
+ int height = tabHeight - 1;
+ boolean simple = parent.simple;
+ // Draw Tab Header
+ if (parent.onBottom) {
+ int[] left, right;
+ if ((style & SWT.BORDER) != 0) {
+ left = simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER;
+ right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER : BOTTOM_RIGHT_CORNER;
+ } else {
+ left = simple ? SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS : BOTTOM_LEFT_CORNER_BORDERLESS;
+ right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS : BOTTOM_RIGHT_CORNER_BORDERLESS;
+ }
+ shape = new int[left.length + right.length + 4];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y-highlight_header;
+ for (int i = 0; i < left.length/2; i++) {
+ shape[index++] = x+left[2*i];
+ shape[index++] = y+height+left[2*i+1];
+ if (borderLeft == 0) shape[index-1] += 1;
+ }
+ for (int i = 0; i < right.length/2; i++) {
+ shape[index++] = x+width+right[2*i];
+ shape[index++] = y+height+right[2*i+1];
+ if (borderLeft == 0) shape[index-1] += 1;
+ }
+ shape[index++] = x+width;
+ shape[index++] = y-highlight_header;
+ } else {
+ int[] left, right;
+ if ((style & SWT.BORDER) != 0) {
+ left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
+ right = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER;
+ } else {
+ left = simple ? SIMPLE_TOP_LEFT_CORNER_BORDERLESS : TOP_LEFT_CORNER_BORDERLESS;
+ right = simple ? SIMPLE_TOP_RIGHT_CORNER_BORDERLESS : TOP_RIGHT_CORNER_BORDERLESS;
+ }
+ shape = new int[left.length + right.length + 4];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y+height+highlight_header + 1;
+ for (int i = 0; i < left.length/2; i++) {
+ shape[index++] = x+left[2*i];
+ shape[index++] = y+left[2*i+1];
+ }
+ for (int i = 0; i < right.length/2; i++) {
+ shape[index++] = x+width+right[2*i];
+ shape[index++] = y+right[2*i+1];
+ }
+ shape[index++] = x+width;
+ shape[index++] = y+height+highlight_header + 1;
+ }
+ // Fill in background
+ boolean single = parent.single;
+ boolean bkSelected = single && selectedIndex != -1;
+ drawBackground(gc, shape, bkSelected);
+ // Fill in parent background for non-rectangular shape
+ Region r = new Region();
+ r.add(new Rectangle(x, y, width + 1, height + 1));
+ r.subtract(shape);
+ gc.setBackground(parent.getParent().getBackground());
+ fillRegion(gc, r);
+ r.dispose();
+
+ // Draw selected tab
+ if (selectedIndex == -1) {
+ // if no selected tab - draw line across bottom of all tabs
+ int x1 = borderLeft;
+ int y1 = (parent.onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight;
+ int x2 = size.x - borderRight;
+ gc.setForeground(borderColor);
+ gc.drawLine(x1, y1, x2, y1);
+ }
+
+ // Draw border line
+ if (borderLeft > 0) {
+ if (! borderColor.equals(lastBorderColor)) createAntialiasColors();
+ antialias(shape, null, tabAreaColor, gc);
+ gc.setForeground(borderColor);
+ gc.drawPolyline(shape);
+ }
+ }
+
+ void drawUnselected(int index, GC gc, Rectangle bounds, int state) {
+ CTabItem item = parent.items[index];
+ int x = bounds.x;
+ int y = bounds.y;
+ int height = bounds.height;
+ int width = bounds.width;
+
+ // Do not draw partial items
+ if (!item.showing) return;
+
+ Rectangle clipping = gc.getClipping();
+ if (!clipping.intersects(bounds)) return;
+
+ if ((state & SWT.BACKGROUND) != 0) {
+ if (index > 0 && index < parent.selectedIndex)
+ drawLeftUnselectedBorder(gc, bounds, state);
+ // If it is the last one then draw a line
+ if (index > parent.selectedIndex)
+ drawRightUnselectedBorder(gc, bounds, state);
+ }
+
+ if ((state & SWT.FOREGROUND) != 0) {
+ // draw Image
+ Rectangle trim = computeTrim(index, SWT.NONE, 0, 0, 0, 0);
+ int xDraw = x - trim.x;
+ Image image = item.getImage();
+ if (image != null && parent.showUnselectedImage) {
+ Rectangle imageBounds = image.getBounds();
+ // only draw image if it won't overlap with close button
+ int maxImageWidth = x + width - xDraw - (trim.width + trim.x);
+ if (parent.showUnselectedClose && (parent.showClose || item.showClose)) {
+ maxImageWidth -= item.closeRect.width + INTERNAL_SPACING;
+ }
+ if (imageBounds.width < maxImageWidth) {
+ int imageX = xDraw;
+ int imageHeight = imageBounds.height;
+ int imageY = y + (height - imageHeight) / 2;
+ imageY += parent.onBottom ? -1 : 1;
+ 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 - (trim.width + trim.x);
+ if (parent.showUnselectedClose && (parent.showClose || item.showClose)) {
+ textWidth -= item.closeRect.width + INTERNAL_SPACING;
+ }
+ if (textWidth > 0) {
+ Font gcFont = gc.getFont();
+ gc.setFont(item.font == null ? parent.getFont() : item.font);
+ if (item.shortenedText == null || item.shortenedTextWidth != textWidth) {
+ item.shortenedText = shortenText(gc, item.getText(), textWidth);
+ item.shortenedTextWidth = textWidth;
+ }
+ Point extent = gc.textExtent(item.shortenedText, FLAGS);
+ int textY = y + (height - extent.y) / 2;
+ textY += parent.onBottom ? -1 : 1;
+ gc.setForeground(parent.getForeground());
+ gc.drawText(item.shortenedText, xDraw, textY, FLAGS);
+ gc.setFont(gcFont);
+ }
+ // draw close
+ if (parent.showUnselectedClose && (parent.showClose || item.showClose)) drawClose(gc, item.closeRect, item.closeImageState);
+ }
+ }
+
+ void fillRegion(GC gc, Region region) {
+ // NOTE: region passed in to this function will be modified
+ Region clipping = new Region();
+ gc.getClipping(clipping);
+ region.intersect(clipping);
+ gc.setClipping(region);
+ gc.fillRectangle(region.getBounds());
+ gc.setClipping(clipping);
+ clipping.dispose();
+ }
+
+ Color getFillColor() {
+ if (fillColor == null) {
+ fillColor = new Color(parent.getDisplay(), CLOSE_FILL);
+ }
+ return fillColor;
+ }
+
+ /*
+ * Return true if given start color, the cache of highlight colors we have
+ * would match the highlight colors we'd compute.
+ */
+ boolean isSelectionHighlightColorsCacheHit(Color start) {
+
+ if(selectionHighlightGradientColorsCache == null)
+ return false;
+
+ //this case should never happen but check to be safe before accessing array indexes
+ if(selectionHighlightGradientColorsCache.length < 2)
+ return false;
+
+ Color highlightBegin = selectionHighlightGradientColorsCache[0];
+ Color highlightEnd = selectionHighlightGradientColorsCache[selectionHighlightGradientColorsCache.length - 1];
+
+ if(! highlightBegin.equals(start))
+ return false;
+
+ //Compare number of colours we have vs. we'd compute
+ if(selectionHighlightGradientColorsCache.length != parent.tabHeight)
+ return false;
+
+ //Compare existing highlight end to what it would be (selectionBackground)
+ if(! highlightEnd.equals(parent.selectionBackground))
+ return false;
+
+ return true;
+ }
+
+ void setSelectionHighlightGradientColor(Color start) {
+ //
+ //Set to null to match all the early return cases.
+ //For early returns, don't realloc the cache, we may get a cache hit next time we're given the highlight
+ selectionHighlightGradientBegin = null;
+
+ if(start == null)
+ return;
+
+ //don't bother on low colour
+ if (parent.getDisplay().getDepth() < 15)
+ return;
+
+ //don't bother if we don't have a background gradient
+ if(parent.selectionGradientColors.length < 2)
+ return;
+
+ //OK we know its a valid gradient now
+ selectionHighlightGradientBegin = start;
+
+ if(! isSelectionHighlightColorsCacheHit(start))
+ createSelectionHighlightGradientColors(start); //if no cache hit then compute new ones
+ }
+
+ String shortenText(GC gc, String text, int width) {
+ return useEllipses()
+ ? shortenText(gc, text, width, ELLIPSIS)
+ : shortenText(gc, text, width, ""); //$NON-NLS-1$
+ }
+
+ String shortenText(GC gc, String text, int width, String ellipses) {
+ if (gc.textExtent(text, FLAGS).x <= width) return text;
+ int ellipseWidth = gc.textExtent(ellipses, FLAGS).x;
+ int length = text.length();
+ TextLayout layout = new TextLayout(parent.getDisplay());
+ layout.setText(text);
+ int end = layout.getPreviousOffset(length, SWT.MOVEMENT_CLUSTER);
+ while (end > 0) {
+ text = text.substring(0, end);
+ int l = gc.textExtent(text, FLAGS).x;
+ if (l + ellipseWidth <= width) {
+ break;
+ }
+ end = layout.getPreviousOffset(end, SWT.MOVEMENT_CLUSTER);
+ }
+ layout.dispose();
+ return end == 0 ? text.substring(0, 1) : text + ellipses;
+ }
+
+ void updateCurves () {
+ int tabHeight = parent.tabHeight;
+ if (tabHeight == lastTabHeight) return;
+ if (parent.onBottom) {
+ int d = tabHeight - 12;
+ curve = new int[]{0,13+d, 0,12+d, 2,12+d, 3,11+d, 5,11+d, 6,10+d, 7,10+d, 9,8+d, 10,8+d,
+ 11,7+d, 11+d,7,
+ 12+d,6, 13+d,6, 15+d,4, 16+d,4, 17+d,3, 19+d,3, 20+d,2, 22+d,2, 23+d,1};
+ curveWidth = 26+d;
+ curveIndent = curveWidth/3;
+ } else {
+ int d = tabHeight - 12;
+ curve = new int[]{0,0, 0,1, 2,1, 3,2, 5,2, 6,3, 7,3, 9,5, 10,5,
+ 11,6, 11+d,6+d,
+ 12+d,7+d, 13+d,7+d, 15+d,9+d, 16+d,9+d, 17+d,10+d, 19+d,10+d, 20+d,11+d, 22+d,11+d, 23+d,12+d};
+ curveWidth = 26+d;
+ curveIndent = curveWidth/3;
+
+ //this could be static but since values depend on curve, better to keep in one place
+ topCurveHighlightStart = new int[] {
+ 0, 2, 1, 2, 2, 2,
+ 3, 3, 4, 3, 5, 3,
+ 6, 4, 7, 4,
+ 8, 5,
+ 9, 6, 10, 6};
+
+ //also, by adding in 'd' here we save some math cost when drawing the curve
+ topCurveHighlightEnd = new int[] {
+ 10+d, 6+d,
+ 11+d, 7+d,
+ 12+d, 8+d, 13+d, 8+d,
+ 14+d, 9+d,
+ 15+d, 10+d, 16+d, 10+d,
+ 17+d, 11+d, 18+d, 11+d, 19+d, 11+d,
+ 20+d, 12+d, 21+d, 12+d, 22+d, 12+d };
+ }
+ }
+
+ /*
+ * Return whether to use ellipses or just truncate labels
+ */
+ boolean useEllipses() {
+ return parent.simple;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java
index 392d7c6682..e5b2eee2ad 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java
@@ -47,19 +47,10 @@ public class CTabItem extends Item {
Image disabledImage;
Rectangle closeRect = new Rectangle(0, 0, 0, 0);
- int closeImageState = CTabFolder.NONE;
+ int closeImageState = SWT.BACKGROUND;
boolean showClose = false;
boolean showing = false;
- // internal constants
- static final int TOP_MARGIN = 2;
- static final int BOTTOM_MARGIN = 2;
- static final int LEFT_MARGIN = 4;
- static final int RIGHT_MARGIN = 4;
- static final int INTERNAL_SPACING = 4;
- static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC;
- static final String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026"
-
/**
* Constructs a new instance of this class given its parent
* (which must be a <code>CTabFolder</code>) and a style value
@@ -127,37 +118,6 @@ public CTabItem (CTabFolder parent, int style, int index) {
parent.createItem (this, index);
}
-/*
- * Return whether to use ellipses or just truncate labels
- */
-boolean useEllipses() {
- return parent.simple;
-}
-
-String shortenText(GC gc, String text, int width) {
- return useEllipses()
- ? shortenText(gc, text, width, ELLIPSIS)
- : shortenText(gc, text, width, ""); //$NON-NLS-1$
-}
-
-String shortenText(GC gc, String text, int width, String ellipses) {
- if (gc.textExtent(text, FLAGS).x <= width) return text;
- int ellipseWidth = gc.textExtent(ellipses, FLAGS).x;
- int length = text.length();
- TextLayout layout = new TextLayout(getDisplay());
- layout.setText(text);
- int end = layout.getPreviousOffset(length, SWT.MOVEMENT_CLUSTER);
- while (end > 0) {
- text = text.substring(0, end);
- int l = gc.textExtent(text, FLAGS).x;
- if (l + ellipseWidth <= width) {
- break;
- }
- end = layout.getPreviousOffset(end, SWT.MOVEMENT_CLUSTER);
- }
- layout.dispose();
- return end == 0 ? text.substring(0, 1) : text + ellipses;
-}
public void dispose() {
if (isDisposed ()) return;
@@ -170,498 +130,7 @@ public void dispose() {
shortenedText = null;
font = null;
}
-void drawClose(GC gc) {
- if (closeRect.width == 0 || closeRect.height == 0) return;
- Display display = getDisplay();
-
- // draw X 9x9
- int indent = Math.max(1, (CTabFolder.BUTTON_SIZE-9)/2);
- int x = closeRect.x + indent;
- int y = closeRect.y + indent;
- y += parent.onBottom ? -1 : 1;
-
- Color closeBorder = display.getSystemColor(CTabFolder.BUTTON_BORDER);
- switch (closeImageState) {
- case CTabFolder.NORMAL: {
- int[] shape = new int[] {x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
- x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
- x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
- x,y+7, x+2,y+5, x+2,y+4, x,y+2};
- gc.setBackground(display.getSystemColor(CTabFolder.BUTTON_FILL));
- gc.fillPolygon(shape);
- gc.setForeground(closeBorder);
- gc.drawPolygon(shape);
- break;
- }
- case CTabFolder.HOT: {
- int[] shape = new int[] {x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
- x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
- x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
- x,y+7, x+2,y+5, x+2,y+4, x,y+2};
- gc.setBackground(parent.getFillColor());
- gc.fillPolygon(shape);
- gc.setForeground(closeBorder);
- gc.drawPolygon(shape);
- break;
- }
- case CTabFolder.SELECTED: {
- int[] shape = new int[] {x+1,y+1, x+3,y+1, x+5,y+3, x+6,y+3, x+8,y+1, x+10,y+1,
- x+10,y+3, x+8,y+5, x+8,y+6, x+10,y+8, x+10,y+10,
- x+8,y+10, x+6,y+8, x+5,y+8, x+3,y+10, x+1,y+10,
- x+1,y+8, x+3,y+6, x+3,y+5, x+1,y+3};
- gc.setBackground(parent.getFillColor());
- gc.fillPolygon(shape);
- gc.setForeground(closeBorder);
- gc.drawPolygon(shape);
- break;
- }
- case CTabFolder.NONE: {
- int[] shape = new int[] {x,y, x+10,y, x+10,y+10, x,y+10};
- if (parent.gradientColors != null && !parent.gradientVertical) {
- parent.drawBackground(gc, shape, false);
- } else {
- Color defaultBackground = parent.getBackground();
- Color[] colors = parent.gradientColors;
- int[] percents = parent.gradientPercents;
- boolean vertical = parent.gradientVertical;
- parent.drawBackground(gc, shape, x, y, 10, 10, defaultBackground, null, colors, percents, vertical);
- }
- break;
- }
- }
-}
-void drawSelected(GC gc ) {
- Point size = parent.getSize();
- int rightEdge = Math.min (x + width, parent.getRightItemEdge());
-
- // Draw selection border across all tabs
- int xx = parent.borderLeft;
- int yy = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - parent.highlight_header : parent.borderTop + parent.tabHeight + 1;
- int ww = size.x - parent.borderLeft - parent.borderRight;
- int hh = parent.highlight_header - 1;
- int[] shape = new int[] {xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh};
- if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
- parent.drawBackground(gc, shape, true);
- } else {
- gc.setBackground(parent.selectionBackground);
- gc.fillRectangle(xx, yy, ww, hh);
- }
-
- if (parent.single) {
- if (!showing) return;
- } else {
- // if selected tab scrolled out of view or partially out of view
- // just draw bottom line
- if (!showing){
- int x1 = Math.max(0, parent.borderLeft - 1);
- int y1 = (parent.onBottom) ? y - 1 : y + height;
- int x2 = size.x - parent.borderRight;
- gc.setForeground(getDisplay().getSystemColor(CTabFolder.BORDER1_COLOR));
- gc.drawLine(x1, y1, x2, y1);
- return;
- }
-
- // draw selected tab background and outline
- shape = null;
- if (this.parent.onBottom) {
- int[] left = parent.simple ? CTabFolder.SIMPLE_BOTTOM_LEFT_CORNER : CTabFolder.BOTTOM_LEFT_CORNER;
- int[] right = parent.simple ? CTabFolder.SIMPLE_BOTTOM_RIGHT_CORNER : parent.curve;
- if (parent.borderLeft == 0 && parent.indexOf(this) == parent.firstIndex) {
- left = new int[]{x, y+height};
- }
- shape = new int[left.length+right.length+8];
- int index = 0;
- shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
- shape[index++] = y - 1;
- shape[index++] = x;
- shape[index++] = y - 1;
- for (int i = 0; i < left.length/2; i++) {
- shape[index++] = x + left[2*i];
- shape[index++] = y + height + left[2*i+1] - 1;
- }
- for (int i = 0; i < right.length/2; i++) {
- shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i];
- shape[index++] = parent.simple ? y + height + right[2*i+1] - 1 : y + right[2*i+1] - 2;
- }
- shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
- shape[index++] = y - 1;
- shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
- shape[index++] = y - 1;
- } else {
- int[] left = parent.simple ? CTabFolder.SIMPLE_TOP_LEFT_CORNER : CTabFolder.TOP_LEFT_CORNER;
- int[] right = parent.simple ? CTabFolder.SIMPLE_TOP_RIGHT_CORNER : parent.curve;
- if (parent.borderLeft == 0 && parent.indexOf(this) == parent.firstIndex) {
- left = new int[]{x, y};
- }
- shape = new int[left.length+right.length+8];
- int index = 0;
- shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
- shape[index++] = y + height + 1;
- shape[index++] = x;
- shape[index++] = y + height + 1;
- for (int i = 0; i < left.length/2; i++) {
- shape[index++] = x + left[2*i];
- shape[index++] = y + left[2*i+1];
- }
- for (int i = 0; i < right.length/2; i++) {
- shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i];
- shape[index++] = y + right[2*i+1];
- }
- shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
- shape[index++] = y + height + 1;
- shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
- shape[index++] = y + height + 1;
- }
-
- Rectangle clipping = gc.getClipping();
- Rectangle bounds = getBounds();
- bounds.height += 1;
- if (parent.onBottom) bounds.y -= 1;
- boolean tabInPaint = clipping.intersects(bounds);
-
- if (tabInPaint) {
- // fill in tab background
- if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
- parent.drawBackground(gc, shape, true);
- } else {
- Color defaultBackground = parent.selectionBackground;
- Image image = parent.selectionBgImage;
- Color[] colors = parent.selectionGradientColors;
- int[] percents = parent.selectionGradientPercents;
- boolean vertical = parent.selectionGradientVertical;
- xx = x;
- yy = parent.onBottom ? y -1 : y + 1;
- ww = width;
- hh = height;
- if (!parent.single && !parent.simple) ww += parent.curveWidth - parent.curveIndent;
- parent.drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical);
- }
- }
-
- //Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop)
- //otherwise the curve looks jagged
- drawHighlight(gc, rightEdge);
-
- // draw outline
- shape[0] = Math.max(0, parent.borderLeft - 1);
- if (parent.borderLeft == 0 && parent.indexOf(this) == parent.firstIndex) {
- shape[1] = parent.onBottom ? y + height - 1 : y;
- shape[5] = shape[3] = shape[1];
- }
- shape[shape.length - 2] = size.x - parent.borderRight + 1;
- for (int i = 0; i < shape.length/2; i++) {
- if (shape[2*i + 1] == y + height + 1) shape[2*i + 1] -= 1;
- }
- Color borderColor = getDisplay().getSystemColor(CTabFolder.BORDER1_COLOR);
- if (! borderColor.equals(parent.lastBorderColor)) parent.createAntialiasColors();
- parent.antialias(shape, parent.selectedInnerColor, parent.selectedOuterColor, gc);
- gc.setForeground(borderColor);
- gc.drawPolyline(shape);
-
- if (!tabInPaint) return;
- }
-
- // draw Image
- int xDraw = x + LEFT_MARGIN;
- if (parent.single && (parent.showClose || showClose)) xDraw += CTabFolder.BUTTON_SIZE;
- Image image = getImage();
- if (image != null) {
- Rectangle imageBounds = image.getBounds();
- // only draw image if it won't overlap with close button
- int maxImageWidth = rightEdge - xDraw - RIGHT_MARGIN;
- if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING;
- if (imageBounds.width < maxImageWidth) {
- int imageX = xDraw;
- int imageY = y + (height - imageBounds.height) / 2;
- imageY += parent.onBottom ? -1 : 1;
- gc.drawImage(image, imageX, imageY);
- xDraw += imageBounds.width + INTERNAL_SPACING;
- }
- }
-
- // draw Text
- int textWidth = rightEdge - xDraw - RIGHT_MARGIN;
- if (!parent.single && closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING;
- if (textWidth > 0) {
- Font gcFont = gc.getFont();
- gc.setFont(font == null ? parent.getFont() : font);
-
- if (shortenedText == null || shortenedTextWidth != textWidth) {
- shortenedText = shortenText(gc, getText(), textWidth);
- shortenedTextWidth = textWidth;
- }
- Point extent = gc.textExtent(shortenedText, FLAGS);
- int textY = y + (height - extent.y) / 2;
- textY += parent.onBottom ? -1 : 1;
-
- gc.setForeground(parent.selectionForeground);
- gc.drawText(shortenedText, xDraw, textY, FLAGS);
- gc.setFont(gcFont);
-
- // draw a Focus rectangle
- if (parent.isFocusControl()) {
- Display display = getDisplay();
- if (parent.simple || parent.single) {
- gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
- gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- gc.drawFocus(xDraw-1, textY-1, extent.x+2, extent.y+2);
- } else {
- gc.setForeground(display.getSystemColor(CTabFolder.BUTTON_BORDER));
- gc.drawLine(xDraw, textY+extent.y+1, xDraw+extent.x+1, textY+extent.y+1);
- }
- }
- }
- if (parent.showClose || showClose) drawClose(gc);
-}
-/*
- * Draw a highlight effect along the left, top, and right edges of the tab.
- * Only for curved tabs, on top.
- * Do not draw if insufficient colors.
- */
-void drawHighlight(GC gc, int rightEdge) {
- //only draw for curvy tabs and only draw for top tabs
- if(parent.simple || this.parent.onBottom)
- return;
-
- if(parent.selectionHighlightGradientBegin == null)
- return;
-
- Color[] gradients = parent.selectionHighlightGradientColorsCache;
- if(gradients == null)
- return;
- int gradientsSize = gradients.length;
- if(gradientsSize == 0)
- return; //shouldn't happen but just to be tidy
-
- gc.setForeground(gradients[0]);
-
- //draw top horizontal line
- gc.drawLine(
- CTabFolder.TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve
- 1 + y,
- rightEdge - parent.curveIndent,
- 1 + y);
-
- int[] leftHighlightCurve = CTabFolder.TOP_LEFT_CORNER_HILITE;
-
- int d = parent.tabHeight - parent.topCurveHighlightEnd.length /2;
-
- int lastX = 0;
- int lastY = 0;
- int lastColorIndex = 0;
-
- //draw upper left curve highlight
- for (int i = 0; i < leftHighlightCurve.length /2; i++) {
- int rawX = leftHighlightCurve[i * 2];
- int rawY = leftHighlightCurve[i * 2 + 1];
- lastX = rawX + x;
- lastY = rawY + y;
- lastColorIndex = rawY - 1;
- gc.setForeground(gradients[lastColorIndex]);
- gc.drawPoint(lastX, lastY);
- }
- //draw left vertical line highlight
- for(int i = lastColorIndex; i < gradientsSize; i++) {
- gc.setForeground(gradients[i]);
- gc.drawPoint(lastX, 1 + lastY++);
- }
-
- int rightEdgeOffset = rightEdge - parent.curveIndent;
-
- //draw right swoop highlight up to diagonal portion
- for (int i = 0; i < parent.topCurveHighlightStart.length /2; i++) {
- int rawX = parent.topCurveHighlightStart[i * 2];
- int rawY = parent.topCurveHighlightStart[i * 2 + 1];
- lastX = rawX + rightEdgeOffset;
- lastY = rawY + y;
- lastColorIndex = rawY - 1;
- if(lastColorIndex >= gradientsSize)
- break; //can happen if tabs are unusually short and cut off the curve
- gc.setForeground(gradients[lastColorIndex]);
- gc.drawPoint(lastX, lastY);
- }
- //draw right diagonal line highlight
- for(int i = lastColorIndex; i < lastColorIndex + d; i++) {
- if(i >= gradientsSize)
- break; //can happen if tabs are unusually short and cut off the curve
- gc.setForeground(gradients[i]);
- gc.drawPoint(1 + lastX++, 1 + lastY++);
- }
-
- //draw right swoop highlight from diagonal portion to end
- for (int i = 0; i < parent.topCurveHighlightEnd.length /2; i++) {
- int rawX = parent.topCurveHighlightEnd[i * 2]; //d is already encoded in this value
- int rawY = parent.topCurveHighlightEnd[i * 2 + 1]; //d already encoded
- lastX = rawX + rightEdgeOffset;
- lastY = rawY + y;
- lastColorIndex = rawY - 1;
- if(lastColorIndex >= gradientsSize)
- break; //can happen if tabs are unusually short and cut off the curve
- gc.setForeground(gradients[lastColorIndex]);
- gc.drawPoint(lastX, lastY);
- }
-}
-
-/*
- * Draw the unselected border for the receiver on the right.
- *
- * @param gc
- */
-void drawRightUnselectedBorder(GC gc) {
-
- int[] shape = null;
- int startX = x + width - 1;
-
- if (this.parent.onBottom) {
- int[] right = parent.simple
- ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
- : CTabFolder.BOTTOM_RIGHT_CORNER;
-
- shape = new int[right.length + 2];
- int index = 0;
-
- for (int i = 0; i < right.length / 2; i++) {
- shape[index++] = startX + right[2 * i];
- shape[index++] = y + height + right[2 * i + 1] - 1;
- }
- shape[index++] = startX;
- shape[index++] = y - 1;
- } else {
- int[] right = parent.simple
- ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
- : CTabFolder.TOP_RIGHT_CORNER;
-
- shape = new int[right.length + 2];
- int index = 0;
-
- for (int i = 0; i < right.length / 2; i++) {
- shape[index++] = startX + right[2 * i];
- shape[index++] = y + right[2 * i + 1];
- }
-
- shape[index++] = startX;
- shape[index++] = y + height;
-
- }
-
- drawBorder(gc, shape);
-
-}
-
-/*
- * Draw the border of the tab
- *
- * @param gc
- * @param shape
- */
-void drawBorder(GC gc, int[] shape) {
-
- gc.setForeground(getDisplay().getSystemColor(CTabFolder.BORDER1_COLOR));
- gc.drawPolyline(shape);
-}
-
-/*
- * Draw the unselected border for the receiver on the left.
- *
- * @param gc
- */
-void drawLeftUnselectedBorder(GC gc) {
-
- int[] shape = null;
- if (this.parent.onBottom) {
- int[] left = parent.simple
- ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
- : CTabFolder.BOTTOM_LEFT_CORNER;
-
- shape = new int[left.length + 2];
- int index = 0;
- shape[index++] = x;
- shape[index++] = y - 1;
- for (int i = 0; i < left.length / 2; i++) {
- shape[index++] = x + left[2 * i];
- shape[index++] = y + height + left[2 * i + 1] - 1;
- }
- } else {
- int[] left = parent.simple
- ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
- : CTabFolder.TOP_LEFT_CORNER;
-
- shape = new int[left.length + 2];
- int index = 0;
- shape[index++] = x;
- shape[index++] = y + height;
- for (int i = 0; i < left.length / 2; i++) {
- shape[index++] = x + left[2 * i];
- shape[index++] = y + left[2 * i + 1];
- }
-
- }
-
- drawBorder(gc, shape);
-}
-
-void drawUnselected(GC gc) {
- // Do not draw partial items
- if (!showing) return;
-
- Rectangle clipping = gc.getClipping();
- Rectangle bounds = getBounds();
- if (!clipping.intersects(bounds)) return;
-
- // draw border
- int index = parent.indexOf(this);
-
- if (index > 0 && index < parent.selectedIndex)
- drawLeftUnselectedBorder(gc);
- // If it is the last one then draw a line
- if (index > parent.selectedIndex)
- drawRightUnselectedBorder(gc);
-
- // draw Image
- int xDraw = x + LEFT_MARGIN;
- Image image = getImage();
- if (image != null && parent.showUnselectedImage) {
- Rectangle imageBounds = image.getBounds();
- // only draw image if it won't overlap with close button
- int maxImageWidth = x + width - xDraw - RIGHT_MARGIN;
- if (parent.showUnselectedClose && (parent.showClose || showClose)) {
- maxImageWidth -= closeRect.width + INTERNAL_SPACING;
- }
- if (imageBounds.width < maxImageWidth) {
- int imageX = xDraw;
- int imageHeight = imageBounds.height;
- int imageY = y + (height - imageHeight) / 2;
- imageY += parent.onBottom ? -1 : 1;
- 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 (parent.showUnselectedClose && (parent.showClose || showClose)) {
- textWidth -= closeRect.width + INTERNAL_SPACING;
- }
- if (textWidth > 0) {
- Font gcFont = gc.getFont();
- gc.setFont(font == null ? parent.getFont() : font);
- if (shortenedText == null || shortenedTextWidth != textWidth) {
- shortenedText = shortenText(gc, getText(), textWidth);
- shortenedTextWidth = textWidth;
- }
- Point extent = gc.textExtent(shortenedText, FLAGS);
- int textY = y + (height - extent.y) / 2;
- textY += parent.onBottom ? -1 : 1;
- gc.setForeground(parent.getForeground());
- gc.drawText(shortenedText, xDraw, textY, FLAGS);
- gc.setFont(gcFont);
- }
- // draw close
- if (parent.showUnselectedClose && (parent.showClose || showClose)) drawClose(gc);
-}
/**
* Returns a rectangle describing the receiver's size and location
* relative to its parent.
@@ -675,9 +144,7 @@ void drawUnselected(GC gc) {
*/
public Rectangle getBounds () {
//checkWidget();
- int w = width;
- if (!parent.simple && !parent.single && parent.indexOf(this) == parent.selectedIndex) w += parent.curveWidth - parent.curveIndent;
- return new Rectangle(x, y, w, height);
+ return new Rectangle(x, y, width, height);
}
/**
* Gets the control that is displayed in the content area of the tab item.
@@ -793,73 +260,7 @@ public boolean isShowing () {
checkWidget();
return showing;
}
-void onPaint(GC gc, boolean isSelected) {
- if (width == 0 || height == 0) return;
- if (isSelected) {
- drawSelected(gc);
- } else {
- drawUnselected(gc);
- }
-}
-int preferredHeight(GC gc) {
- Image image = getImage();
- int h = (image == null) ? 0 : image.getBounds().height;
- String text = getText();
- if (font == null) {
- h = Math.max(h, gc.textExtent(text, FLAGS).y);
- } else {
- Font gcFont = gc.getFont();
- gc.setFont(font);
- h = Math.max(h, gc.textExtent(text, FLAGS).y);
- gc.setFont(gcFont);
- }
- return h + TOP_MARGIN + BOTTOM_MARGIN;
-}
-int preferredWidth(GC gc, boolean isSelected, boolean minimum) {
- // NOTE: preferred width does not include the "dead space" caused
- // by the curve.
- if (isDisposed()) return 0;
- int w = 0;
- Image image = getImage();
- if (image != null && (isSelected || parent.showUnselectedImage)) {
- w += image.getBounds().width;
- }
- String text = null;
- if (minimum) {
- int minChars = parent.minChars;
- text = minChars == 0 ? null : getText();
- if (text != null && text.length() > minChars) {
- if (useEllipses()) {
- int end = minChars < ELLIPSIS.length() + 1 ? minChars : minChars - ELLIPSIS.length();
- text = text.substring(0, end);
- if (minChars > ELLIPSIS.length() + 1) text += ELLIPSIS;
- } else {
- int end = minChars;
- text = text.substring(0, end);
- }
- }
- } else {
- text = getText();
- }
- if (text != null) {
- if (w > 0) w += INTERNAL_SPACING;
- if (font == null) {
- w += gc.textExtent(text, FLAGS).x;
- } else {
- Font gcFont = gc.getFont();
- gc.setFont(font);
- w += gc.textExtent(text, FLAGS).x;
- gc.setFont(gcFont);
- }
- }
- if (parent.showClose || showClose) {
- if (isSelected || parent.showUnselectedClose) {
- if (w > 0) w += INTERNAL_SPACING;
- w += CTabFolder.BUTTON_SIZE;
- }
- }
- return w + 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.
@@ -969,18 +370,25 @@ public void setImage (Image image) {
Rectangle bounds = image.getBounds();
if (bounds.width == oldBounds.width && bounds.height == oldBounds.height) {
if (showing) {
- boolean selected = parent.indexOf(this) == parent.selectedIndex;
+ int index = parent.indexOf(this);
+ boolean selected = index == parent.selectedIndex;
if (selected || parent.showUnselectedImage) {
- int imageX = x + LEFT_MARGIN, maxImageWidth;
+ CTabFolderRenderer renderer = parent.renderer;
+ Rectangle trim = renderer.computeTrim(index, SWT.NONE, 0, 0, 0, 0);
+ int imageX = x - trim.x, maxImageWidth;
if (selected) {
- if (parent.single && (parent.showClose || showClose)) imageX += CTabFolder.BUTTON_SIZE;
- int rightEdge = Math.min (x + width, parent.getRightItemEdge());
- maxImageWidth = rightEdge - imageX - RIGHT_MARGIN;
- if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+ GC gc = new GC(parent);
+ if (parent.single && (parent.showClose || showClose)) {
+ imageX += renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, SWT.NONE, gc).x;
+ }
+ int rightEdge = Math.min (x + width, parent.getRightItemEdge(gc));
+ gc.dispose();
+ maxImageWidth = rightEdge - imageX - (trim.width + trim.x);
+ if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + CTabFolderRenderer.INTERNAL_SPACING;
} else {
- maxImageWidth = x + width - imageX - RIGHT_MARGIN;
+ maxImageWidth = x + width - imageX - (trim.width + trim.x);
if (parent.showUnselectedClose && (parent.showClose || showClose)) {
- maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+ maxImageWidth -= closeRect.width + CTabFolderRenderer.INTERNAL_SPACING;
}
}
if (bounds.width < maxImageWidth) {