338147 - Update CTabFolder tab management
diff --git a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolder.java b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolder.java
index 5cf1c95..10ab6c0 100644
--- a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolder.java
+++ b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolder.java
@@ -148,33 +148,32 @@
 	boolean showClose = false;
 	boolean showUnselectedClose = true;
 	
-	Rectangle chevronRect = new Rectangle(0, 0, 0, 0);
-	int chevronImageState = SWT.NONE;
+	boolean showMin = false;
+	boolean minimized = false;
+	boolean showMax = false;
+	boolean maximized = false;
+	ToolBar minMaxTb;
+	ToolItem maxItem;
+	ToolItem minItem;
+	Image maxImage;
+	Image minImage;
+	Image restorImage;
+	
 	boolean showChevron = false;
 	Menu showMenu;
-	
-	boolean showMin = false;
-	Rectangle minRect = new Rectangle(0, 0, 0, 0);
-	boolean minimized = false;
-	int minImageState = SWT.NONE;
-	
-	boolean showMax = false;
-	Rectangle maxRect = new Rectangle(0, 0, 0, 0);
-	boolean maximized = false;
-	int maxImageState = SWT.NONE;
+	ToolBar chevronTb;
+	ToolItem chevronItem;
+	Image chevronImage;
+	int chevronCount;
+	boolean chevronVisible = true;
 	
 	Control topRight;
-	Rectangle topRightRect = new Rectangle(0, 0, 0, 0);
 	int topRightAlignment = SWT.RIGHT;
-	
-	Image topRightImage;
 	boolean ignoreResize;
-	ControlAdapter topRightResize = new ControlAdapter() {
-		public void controlResized(ControlEvent e) {
-			if (ignoreResize) return;
-			if (updateItems()) redraw();
-		}
-	};
+	Control[] controls;
+	int[] controlAlignments;
+	Rectangle[] controlRects;
+	Image[] controlBkImages;
 	
 	// when disposing CTabFolder, don't try to layout the items or 
 	// change the selection as each child is destroyed.
@@ -195,10 +194,8 @@
 	static final int FOREGROUND = SWT.COLOR_WIDGET_FOREGROUND;
 	static final int BACKGROUND = SWT.COLOR_WIDGET_BACKGROUND;
 	
-	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;
+	//TODO: add setter for spacing?
+	static final int SPACING = 3;
 	
 /**
  * Constructs a new instance of this class given its parent
@@ -251,6 +248,10 @@
 	selectionForeground = display.getSystemColor(SELECTION_FOREGROUND);
 	selectionBackground = display.getSystemColor(SELECTION_BACKGROUND);
 	renderer = new CTabFolderRenderer(this);
+	controls = new Control[0];
+	controlAlignments = new int[0];
+	controlRects = new Rectangle[0];
+	controlBkImages = new Image[0];
 	updateTabHeight(false);
 	
 	// Add all listeners
@@ -269,8 +270,9 @@
 				case SWT.MouseMove:        onMouse(event); break;
 				case SWT.MouseUp:          onMouse(event); break;
 				case SWT.Paint:            onPaint(event);	break;
-				case SWT.Resize:           onResize();	break;
+				case SWT.Resize:           onResize(event);	break;
 				case SWT.Traverse:         onTraverse(event); break;
+				case SWT.Selection:        onSelection(event); break;
 			}
 		}
 	};
@@ -422,6 +424,183 @@
 	addListener(SWT.DefaultSelection, typedListener);
 }
 
+Rectangle[] computeControlBounds (Point size, boolean[][] position) {
+	if (controls == null || controls.length == 0) return new Rectangle[0];
+	Rectangle[] rects = new Rectangle[controls.length];
+	for (int i = 0; i < rects.length; i++) {
+		rects[i] = new Rectangle(0, 0, 0, 0);
+	}
+	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;
+
+	Point[] tabControlSize = new Point[controls.length];
+	boolean[] overflow = new boolean [controls.length];
+	//Left Control
+	int leftWidth = 0;
+	int x = borderLeft + SPACING;
+	int rightWidth = 0;
+	int allWidth = 0;
+	for (int i = 0; i < controls.length; i++) {
+		Point ctrlSize = tabControlSize[i] = controls[i].getVisible() ? controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT) : new Point(0,0);
+		int alignment = controlAlignments[i];
+		if ((alignment & SWT.LEAD) != 0) {
+			rects[i].width = ctrlSize.x;
+			rects[i].height = Math.max(tabHeight - 1, ctrlSize.y);
+			rects[i].x = x;
+			rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+			x += ctrlSize.x;
+			leftWidth += ctrlSize.x;
+		} else {
+			if ((alignment & (SWT.FILL | SWT.WRAP)) == 0) {
+				rightWidth += ctrlSize.x;
+			}
+			allWidth += ctrlSize.x;
+		}
+	}
+	if (leftWidth > 0) leftWidth += SPACING * 2;
+
+	int itemWidth = 0;
+	for (int i = 0; i < items.length; i++) {
+		if (items[i].showing) itemWidth += items[i].width;
+	}
+	
+	int maxWidth = size.x - borderLeft - leftWidth - borderRight;
+	int availableWidth = Math.max(0, maxWidth - itemWidth - rightWidth);
+	if (rightWidth > 0) availableWidth -= SPACING * 2;
+	x =  size.x  - borderRight - SPACING;
+	if (itemWidth + allWidth <= maxWidth) {
+		//Everything fits
+		for (int i = 0; i < controls.length; i++) {
+			int alignment = controlAlignments[i];
+			if ((alignment & SWT.TRAIL) != 0) {
+				Point ctrlSize = tabControlSize[i];
+				x -= ctrlSize.x;
+				rects[i].width = ctrlSize.x;
+				rects[i].height = Math.min(tabHeight - 1, ctrlSize.y);
+				rects[i].x = x;
+				rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+				if ((alignment & (SWT.FILL | SWT.WRAP)) != 0) availableWidth -= ctrlSize.x; 
+			}
+		}
+	} else {
+		for (int i = 0; i < controls.length; i++) {
+			int alignment = controlAlignments[i];
+			Point ctrlSize = tabControlSize[i];
+			if ((alignment & SWT.TRAIL) != 0) { 
+				if ((alignment & (SWT.FILL | SWT.WRAP)) == 0) {
+					x -= ctrlSize.x;
+					rects[i].width = ctrlSize.x;
+					rects[i].height = Math.min(tabHeight - 1, ctrlSize.y);
+					rects[i].x = x;
+					rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+				} else if (((alignment & (SWT.WRAP)) != 0 && ctrlSize.x < availableWidth)) {
+					x -= ctrlSize.x;
+					rects[i].width = ctrlSize.x;
+					rects[i].height = Math.min(tabHeight - 1, ctrlSize.y);
+					rects[i].x = x;
+					rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+					availableWidth -= ctrlSize.x;
+				} else if ((alignment & (SWT.FILL)) != 0 && (alignment & (SWT.WRAP)) == 0) {
+					rects[i].width = 0;
+					rects[i].height = Math.min(tabHeight - 1, ctrlSize.y);
+					rects[i].x = x;
+					rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+				} else {
+					if ((alignment & (SWT.WRAP)) != 0) {
+						overflow[i] = true;
+					}
+				}
+			}
+		}
+	}
+	
+	//Any space, distribute amongst FILL
+	if (availableWidth > 0) {
+		int fillCount = 0;
+		for (int i = 0; i < controls.length; i++) {
+			int alignment = controlAlignments[i];
+			if ((alignment & SWT.TRAIL) != 0 && (alignment & SWT.FILL) != 0 && !overflow[i]) {
+				 fillCount++;
+			}
+		}
+		if (fillCount != 0) {
+			int extraSpace = availableWidth/fillCount;
+			int addedSpace = 0;
+			for (int i = 0; i < controls.length; i++) {
+				int alignment = controlAlignments[i];
+				if ((alignment & SWT.TRAIL) != 0) {
+					if ((alignment & SWT.FILL) != 0 && !overflow[i]) {
+						rects[i].width += extraSpace;
+						addedSpace += extraSpace;
+					}
+					if (!overflow[i]) {
+						rects[i].x -= addedSpace;
+					}
+				}
+			}
+		}
+	}
+	
+	//Go through overflow laying out all wrapped controls
+	Rectangle bodyTrim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+	int bodyRight = bodyTrim.width + bodyTrim.x;
+	int bodyLeft = -bodyTrim.x;
+	int bodyWidth = size.x - bodyLeft - bodyRight;
+	x = size.x - bodyRight;
+	int y = -bodyTrim.y;
+	availableWidth = bodyWidth;
+	int maxHeight = 0;
+	for (int i = 0; i < controls.length; i++) {
+		if (overflow[i]) {
+			Point ctrlSize = tabControlSize[i];
+			if (availableWidth > ctrlSize.x) {
+				x -= ctrlSize.x;
+				rects[i].width = ctrlSize.x;
+				rects[i].y = y;
+				rects[i].height = ctrlSize.y;
+				rects[i].x = x;
+				availableWidth -= ctrlSize.x;
+				maxHeight = Math.max(maxHeight, ctrlSize.y);
+			} else {
+				x = size.x - bodyRight;
+				y += maxHeight;
+				maxHeight = 0;
+				availableWidth = bodyWidth;
+				if (availableWidth > ctrlSize.x) { 
+					//Relayout this control in the next line
+					i--;
+				} else {
+					ctrlSize = controls[i].computeSize(bodyWidth, SWT.DEFAULT);
+					rects[i].width = bodyWidth;
+					rects[i].y = y;
+					rects[i].height = ctrlSize.y;
+					rects[i].x = size.x - ctrlSize.x - bodyRight;
+					y += ctrlSize.y;
+				}
+			}
+		}
+	}
+	
+	if (showChevron) {
+		int i = 0, lastIndex = -1;
+		while (i < priority.length && items[priority[i]].showing) {
+			lastIndex = Math.max(lastIndex, priority[i++]);
+		}
+		if (lastIndex == -1) lastIndex = firstIndex;
+		if (lastIndex != -1) {
+			CTabItem lastItem = items[lastIndex];
+			int w = lastItem.x + lastItem.width + SPACING;
+			if (!simple && lastIndex == selectedIndex) w -= renderer.curveIndent;
+			rects[controls.length - 1].x = w;
+		}
+	}
+	
+	if (position != null) position[0] = overflow;
+	return rects;
+}
 /*
 * This class was not intended to be subclassed but this restriction
 * cannot be enforced without breaking backward compatibility.
@@ -436,17 +615,39 @@
 public Rectangle computeTrim (int x, int y, int width, int height) {
 	checkWidget();
 	Rectangle trim =  renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, x, y, width, height);
-	if (topRight != null && topRightAlignment == (SWT.RIGHT | SWT.WRAP)) {
-		Rectangle bounds = topRight.getBounds();
-		if (bounds.y >= getTabHeight()) {
-			if (!onBottom) {
-				trim.y -= bounds.height;
-			}
-			trim.height += bounds.height;
-		}
+	Point size = new Point(width, height);
+	int wrapHeight = getWrappedHeight(size);
+	if (onBottom) {
+		trim.height += wrapHeight;
+	} else {
+		trim.y -= wrapHeight;
+		trim.height += wrapHeight;
 	}
 	return trim;
 }
+Image createButtonImage(Display display, int button) {
+	Point size = renderer.computeSize(button, SWT.NONE, null, SWT.DEFAULT, SWT.DEFAULT);
+	Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0);
+	Image image = new Image (display, size.x - trim.width, size.y - trim.height);
+	GC gc = new GC (image);
+	RGB transparent;
+	if (button == CTabFolderRenderer.PART_CHEVRON_BUTTON) {
+		transparent = new RGB(0xFF, 0xFF, 0xFF);
+	} else {
+		transparent = new RGB(0xFD, 0, 0);
+	}
+	Color transColor = new Color(display, transparent);
+	gc.setBackground(transColor);
+	gc.fillRectangle(image.getBounds());
+	renderer.draw(button, SWT.NONE, new Rectangle(trim.x, trim.y, size.x, size.y), gc);
+	gc.dispose ();
+	transColor.dispose();
+	ImageData imageData = image.getImageData();
+	imageData.transparentPixel = imageData.palette.getPixel(transparent);
+	image.dispose();
+	image = new Image(display, imageData);
+	return image;
+}
 void createItem (CTabItem item, int index) {
 	if (0 > index || index > getItemCount ())SWT.error (SWT.ERROR_INVALID_RANGE);
 	item.parent = this;
@@ -544,20 +745,48 @@
 	checkWidget();
 	return borderVisible;
 }
+ToolBar getChevron() {
+	if (chevronTb == null) {
+		chevronTb = new ToolBar(this, SWT.NONE);
+		addTabControl(chevronTb, SWT.TRAIL, -1, false);
+	}
+	if (chevronItem == null) {
+		chevronItem = new ToolItem(chevronTb, SWT.PUSH);
+		chevronItem.setToolTipText(SWT.getMessage("SWT_ShowList"));
+		chevronItem.addListener(SWT.Selection, listener);
+	}
+	return chevronTb;
+}
+/**
+ * Returns <code>true</code> if the chevron button
+ * is visible when necessary.
+ *
+ * @return the visibility of the chevron button
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 4.1
+ */
+public boolean getChevronVisible() {
+	checkWidget();
+	return chevronVisible;
+}
 public Rectangle getClientArea() {
 	checkWidget();
+	//TODO: HACK - find a better way to get padding
 	Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.FILL, 0, 0, 0, 0);
-	if (topRight != null && topRightAlignment == (SWT.RIGHT | SWT.WRAP)) {
-		Rectangle bounds = topRight.getBounds();
-		if (bounds.y >= getTabHeight()) { 
-			if (!onBottom) {
-				trim.y -= bounds.height;
-			}
-			trim.height += bounds.height;
-		}
+	Point size = getSize();
+	int wrapHeight = getWrappedHeight(size);
+	if (onBottom) {
+		trim.height += wrapHeight;
+	} else {
+		trim.y -= wrapHeight;
+		trim.height += wrapHeight;
 	}
 	if (minimized) return new Rectangle(-trim.x, -trim.y, 0, 0);
-	Point size = getSize();
 	int width = size.x - trim.width;
 	int height = size.y - trim.height;
 	return new Rectangle(-trim.x, -trim.y, width, height);
@@ -600,7 +829,6 @@
 	Point size = getSize();
 	Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, 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]];
 		Rectangle rect = item.getBounds();
@@ -638,7 +866,19 @@
 	System.arraycopy(items, 0, tabItems, 0, items.length);
 	return tabItems;
 }
-
+int getLeftItemEdge (GC gc, int part){
+	Rectangle trim = renderer.computeTrim(part, SWT.NONE, 0, 0, 0, 0);
+	int x = -trim.x; 
+	int width = 0;
+	for (int i = 0; i < controls.length; i++) {
+		if ((controlAlignments[i] & SWT.LEAD) != 0 && controls[i].getVisible()) {
+			width += controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).x;	
+		}
+	}
+	if (width != 0) width += SPACING * 2;
+	x += width;
+	return Math.max(0, x);
+}
 /*
  * Return the lowercase of the first non-'&' character following
  * an '&' character in the given string. If there are no '&'
@@ -803,14 +1043,17 @@
 }
 int getRightItemEdge (GC gc){
 	Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, 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, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (showMax) x -= renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (showChevron) x -= renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (topRight != null && topRightAlignment == SWT.RIGHT) {
-		Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT);
-		x -= rightSize.x + 3;
+	int x = getSize().x - (trim.width + trim.x);
+	int width = 0;
+	for (int i = 0; i < controls.length; i++) {
+		int align = controlAlignments[i];
+		if ((align & SWT.WRAP) == 0 && (align & SWT.LEAD) == 0 && controls[i].getVisible()) {
+			Point rightSize = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
+			width += rightSize.x;
+		}
 	}
+	if (width != 0) width += SPACING * 2;
+	x -= width;
 	return Math.max(0, x);
 }
 /**
@@ -941,14 +1184,6 @@
 	return onBottom ? SWT.BOTTOM : SWT.TOP;
 }
 /**
- * WARNING: Provisional API. This API is temporary and is not guaranteed to exist in
- * future releases.
- */
-public Control getTopControl (){
-	checkWidget ();
-	return topRight;
-}
-/**
  * Returns the control in the top right corner of the tab folder. 
  * Typically this is a close button or a composite with a menu and close button.
  *
@@ -1041,12 +1276,6 @@
 			int childID = e.childID;
 			if (childID >= 0 && childID < items.length) {
 				name = stripMnemonic(items[childID].getText());
-			} else if (childID == items.length + CHEVRON_CHILD_ID) {
-				name = SWT.getMessage("SWT_ShowList"); //$NON-NLS-1$
-			} else if (childID == items.length + MINIMIZE_CHILD_ID) {
-				name = minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$
-			} else if (childID == items.length + MAXIMIZE_CHILD_ID) {
-				name = maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$
 			}
 			e.result = name;
 		}
@@ -1089,18 +1318,10 @@
 				}
 			}
 			if (childID == ACC.CHILDID_NONE) {
-				if (showChevron && chevronRect.contains(testPoint)) {
-					childID = items.length + CHEVRON_CHILD_ID;
-				} else if (showMin && minRect.contains(testPoint)) {
-					childID = items.length + MINIMIZE_CHILD_ID;
-				} else if (showMax && maxRect.contains(testPoint)) {
-					childID = items.length + MAXIMIZE_CHILD_ID;
-				} else {
-					Rectangle location = getBounds();
-					location.height = location.height - getClientArea().height;
-					if (location.contains(testPoint)) {
-						childID = ACC.CHILDID_SELF;
-					}
+				Rectangle location = getBounds();
+				location.height = location.height - getClientArea().height;
+				if (location.contains(testPoint)) {
+					childID = ACC.CHILDID_SELF;
 				}
 			}
 			e.childID = childID;
@@ -1116,12 +1337,6 @@
 			} else {
 				if (childID >= 0 && childID < items.length && items[childID].isShowing()) {
 					location = items[childID].getBounds();
-				} else if (showChevron && childID == items.length + CHEVRON_CHILD_ID) {
-					location = chevronRect;
-				} else if (showMin && childID == items.length + MINIMIZE_CHILD_ID) {
-					location = minRect;
-				} else if (showMax && childID == items.length + MAXIMIZE_CHILD_ID) {
-					location = maxRect;
 				}
 				if (location != null) {
 					pt = toDisplay(location.x, location.y);
@@ -1136,7 +1351,7 @@
 		}
 		
 		public void getChildCount(AccessibleControlEvent e) {
-			e.detail = items.length + EXTRA_CHILD_ID_COUNT;
+			e.detail = items.length;
 		}
 		
 		public void getDefaultAction(AccessibleControlEvent e) {
@@ -1145,7 +1360,7 @@
 			if (childID >= 0 && childID < items.length) {
 				action = SWT.getMessage ("SWT_Switch"); //$NON-NLS-1$
 			}
-			if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) {
+			if (childID >= items.length && childID < items.length) {
 				action = SWT.getMessage ("SWT_Press"); //$NON-NLS-1$
 			}
 			e.result = action;
@@ -1170,7 +1385,7 @@
 				role = ACC.ROLE_TABFOLDER;
 			} else if (childID >= 0 && childID < items.length) {
 				role = ACC.ROLE_TABITEM;
-			} else if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) {
+			} else if (childID >= items.length && childID < items.length) {
 				role = ACC.ROLE_PUSHBUTTON;
 			}
 			e.detail = role;
@@ -1196,18 +1411,12 @@
 						state |= ACC.STATE_FOCUSED;
 					}
 				}
-			} else if (childID == items.length + CHEVRON_CHILD_ID) {
-				state = showChevron ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
-			} else if (childID == items.length + MINIMIZE_CHILD_ID) {
-				state = showMin ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
-			} else if (childID == items.length + MAXIMIZE_CHILD_ID) {
-				state = showMax ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
 			}
 			e.detail = state;
 		}
 		
 		public void getChildren(AccessibleControlEvent e) {
-			int childIdCount = items.length + EXTRA_CHILD_ID_COUNT;
+			int childIdCount = items.length;
 			Object[] children = new Object[childIdCount];
 			for (int i = 0; i < childIdCount; i++) {
 				children[i] = new Integer(i);
@@ -1264,6 +1473,8 @@
 					index = visible [current + offset];
 				} else {
 					if (showChevron) {
+						Rectangle chevronRect = chevronItem.getBounds();
+						chevronRect = event.display.map(chevronTb, this, chevronRect);
 						CTabFolderEvent e = new CTabFolderEvent(this);
 						e.widget = this;
 						e.time = event.time;
@@ -1318,27 +1529,37 @@
 	selectionBackground = null;
 	selectionForeground = null;
 	
-	if (topRight != null && !topRight.isDisposed())
-		topRight.removeControlListener(topRightResize);
+	if (controlBkImages != null) {
+		for (int i = 0; i < controlBkImages.length; i++) {
+			if (controlBkImages[i] != null) {
+				controlBkImages[i].dispose();
+				controlBkImages[i] = null;
+			}
+		}
+		controlBkImages = null;
+	}
+	controls = null;
+	controlAlignments = null;
+	controlRects = null;
 	
-	if (topRightImage != null) topRightImage.dispose();
-	topRightImage = null;
+	if (maxImage != null) maxImage.dispose();
+	maxImage = null;
+	
+	if (minImage != null) minImage.dispose();
+	minImage = null;
+	
+	if (chevronImage != null) chevronImage.dispose();
+	chevronImage = null;
 	
 	if (renderer != null) renderer.dispose();
 	renderer = null;
 }
 void onDragDetect(Event event) {
 	boolean consume = false;
-	if (chevronRect.contains(event.x, event.y) ||
-	    minRect.contains(event.x, event.y) ||
-		maxRect.contains(event.x, event.y)){
-		consume = true;
-	} else {
-		for (int i = 0; i < items.length; i++) {
-			if (items[i].closeRect.contains(event.x, event.y)) {
-					consume = true;
-					break;
-			}
+	for (int i = 0; i < items.length; i++) {
+		if (items[i].closeRect.contains(event.x, event.y)) {
+				consume = true;
+				break;
 		}
 	}
 	if (consume) {
@@ -1392,18 +1613,6 @@
 			break;
 		}
 		case SWT.MouseExit: {
-			if (minImageState != SWT.NONE) {
-				minImageState = SWT.NONE;
-				redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
-			}
-			if (maxImageState != SWT.NONE) {
-				maxImageState = SWT.NONE;
-				redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
-			}
-			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 != SWT.BACKGROUND) {
@@ -1423,28 +1632,6 @@
 		}
 		case SWT.MouseDown: {
 			if (event.button != 1) return;
-			if (minRect.contains(x, y)) {
-				minImageState = SWT.SELECTED;
-				redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
-				update();
-				return;
-			}
-			if (maxRect.contains(x, y)) {
-				maxImageState = SWT.SELECTED;
-				redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
-				update();
-				return;
-			}
-			if (chevronRect.contains(x, y)) {
-				if (chevronImageState != SWT.HOT) {
-					chevronImageState = SWT.HOT;
-				} else {
-					chevronImageState = SWT.SELECTED;
-				}
-				redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
-				update();
-				return;
-			}
 			CTabItem item = null;
 			if (single) {
 				if (selectedIndex != -1) {
@@ -1483,40 +1670,7 @@
 		}
 		case SWT.MouseMove: {
 			_setToolTipText(event.x, event.y);
-			boolean close = false, minimize = false, maximize = false, chevron = false;
-			if (minRect.contains(x, y)) {
-				minimize = true;
-				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 != 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 != SWT.SELECTED && chevronImageState != SWT.HOT) {
-					chevronImageState = SWT.HOT;
-					redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
-				}
-			}
-			if (minImageState != SWT.NONE && !minimize) {
-				minImageState = SWT.NONE;
-				redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
-			}
-			if (maxImageState != SWT.NONE && !maximize) {
-				maxImageState = SWT.NONE;
-				redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
-			}
-			if (chevronImageState != SWT.NONE && !chevron) {
-				chevronImageState = SWT.NONE;
-				redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
-			}
+			boolean close = false;
 			for (int i=0; i<items.length; i++) {
 				CTabItem item = items[i];
 				close = false;
@@ -1555,59 +1709,6 @@
 		}
 		case SWT.MouseUp: {
 			if (event.button != 1) return;
-			if (chevronRect.contains(x, y)) {
-				boolean selected = chevronImageState == SWT.SELECTED;
-				if (!selected) return;
-				CTabFolderEvent e = new CTabFolderEvent(this);
-				e.widget = this;
-				e.time = event.time;
-				e.x = chevronRect.x;
-				e.y = chevronRect.y;
-				e.width = chevronRect.width;
-				e.height = chevronRect.height;
-				e.doit = true;
-				for (int i = 0; i < folderListeners.length; i++) {
-					folderListeners[i].showList(e);
-				}
-				if (e.doit && !isDisposed()) {
-					showList(chevronRect);
-				}
-				return;
-			}
-			if (minRect.contains(x, y)) {
-				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);
-				e.widget = this;
-				e.time = event.time;
-				for (int i = 0; i < folderListeners.length; i++) {
-					if (minimized) {
-						folderListeners[i].restore(e);
-					} else {
-						folderListeners[i].minimize(e);
-					}
-				}
-				return;
-			}
-			if (maxRect.contains(x, y)) {
-				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);
-				e.widget = this;
-				e.time = event.time;
-				for (int i = 0; i < folderListeners.length; i++) {
-					if (maximized) {
-						folderListeners[i].restore(e);
-					} else {
-						folderListeners[i].maximize(e);
-					}
-				}
-				return;
-			}
 			CTabItem item = null;
 			if (single) {
 				if (selectedIndex != -1) {
@@ -1693,6 +1794,8 @@
 				index = visible [current + offset];
 			} else {
 				if (showChevron) {
+					Rectangle chevronRect = chevronItem.getBounds();
+					chevronRect = event.display.map(chevronTb, this, chevronRect);
 					CTabFolderEvent e = new CTabFolderEvent(this);
 					e.widget = this;
 					e.time = event.time;
@@ -1772,17 +1875,10 @@
 	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() {
+void onResize(Event event) {
+	if (ignoreResize) return;
 	if (updateItems()) redrawTabs();
 	
 	Point size = getSize();
@@ -1806,6 +1902,48 @@
 	}
 	oldSize = size;
 }
+void onSelection(Event event) {
+	if (event.widget == maxItem) {
+		CTabFolderEvent e = new CTabFolderEvent(this);
+		e.widget = CTabFolder.this;
+		e.time = event.time;
+		for (int i = 0; i < folderListeners.length; i++) {
+			if (maximized) {
+				folderListeners[i].restore(e);
+			} else {
+				folderListeners[i].maximize(e);
+			}
+		}
+	} else if (event.widget == minItem) {
+		CTabFolderEvent e = new CTabFolderEvent(this);
+		e.widget = CTabFolder.this;
+		e.time = event.time;
+		for (int i = 0; i < folderListeners.length; i++) {
+			if (minimized) {
+				folderListeners[i].restore(e);
+			} else {
+				folderListeners[i].minimize(e);
+			}
+		}
+	} else if (event.widget == chevronItem) {
+		Rectangle chevronRect = chevronItem.getBounds();
+		chevronRect = event.display.map(chevronTb, this, chevronRect);
+		CTabFolderEvent e = new CTabFolderEvent(this);
+		e.widget = this;
+		e.time = event.time;
+		e.x = chevronRect.x;
+		e.y = chevronRect.y;
+		e.width = chevronRect.width;
+		e.height = chevronRect.height;
+		e.doit = true;
+		for (int i = 0; i < folderListeners.length; i++) {
+			folderListeners[i].showList(e);
+		}
+		if (e.doit && !isDisposed()) {
+			showList(chevronRect);
+		}
+	}
+}
 void onTraverse (Event event) {
 	if (ignoreTraverse) return;
 	switch (event.detail) {
@@ -1964,7 +2102,7 @@
 public void setBackground (Color color) {
 	super.setBackground(color);
 	renderer.createAntialiasColors(); //TODO: need better caching strategy
-	updateTopRightBackground();
+	updateBkImages();
 	redraw();
 }
 /**
@@ -2118,205 +2256,85 @@
 }
 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;
-	oldWidth = maxRect.width;
-	oldHeight = maxRect.height;
-	maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0;
+	Display display = getDisplay();
 	if (showMax) {
-		Point maxSize = renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT);
-		maxRect.x = size.x - borderRight - maxSize.x - 3;
-		if (borderRight > 0) maxRect.x += 1;
-		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) {
-		int left = Math.min(oldX, maxRect.x);
-		int right = Math.max(oldX + oldWidth, maxRect.x + maxRect.width);
-		int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-		redraw(left, top, right - left, tabHeight, false); 
-	}
-
-	// min button
-	oldX = minRect.x;
-	oldY = minRect.y;
-	oldWidth = minRect.width;
-	oldHeight = minRect.height;
-	minRect.x = minRect.y = minRect.width = minRect.height = 0;
-	if (showMin) {
-		Point minSize = renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT);
-		minRect.x = size.x - borderRight - maxRect.width - minSize.x - 3;
-		if (borderRight > 0) minRect.x += 1;
-		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) {
-		int left = Math.min(oldX, minRect.x);
-		int right = Math.max(oldX + oldWidth, minRect.x + minRect.width);
-		int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-		redraw(left, top, right - left, tabHeight, false);
-	}
-	
-	// top right control
-	oldX = topRightRect.x;
-	oldY = topRightRect.y;
-	oldWidth = topRightRect.width;
-	oldHeight = topRightRect.height;
-	topRightRect.x = topRightRect.y = topRightRect.width = topRightRect.height = 0;
-	if (topRight != null) {
-		switch (topRightAlignment) {
-			case SWT.FILL: {
-				int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width;
-				if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2;
-				if (single) {
-					if (items.length == 0 || selectedIndex == -1) {
-						topRightRect.x = borderLeft + 3;
-						topRightRect.width = rightEdge - topRightRect.x;
-					} else {
-						// fill size is 0 if item compressed
-						CTabItem item = items[selectedIndex];
-						int chevronWidth = renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-						if (item.x + item.width + 7 + chevronWidth >= rightEdge) break;
-						topRightRect.x = item.x + item.width + 7 + chevronWidth;
-						topRightRect.width = rightEdge - topRightRect.x;
-					}
-				} else {
-					// fill size is 0 if chevron showing
-					if (showChevron) break;
-					if (items.length == 0) {
-						topRightRect.x = borderLeft + 3;
-					} else {
-						int lastIndex = items.length - 1;
-						CTabItem lastItem = items[lastIndex];
-						topRightRect.x = lastItem.x + lastItem.width;
-					}
-					topRightRect.width = Math.max(0, rightEdge - topRightRect.x);
-				}
-				topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-				topRightRect.height = tabHeight - 1;
-				break;
-			}
-			case SWT.RIGHT: {
-				Point topRightSize = topRight.computeSize(SWT.DEFAULT, tabHeight, false);
-				int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width;
-				if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2;
-				topRightRect.x = rightEdge - topRightSize.x;
-				topRightRect.width = topRightSize.x;
-				topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-				topRightRect.height = tabHeight - 1;
-				break;
-			}
-			case SWT.RIGHT | SWT.WRAP: {
-				Point topRightSize = topRight.computeSize(SWT.DEFAULT, tabHeight, false);
-				int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width;
-				if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2;
-				int leftEdge = 0;
-				if (items.length == 0) {
-					leftEdge = borderLeft + 3;
-				} else {
-					int lastIndex = items.length - 1;
-					CTabItem lastItem = items[lastIndex];
-					leftEdge = lastItem.x + lastItem.width;
-				}
-				
-				if (topRightSize.x <= rightEdge - leftEdge) {
-					topRightRect.x = rightEdge - topRightSize.x;
-					topRightRect.width = topRightSize.x;
-					topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-					topRightRect.height = tabHeight - 1;
-				} else {
-					Rectangle bodyTrim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
-					Point preferredSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT);
-					int bodyRight = bodyTrim.width + bodyTrim.x;
-					int bodyLeft = -bodyTrim.x;
-					int compWidth = size.x - bodyLeft - bodyRight;
-					if (compWidth > preferredSize.x) {
-						topRightRect.width = preferredSize.x;
-						topRightRect.y = -bodyTrim.y;
-						topRightRect.height = preferredSize.y;
-						topRightRect.x = size.x - preferredSize.x - bodyRight;
-					} else {
-						preferredSize = topRight.computeSize(compWidth, SWT.DEFAULT);
-						topRightRect.width = compWidth;
-						topRightRect.y = -bodyTrim.y;
-						topRightRect.height = preferredSize.y;
-						topRightRect.x = size.x - preferredSize.x - bodyRight;
-					}
-				}
-			}
+		if (minMaxTb == null) {
+			minMaxTb = new ToolBar(this, SWT.NONE);
+			addTabControl(minMaxTb, SWT.TRAIL, 0, false);
 		}
-		ignoreResize = true;
-		topRight.setBounds(topRightRect);
-		ignoreResize = false;
-	}
-	if (oldY != topRightRect.y || oldHeight != topRightRect.height) {	
-		updateTopRightBackground();
-	}
-	if (oldX != topRightRect.x || oldWidth != topRightRect.width ||
-		oldY != topRightRect.y || oldHeight != topRightRect.height) {	
-		int left = Math.min(oldX, topRightRect.x);
-		int right = Math.max(oldX + oldWidth, topRightRect.x + topRightRect.width);
-		int top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1;
-		redraw(left, top, right - left, tabHeight, false);
-	}
-	
-	// chevron button
-	oldX = chevronRect.x;
-	oldY = chevronRect.y;
-	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, SWT.DEFAULT, SWT.DEFAULT);
-	if (single) {
-		if (selectedIndex == -1 || items.length > 1) {
-			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;
-			} else {
-				CTabItem item = items[selectedIndex];
-				int w = size.x - borderRight - 3 - minRect.width - maxRect.width - chevronRect.width;
-				if (topRightRect.width > 0) w -= topRightRect.width + 3;
-				chevronRect.x = Math.min(item.x + item.width + 3, w);
+		if (maxItem == null) {
+			maxItem = new ToolItem(minMaxTb, SWT.PUSH);
+			if (maxImage == null) {
+				maxImage = createButtonImage(display, CTabFolderRenderer.PART_MAX_BUTTON);
 			}
-			if (borderRight > 0) chevronRect.x += 1;
+			maxItem.setImage(maxImage);
+			maxItem.setToolTipText(maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize")); //$NON-NLS-1$ //$NON-NLS-2$
+			maxItem.addListener(SWT.Selection, listener);
 		}
 	} else {
-		if (showChevron) {
-			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++]);
-			}
-			if (lastIndex == -1) lastIndex = firstIndex;
-			CTabItem lastItem = items[lastIndex];
-			int w = lastItem.x + lastItem.width + 3;
-			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;
+		//might need to remove it if already there
+		if (maxItem != null) {
+			maxItem.dispose();
+			maxItem = null;
 		}
 	}
-	if (oldX != chevronRect.x || oldWidth != chevronRect.width ||
-	    oldY != chevronRect.y || oldHeight != chevronRect.height) {
-		int left = Math.min(oldX, chevronRect.x);
-		int right = Math.max(oldX + oldWidth, chevronRect.x + chevronRect.width);
-		int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
-		redraw(left, top, right - left, tabHeight, false);
+	// min button
+	if (showMin) {
+		if (minMaxTb == null) {
+			minMaxTb = new ToolBar(this, SWT.NONE);
+			addTabControl(minMaxTb, SWT.TRAIL, 0, false);
+		}
+		if (minItem == null) {
+			minItem = new ToolItem(minMaxTb, SWT.PUSH, 0);
+			if (minImage == null) {
+				minImage = createButtonImage(display, CTabFolderRenderer.PART_MIN_BUTTON);
+			}
+			minItem.setImage(minImage);
+			minItem.setToolTipText(minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize")); //$NON-NLS-1$ //$NON-NLS-2$
+			minItem.addListener(SWT.Selection, listener);
+		}
+	} else {
+		//might need to remove it if already there
+		if (minItem != null) {
+			minItem.dispose();
+			minItem = null;
+		}
 	}
+	if (minMaxTb != null && minMaxTb.getItemCount() == 0) {
+		removeTabControl(minMaxTb);
+		minMaxTb.dispose();
+		minMaxTb = null;
+	}
+	if (showChevron) {
+		int itemCount = items.length;
+		int count;
+		if (single) {
+			count = selectedIndex == -1 ? itemCount : itemCount - 1;
+		} else {
+			int showCount = 0;
+			while (showCount < priority.length && items[priority[showCount]].showing) {
+				showCount++;
+			}
+			count = itemCount - showCount;
+		}
+		if (count != chevronCount) {
+			chevronCount = count;
+			if (chevronImage != null) chevronImage.dispose();
+			chevronImage = createButtonImage(display, CTabFolderRenderer.PART_CHEVRON_BUTTON);
+			chevronItem.setImage(chevronImage);
+		} 
+    }
+	Rectangle[] rects = computeControlBounds(size, null);
+	boolean changed = false;
+	ignoreResize = true;
+	for (int i = 0; i < controls.length; i++) {
+		controls[i].setBounds(rects[i]);
+		if (!changed && !rects[i].equals(controlRects[i])) changed = true;
+	}
+	ignoreResize = false;
+	controlRects = rects;
+	if (changed) updateBkImages();
 }
 public void setFont(Font font) {
 	checkWidget();
@@ -2376,12 +2394,12 @@
 	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, SWT.DEFAULT, SWT.DEFAULT);
+	int leftItemEdge = getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER);
 	if (single) {
 		int defaultX = getDisplay().getBounds().width + 10; // off screen
 		for (int i = 0; i < items.length; i++) {
@@ -2389,11 +2407,11 @@
 			if (i == selectedIndex) {
 				firstIndex = selectedIndex;
 				int oldX = item.x, oldY = item.y;
-				item.x = borderLeft;
+				item.x = leftItemEdge;
 				item.y = y;
 				item.showing = true;
 				if (showClose || item.showClose) {
-					item.closeRect.x = borderLeft - renderer.computeTrim(i, SWT.NONE, 0, 0, 0, 0).x;
+					item.closeRect.x = leftItemEdge - 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;
@@ -2404,14 +2422,14 @@
 		}
 	} else {
 		int rightItemEdge = getRightItemEdge(gc);
-		int maxWidth = rightItemEdge - borderLeft;
+		int maxWidth = rightItemEdge - leftItemEdge;
 		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;
 		}
-		int x = -renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0).x;
+		int x = getLeftItemEdge(gc, CTabFolderRenderer.PART_HEADER);
 		int defaultX = getDisplay().getBounds().width + 10; // off screen
 		firstIndex = items.length - 1;
 		for (int i = 0; i < items.length; i++) {
@@ -2477,18 +2495,18 @@
 	if (isDisposed()) return changed;
 	Point size = getSize();
 	if (size.x <= 0 || size.y <= 0) return changed;
-
-	Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
-	int borderRight = trim.width + trim.x;
-	int borderLeft = -trim.x;
-	
+	ToolBar chevron = getChevron();
+	if (chevron != null) chevron.setVisible(false);
 	showChevron = false;
 	if (single) {
-		showChevron = true;
+		showChevron = chevronVisible && items.length > 1;
+		if (showChevron) {
+			chevron.setVisible(true);
+		}
 		if (selectedIndex != -1) {
 			CTabItem tab = items[selectedIndex];
 			int width = renderer.computeSize(selectedIndex, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-			width = Math.min(width, getRightItemEdge(gc) - borderLeft);
+			width = Math.min(width, getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER));
 			if (tab.height != tabHeight || tab.width != width) {
 				changed = true;
 				tab.shortenedText = null;
@@ -2507,17 +2525,8 @@
 	}
 	
 	if (items.length == 0) return changed;
-
 	int[] widths;
-	int tabAreaWidth = size.x - borderLeft - borderRight - 3;
-	if (showMin) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (showMax) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (topRightAlignment == SWT.RIGHT && topRight != null) {
-		Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
-		tabAreaWidth -= rightSize.x + 3;
-	}
-	tabAreaWidth = Math.max(0, tabAreaWidth);
-
+	int tabAreaWidth = Math.max(0, getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER));
 	// First, try the minimum tab size at full compression.
 	int minWidth = 0;
 	int[] minWidths = new int[items.length];	
@@ -2531,8 +2540,11 @@
 	}
 	if (minWidth > tabAreaWidth) {
 		// full compression required and a chevron
-		showChevron = items.length > 1;
-		if (showChevron) tabAreaWidth -= renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+		showChevron = chevronVisible && items.length > 1;
+		if (showChevron) {
+			tabAreaWidth -= chevron.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+			chevron.setVisible(true);
+		}
 		widths = minWidths;
 		int index = selectedIndex != -1 ? selectedIndex : 0;
 		if (tabAreaWidth < widths[index]) {
@@ -2655,7 +2667,10 @@
 	if (this.maximized == maximize) return;
 	if (maximize && this.minimized) setMinimized(false);
 	this.maximized = maximize;
-	redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+	if (maxImage != null) maxImage.dispose();
+	maxImage = createButtonImage(getDisplay(), CTabFolderRenderer.PART_MAX_BUTTON);
+	maxItem.setImage(maxImage);
+	maxItem.setToolTipText(maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize")); //$NON-NLS-1$ //$NON-NLS-2$
 }
 /**
  * Marks the receiver's minimize button as visible if the argument is <code>true</code>,
@@ -2695,7 +2710,10 @@
 	if (this.minimized == minimize) return;
 	if (minimize && this.maximized) setMaximized(false);
 	this.minimized = minimize;
-	redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+	if (minImage != null) minImage.dispose();
+	minImage = createButtonImage(getDisplay(), CTabFolderRenderer.PART_MIN_BUTTON);
+	minItem.setImage(minImage);
+	minItem.setToolTipText(minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize")); //$NON-NLS-1$ //$NON-NLS-2$
 }
 
 /**
@@ -3148,6 +3166,11 @@
 		redraw();
 	}
 }
+
+int getControlY(Point size, Rectangle[] rects, int borderBottom, int borderTop, int i) {
+	return onBottom ? size.y - 1 - borderBottom - tabHeight + (tabHeight - rects[i].height)/2 : 1 + borderTop + (tabHeight - rects[i].height)/2;
+}
+
 /**
  * Specify a fixed height for the tab items.  If no height is specified,
  * the default height is the height of the text or the image, whichever 
@@ -3251,22 +3274,15 @@
 	if (control != null && control.getParent() != this) {
 		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
 	}
-	
-	if (topRight != null && !topRight.isDisposed()) {
-		topRight.removeControlListener(topRightResize);
-		topRight.setBackground (null);
-		topRight.setBackgroundImage (null);
-	}
-	
+	if (topRight == control && topRightAlignment == alignment) return;
+	if (topRight != null) removeTabControl(topRight, false);
 	topRight = control;
-
-	if (topRight != null)
-		topRight.addControlListener(topRightResize);
-	
 	topRightAlignment = alignment;
+	alignment &= ~SWT.RIGHT;
+	if (control != null) addTabControl(control, SWT.TRAIL | alignment, -1, false);
 	updateTabHeight(false);
 	if (updateItems()) redraw();
-	updateTopRightBackground();
+	updateBkImages();
 }
 
 
@@ -3427,9 +3443,7 @@
 		// make sure selected item will be showing
 		int firstIndex = showIndex;
 		if (priority[0] < showIndex) {
-			Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
-			int borderLeft = -trim.x;
-			int maxWidth = getRightItemEdge(gc) - borderLeft;
+			int maxWidth = getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER);
 			int width = 0;
 			int[] widths = new int[items.length];
 			for (int i = priority[0]; i <= showIndex; i++) {
@@ -3500,45 +3514,48 @@
 	GC gc = new GC(this);
 	tabHeight = renderer.computeSize(CTabFolderRenderer.PART_HEADER, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).y;
 	gc.dispose();
-	if (fixedTabHeight == SWT.DEFAULT && topRight != null) {
-		int topHeight = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
-		topHeight += renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0,0,0,0).height + 1;
-		tabHeight = Math.max(topHeight, tabHeight);
+	if (fixedTabHeight == SWT.DEFAULT && controls != null && controls.length > 0) {
+		for (int i = 0; i < controls.length; i++) {		
+			if ((controlAlignments[i] & SWT.WRAP) == 0 && controls[i].getVisible()) {
+				int topHeight = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+				topHeight += renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0,0,0,0).height + 1;
+				tabHeight = Math.max(topHeight, tabHeight);
+			}
+		}
 	}
 	if (!force && tabHeight == oldHeight) return false;
 	oldSize = null;
 	notifyListeners(SWT.Resize, new Event());
 	return true;
 }
-void updateTopRightBackground() {
-	if (topRightImage != null) {
-		topRightImage.dispose();
-		topRightImage = null;
-	}
-	if (topRight == null) return;
-	
-	Rectangle bounds = topRight.getBounds();
-	if (topRight instanceof Composite) ((Composite) topRight).setBackgroundMode(SWT.INHERIT_DEFAULT);
-	if (bounds.y > getTabHeight() || gradientColors == null) {
-		topRight.setBackgroundImage(null);
-		topRight.setBackground(getBackground());
-	} else {
-		bounds.width = 10;
-		bounds.y = -bounds.y;
-		bounds.height -= 2*bounds.y;
-		bounds.x = 0;
-		Image image = topRightImage = new Image(topRight.getDisplay(), bounds);
-		GC gc = new GC(image);
-		renderer.drawBackground(gc, bounds, 0);
-		gc.dispose();
-		topRight.setBackground(null);
-		topRight.setBackgroundImage(image);
+
+void updateBkImages() {
+	if (controls != null && controls.length > 0) {
+		for (int i = 0; i < controls.length; i++) {
+			Control control = controls[i];
+			if (control instanceof Composite) ((Composite) control).setBackgroundMode(SWT.INHERIT_DEFAULT);
+			Rectangle bounds = control.getBounds();
+			if (bounds.y > getTabHeight() || gradientColors == null) {
+				control.setBackgroundImage(null);
+				control.setBackground(getBackground());
+			} else {
+				bounds.width = 10;
+				bounds.y = -bounds.y;
+				bounds.height -= 2*bounds.y - 1;
+				bounds.x = 0;
+				if (controlBkImages[i] != null) controlBkImages[i].dispose();
+				controlBkImages[i] = new Image(control.getDisplay(), bounds);
+				GC gc = new GC(controlBkImages[i]);
+				renderer.drawBackground(gc, bounds, 0);
+				gc.dispose();
+				control.setBackground(null);
+				control.setBackgroundImage(controlBkImages[i]);
+			}
+		}
+		
 	}
 }
 String _getToolTip(int x, int y) {
-	if (showMin && minRect.contains(x, y)) return minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$
-	if (showMax && maxRect.contains(x, y)) return maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$
-	if (showChevron && chevronRect.contains(x, y)) return SWT.getMessage("SWT_ShowList"); //$NON-NLS-1$
 	CTabItem item = getItem(new Point (x, y));
 	if (item == null) return null;
 	if (!item.showing) return null;
@@ -3604,16 +3621,71 @@
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this CTabFolder</li>
 * </ul>
-* @since 3.7
+* @since 4.1
 */
 public void addTabControl(Control control, int flags) {
-	SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, "");
+	checkWidget();
+	addTabControl(control, flags, -1, true);
 }
 
-
+void addTabControl(Control control, int flags, int index, boolean update) {
+	switch (flags) {
+		case SWT.TRAIL:
+		case SWT.TRAIL | SWT.WRAP:
+		case SWT.TRAIL | SWT.FILL:
+		case SWT.TRAIL | SWT.FILL | SWT.WRAP:
+		case SWT.LEAD:
+			break;
+		default:
+			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+			break;
+	}
+	if (control != null && control.getParent() != this) {
+		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+	}
+	//check for duplicates
+	for (int i = 0; i < controls.length; i++) {
+		if (controls[i] == control) {
+			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+		}
+	}
+	int length = controls.length;
+	
+	control.addListener(SWT.Resize, listener);
+	
+	//Grow all 4 arrays
+	Control[] newControls = new Control [length + 1];
+	System.arraycopy(controls, 0, newControls, 0, length);
+	controls = newControls;
+	int[] newAlignment = new int [length + 1];
+	System.arraycopy(controlAlignments, 0, newAlignment, 0, length);
+	controlAlignments = newAlignment;
+	Rectangle[] newRect = new Rectangle [length + 1];
+	System.arraycopy(controlRects, 0, newRect, 0, length);
+	controlRects = newRect;
+	Image[] newImage = new Image [length + 1];
+	System.arraycopy(controlBkImages, 0, newImage, 0, length);
+	controlBkImages = newImage;
+	if (index == -1) {
+		index = length;
+		if (chevronTb != null && control != chevronTb) index--;
+	} 
+	System.arraycopy (controls, index, controls, index + 1, length - index);
+	System.arraycopy (controlAlignments, index, controlAlignments, index + 1, length - index);
+	System.arraycopy (controlRects, index, controlRects, index + 1, length - index);
+	System.arraycopy (controlBkImages, index, controlBkImages, index + 1, length - index);
+	controls[index] = control;
+	controlAlignments[index] = flags;
+	controlRects[index] = new Rectangle(0, 0, 0, 0);
+	if (update) {
+		updateTabHeight(false);
+		if (updateItems()) redraw();
+		updateBkImages();
+	}
+}
 
 /**
-* Removes the control from the list of tab controls
+* Removes the control from the list of tab controls.
 *
 * @param control the control to be removed
 * 
@@ -3622,12 +3694,65 @@
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this CTabFolder</li>
 * </ul>
-* @since 3.7
+* @since 4.1
 */
 public void removeTabControl (Control control) {
-	SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, "");
+	checkWidget();
+	removeTabControl (control, true);
 }
 
+void removeTabControl (Control control, boolean update) {
+	if (control != null && control.getParent() != this) {
+		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+	}
+	int index = -1;
+	for (int i = 0; i < controls.length; i++) {
+		if (controls[i] == control){
+			index = i;
+			break;
+		}
+	} 
+	if (index == -1) return;
+	
+	if (!control.isDisposed()) {
+		control.removeListener(SWT.Resize, listener);
+		control.setBackground (null);
+		control.setBackgroundImage (null);
+		if (control instanceof Composite) ((Composite) control).setBackgroundMode(SWT.INHERIT_NONE);
+	}
+	
+	if (controlBkImages[index] != null && !controlBkImages[index].isDisposed()) controlBkImages[index].dispose();
+	if (controls.length == 1) {
+		controls = new Control[0];
+		controlAlignments = new int[0];
+		controlRects = new Rectangle[0];
+		controlBkImages = new Image[0];
+	} else {
+		Control[] newControls = new Control [controls.length - 1];
+		System.arraycopy(controls, 0, newControls, 0, index);
+		System.arraycopy(controls, index + 1, newControls, index, controls.length - index - 1);
+		controls = newControls;
+		
+		int[] newAlignments = new int [controls.length];
+		System.arraycopy(controlAlignments, 0, newAlignments, 0, index);
+		System.arraycopy(controlAlignments, index + 1, newAlignments, index, controls.length - index);
+		controlAlignments = newAlignments;
+		
+		Rectangle[] newRects = new Rectangle [controls.length];
+		System.arraycopy(controlRects, 0, newRects, 0, index);
+		System.arraycopy(controlRects, index + 1, newRects, index, controls.length - index);
+		controlRects = newRects;
+		
+		Image[] newBkImages = new Image [controls.length];
+		System.arraycopy(controlBkImages, 0, newBkImages, 0, index);
+		System.arraycopy(controlBkImages, index + 1, newBkImages, index, controls.length - index);
+		controlBkImages = newBkImages;
+	}
+	if (update) {
+		updateItems();
+		redraw();
+	}
+}
 
 /**
  * Return the visible item for the specified flags.
@@ -3659,8 +3784,24 @@
 	return null;
 }
 
+int getWrappedHeight (Point size) {
+	boolean[][] positions = new boolean[1][];
+	GC gc = new GC(this);
+	Rectangle[] rects = computeControlBounds(size, positions);
+	gc.dispose();
+	int minY = Integer.MAX_VALUE, maxY = 0, wrapHeight = 0;
+	for (int i = 0; i < rects.length; i++) {
+		if (positions[0][i]) {
+			minY = Math.min(minY, rects[i].y);
+			maxY = Math.max(maxY, rects[i].y + rects[i].height);
+			wrapHeight = maxY - minY;
+		}
+	}
+	return wrapHeight;
+}
+
 /**
- * Show a chevron if there are more items to be displayed.
+ * Sets whether a chevron is shown when there are more items to be displayed.
  * 
  * @exception IllegalArgumentException <ul>
  *    <li>ERROR_INVALID_RANGE - if the index is out of range</li>
@@ -3670,9 +3811,13 @@
  *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
  * </ul>
  * 
- * @since 3.7
+ * @since 4.1
  */
 public void setChevronVisible(boolean visible) {
-	SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, "");
+	checkWidget();
+	if (chevronVisible == visible) return;
+	chevronVisible = visible;
+	updateItems();
+	redraw();
 }
 }
diff --git a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderLayout.java b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderLayout.java
index eb651c5..963847e 100644
--- a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderLayout.java
+++ b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderLayout.java
@@ -38,24 +38,44 @@
 			tabW += renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
 		}
 	}
-	tabW += 3;
 	
-	if (folder.showMax) tabW += renderer.computeSize(CTabFolderRenderer.PART_MAX_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (folder.showMin) tabW += renderer.computeSize(CTabFolderRenderer.PART_MIN_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	if (folder.single) tabW += renderer.computeSize(CTabFolderRenderer.PART_CHEVRON_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
-	int headerH = 0;
-	if (folder.topRight != null) {
-		Point pt = folder.topRight.computeSize(SWT.DEFAULT, folder.tabHeight, flushCache);
-		if (wHint == SWT.DEFAULT || folder.topRightAlignment != (SWT.RIGHT | SWT.WRAP)) {
-			tabW += 3 + pt.x;
-		} else {
-			if (wHint - tabW > pt.x) {
-				tabW += 3 + pt.x;
+	int width = 0, wrapHeight = 0;
+	boolean leftControl = false, rightControl = false;
+	if (wHint == SWT.DEFAULT) {
+		for (int i = 0; i < folder.controls.length; i++) {
+			Control control = folder.controls[i];
+			if (control.getVisible()) {
+				if ((folder.controlAlignments[i] & SWT.LEAD) != 0) {
+					leftControl = true;
+				} else {
+					rightControl = true;
+				}
+				width += control.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+			}
+		}
+	} else {
+		Point size = new Point (wHint, hHint);
+		boolean[][] positions = new boolean[1][];
+		Rectangle[] rects = folder.computeControlBounds(size, positions);
+		int minY = Integer.MAX_VALUE, maxY = 0;
+		for (int i = 0; i < rects.length; i++) {
+			if (positions[0][i]) {
+				minY = Math.min(minY, rects[i].y);
+				maxY = Math.max(maxY, rects[i].y + rects[i].height);
+				wrapHeight = maxY - minY;
 			} else {
-				headerH += pt.y;
+				if ((folder.controlAlignments[i] & SWT.LEAD) != 0) {
+					leftControl = true;
+				} else {
+					rightControl = true;
+				}
+				width += rects[i].width;
 			}
 		}
 	}
+	if (leftControl) width += CTabFolder.SPACING * 2;
+	if (rightControl) width += CTabFolder.SPACING * 2;
+	tabW += width;
 
 	gc.dispose();
 	
@@ -71,8 +91,8 @@
 		}
 	}
 
-	int minWidth = Math.max(tabW, controlW);
-	int minHeight = (folder.minimized) ? 0 : controlH + headerH;
+	int minWidth = Math.max(tabW, controlW + folder.marginWidth);
+	int minHeight = (folder.minimized) ? 0 : controlH + wrapHeight;
 	if (minWidth == 0) minWidth = CTabFolder.DEFAULT_WIDTH;
 	if (minHeight == 0) minHeight = CTabFolder.DEFAULT_HEIGHT;
 	
diff --git a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderRenderer.java b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderRenderer.java
index 1912381..0a5afea 100644
--- a/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderRenderer.java
+++ b/bundles/org.eclipse.e4.ui.widgets/src/org/eclipse/e4/ui/widgets/CTabFolderRenderer.java
@@ -80,7 +80,8 @@
 	
 	static final RGB CLOSE_FILL = new RGB(252, 160, 160);
 	
-	static final int BUTTON_SIZE = 18;
+	static final int BUTTON_SIZE = 16;
+	static final int BUTTON_TRIM = 1;
 	
 	static final int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW;
 	static final int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND;
@@ -350,6 +351,15 @@
 			case PART_HEADER:
 				//no trim 
 				break;
+			case PART_MAX_BUTTON:
+			case PART_MIN_BUTTON:
+			case PART_CLOSE_BUTTON:
+			case PART_CHEVRON_BUTTON:
+				x -= BUTTON_TRIM;
+				y -= BUTTON_TRIM;
+				width += BUTTON_TRIM*2;
+				height += BUTTON_TRIM*2;
+				break;
 			case PART_BORDER:
 				x = x - borderLeft;
 				width = width + borderLeft + borderRight; 
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java
index bb428b1..e66ae07 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java
@@ -343,7 +343,9 @@
 		int circX = bounds.x + radius;
 		int circY = bounds.y - 1 + radius;
 		int selectionX1, selectionY1, selectionX2, selectionY2;
-		if (itemIndex == 0) {
+		if (itemIndex == 0
+				&& bounds.x == -computeTrim(CTabFolderRenderer.PART_HEADER,
+						SWT.NONE, 0, 0, 0, 0).x) {
 			circX -= 1;
 			points[index++] = circX - radius;
 			points[index++] = bounds.y + bounds.height;