summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVeronika Irvine <veronika>2004-02-16 19:11:11 +0000
committerVeronika Irvine <veronika>2004-02-16 19:11:11 +0000
commitbbeab947327689cb203638e742e58f555e6c1b64 (patch)
tree07d655a590fec9396850bec7b79636dd73ea4415
parent2cef3fa78da7f2885ce55fa509348982e00b2225 (diff)
downloadeclipse.platform.swt-bbeab947327689cb203638e742e58f555e6c1b64.tar.gz
eclipse.platform.swt-bbeab947327689cb203638e742e58f555e6c1b64.tar.xz
eclipse.platform.swt-bbeab947327689cb203638e742e58f555e6c1b64.zip
Cut over to new look
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java3702
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabItem.java672
2 files changed, 2880 insertions, 1494 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 22b9bb1e66..4cd8ff51f3 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
@@ -10,12 +10,16 @@
*******************************************************************************/
package org.eclipse.swt.custom;
-
import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
-import org.eclipse.swt.accessibility.*;
+
+/**
+* UNDER CONSTRUCTION
+*/
/**
* Instances of this class implement the notebook user interface
@@ -32,7 +36,7 @@ import org.eclipse.swt.accessibility.*;
* </p><p>
* <dl>
* <dt><b>Styles:</b></dt>
- * <dd>TOP, BOTTOM, FLAT</dd>
+ * <dd>CLOSE, TOP, BOTTOM, FLAT, BORDER, SINGLE, MULTI</dd>
* <dt><b>Events:</b></dt>
* <dd>Selection</dd>
* <dd>"CTabFolder"</dd>
@@ -62,92 +66,138 @@ public class CTabFolder extends Composite {
*/
public int marginHeight = 0;
+ /**
+ * A multiple of the tab height that specifies the minimum width to which a tab
+ * will be compressed before scrolling arrows are used to navigate the tabs.
+ *
+ * NOTE This field is badly named for historical reasons. It is not static.
+ */
+ public int MIN_TAB_WIDTH = 3;
+
/**
* Color of innermost line of drop shadow border.
+ *
+ * @deprecated
*/
public static RGB borderInsideRGB = new RGB (132, 130, 132);
/**
* Color of middle line of drop shadow border.
+ *
+ * @deprecated
*/
public static RGB borderMiddleRGB = new RGB (143, 141, 138);
/**
* Color of outermost line of drop shadow border.
+ *
+ * @deprecated
*/
public static RGB borderOutsideRGB = new RGB (171, 168, 165);
-
- /*
- * A multiple of the tab height that specifies the minimum width to which a tab
- * will be compressed before scrolling arrows are used to navigate the tabs.
- */
- public int MIN_TAB_WIDTH = 3;
/* sizing, positioning */
int xClient, yClient;
boolean onBottom = false;
+ boolean single = false;
boolean fixedTabHeight;
int tabHeight;
/* item management */
- private CTabItem items[] = new CTabItem[0];
- private int selectedIndex = -1;
+ CTabItem items[] = new CTabItem[0];
+ int selectedIndex = -1;
int topTabIndex = -1; // index of the left most visible tab.
/* External Listener management */
- private CTabFolderListener[] tabListeners = new CTabFolderListener[0];
+ CTabFolderCloseListener[] closeListeners = new CTabFolderCloseListener[0];
+ CTabFolderMinMaxListener[] minmaxListeners = new CTabFolderMinMaxListener[0];
+ CTabFolderListListener[] listListeners = new CTabFolderListListener[0];
+
+ /* Selected item appearance */
+ Image selectionBgImage;
+ Color[] selectionGradientColors;
+ int[] selectionGradientPercents;
+ boolean selectionGradientVertical;
+ Color selectionForeground;
+ Color selectionBackground;
- /* Color appearance */
- Image backgroundImage;
+ /* Unselected item appearance */
+ Image bgImage;
Color[] gradientColors;
int[] gradientPercents;
- Color selectionForeground;
- Color background;
-
- // internal constants
- private static final int DEFAULT_WIDTH = 64;
- private static final int DEFAULT_HEIGHT = 64;
+ boolean gradientVertical;
- // scrolling arrows
- private ToolBar arrowBar;
- private Image arrowLeftImage;
- private Image arrowRightImage;
-
- private Control topRight;
-
- // close button
+ static Color borderColor;
+
+ // close, min/max and chevron buttons
boolean showClose = false;
- private Image closeImage;
- ToolBar closeBar;
- private ToolBar inactiveCloseBar;
- private CTabItem inactiveItem;
-
- // borders
- boolean showBorders = false;
- private int borderBottom = 0;
- private int borderLeft = 0;
- private int borderRight = 0;
- private int borderTop = 0;
- private Color borderColor1;
- private Color borderColor2;
- private Color borderColor3;
-
+
+ Rectangle chevronRect = new Rectangle(0, 0, 0, 0);
+ int chevronImageState = NORMAL;
+
+ boolean showMin = false;
+ Rectangle minRect = new Rectangle(0, 0, 0, 0);
+ boolean minimized = false;
+ int minImageState = NORMAL;
+
+ boolean showMax = false;
+ Rectangle maxRect = new Rectangle(0, 0, 0, 0);
+ boolean maximized = false;
+ int maxImageState = NORMAL;
+
+ Control topRight;
+ Rectangle topRightRect = new Rectangle(0, 0, 0, 0);
+
+ boolean tipShowing;
+
+ // borders and shapes
+ int borderLeft = 0;
+ int borderRight = 0;
+ int borderTop = 0;
+ int borderBottom = 0;
+ int[] curve;
+
// when disposing CTabFolder, don't try to layout the items or
// change the selection as each child is destroyed.
- private boolean inDispose = false;
+ boolean inDispose = false;
// keep track of size changes in order to redraw only affected area
// on Resize
- private Point oldSize;
- private Font oldFont;
+ Point oldSize;
+ Font oldFont;
// insertion marker
int insertionIndex = -2; // Index of insert marker. Marker always shown after index.
// -2 means no insert marker
-
- // tool tip
- private Shell tip;
- private Label label;
- private boolean showToolTip = false;
- private CTabItem toolTipItem;
+
+ // internal constants
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+ static final int HIGHLIGHT_HEADER = 5;
+ static final int HIGHLIGHT_MARGIN = 3;
+ static final int CURVE_WIDTH = 50;
+ static final int CURVE_RIGHT = 30;
+ static final int CURVE_LEFT = 30;
+ static final int BUTTON_SIZE = 16;
+ static final int[] TOP_LEFT_CORNER = new int[] {0,9, 1,8, 1,7, 2,6, 2,5, 3,4, 4,3, 5,2, 6,2, 7,1, 8,1, 9,0};
+ static final int[] TOP_RIGHT_CORNER = new int[] {-9,0, -8,1, -7,1, -6,2, -5,2, -4,3, -3,4, -2,5, -2,6, -1,7, -1,8, 0,9};
+ static final int[] BOTTOM_LEFT_CORNER = new int[] {0,-9, 1,-8, 1,-7, 2,-6, 2,-5, 3,-4, 4,-3, 5,-2, 6,-2, 7,-1, 8,-1, 9,0};
+ static final int[] BOTTOM_RIGHT_CORNER = new int[] {-9,0, -8,-1, -7,-1, -6,-2, -5,-2, -4,-3, -3,-4, -2,-5, -2,-6, -1,-7, -1,-8, 0,-9};
+
+ 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 NONE = 0;
+ static final int NORMAL = 1;
+ static final int HOT = 2;
+ static final int SELECTED = 3;
+ static final RGB CLOSE_BORDER = new RGB(221, 106, 106);
+ static final RGB CLOSE_FILL = new RGB(214, 195, 195);
+ static final RGB MINMAX_BORDER = new RGB(114, 106, 221);
+ static final RGB MINMAX_FILL = new RGB(199, 196, 242);
+ static final RGB CHEVRON_BORDER = new RGB(111, 220, 106);
+ static final RGB CHEVRON_FILL = new RGB(199, 242, 196);
+
/**
* Constructs a new instance of this class given its parent
@@ -175,107 +225,170 @@ public class CTabFolder extends Composite {
* @see SWT#TOP
* @see SWT#BOTTOM
* @see SWT#FLAT
- * @see #getStyle
+ * @see SWT#BORDER
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see #getStyle()
*/
public CTabFolder(Composite parent, int style) {
super(parent, checkStyle (style));
+ int style2 = super.getStyle();
+ onBottom = (style2 & SWT.BOTTOM) != 0;
+ showClose = (style2 & SWT.CLOSE) != 0;
+// 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;
+
+ //set up default colors
+ Display display = getDisplay();
+ selectionForeground = display.getSystemColor(SELECTION_FOREGROUND);
+ selectionBackground = display.getSystemColor(SELECTION_BACKGROUND);
+ borderColor = display.getSystemColor(BORDER1_COLOR);
+ setForeground(display.getSystemColor(FOREGROUND));
+ setBackground(display.getSystemColor(BACKGROUND));
- onBottom = (getStyle() & SWT.BOTTOM) != 0;
-
- borderColor1 = new Color(getDisplay(), borderInsideRGB);
- borderColor2 = new Color(getDisplay(), borderMiddleRGB);
- borderColor3 = new Color(getDisplay(), borderOutsideRGB);
-
- // tool tip support
- tip = new Shell (getShell(), SWT.ON_TOP);
- label = new Label (tip, SWT.CENTER);
+ initAccessible();
// Add all listeners
Listener listener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
- case SWT.Dispose: onDispose(); break;
- case SWT.Paint: onPaint(event); break;
- case SWT.Resize: onResize(); break;
- case SWT.MouseDoubleClick: onMouseDoubleClick(event); break;
- case SWT.MouseDown: onMouseDown(event); break;
- case SWT.MouseExit: onMouseExit(event); break;
- case SWT.MouseHover: onMouseHover(event); break;
- case SWT.MouseMove: onMouseMove(event); break;
- case SWT.FocusIn: onFocus(event); break;
- case SWT.FocusOut: onFocus(event); break;
- case SWT.KeyDown: onKeyDown(event); break;
- case SWT.Traverse: onTraverse(event); break;
+ case SWT.Dispose: onDispose(); break;
+ case SWT.FocusIn: onFocus(event); break;
+ case SWT.FocusOut: onFocus(event); break;
+ case SWT.MenuDetect: onMenu(event); break;
+ case SWT.MouseDoubleClick: onMouseDoubleClick(event); break;
+ case SWT.MouseDown: onMouse(event); break;
+ case SWT.MouseExit: onMouse(event); break;
+ case SWT.MouseHover: onMouseHover(event); break;
+ 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.Traverse: onTraverse(event); break;
}
}
};
int[] folderEvents = new int[]{
SWT.Dispose,
- SWT.Paint,
- SWT.Resize,
+ SWT.FocusIn,
+ SWT.FocusOut,
+ SWT.KeyDown,
+ SWT.MenuDetect,
SWT.MouseDoubleClick,
- SWT.MouseDown,
+ SWT.MouseDown,
SWT.MouseExit,
SWT.MouseHover,
SWT.MouseMove,
- SWT.FocusIn,
- SWT.FocusOut,
- SWT.KeyDown,
+ SWT.MouseUp,
+ SWT.Paint,
+ SWT.Resize,
SWT.Traverse,
};
for (int i = 0; i < folderEvents.length; i++) {
addListener(folderEvents[i], listener);
}
-
- createArrowBar();
- createCloseBar();
-
- setBorderVisible((style & SWT.BORDER) != 0);
-
- initAccessible();
-
}
-private static int checkStyle (int style) {
- int mask = SWT.TOP | SWT.BOTTOM | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+static int[] bezier(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) {
+ // The parametric equations for a Bezier curve for x[t] and y[t] where 0 <= t <=1 are:
+ // x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^3+(x3-x0+3x1-3x2)t^3
+ // y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3
+ double a0 = x0;
+ double a1 = 3*(x1 - x0);
+ double a2 = 3*(x0 + x2 - 2*x1);
+ double a3 = x3 - x0 + 3*x1 - 3*x2;
+ double b0 = y0;
+ double b1 = 3*(y1 - y0);
+ double b2 = 3*(y0 + y2 - 2*y1);
+ double b3 = y3 - y0 + 3*y1 - 3*y2;
+
+ int[] polygon = new int[2*count + 2];
+ for (int i = 0; i <= count; i++) {
+ double t = (double)i / (double)count;
+ polygon[2*i] = (int)(a0 + a1*t + a2*t*t + a3*t*t*t);
+ polygon[2*i + 1] = (int)(b0 + b1*t + b2*t*t + b3*t*t*t);
+ }
+ return polygon;
+}
+static int checkStyle (int style) {
+ int mask = SWT.CLOSE | SWT.TOP | SWT.BOTTOM | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.SINGLE | SWT.MULTI;
style = style & mask;
// TOP and BOTTOM are mutually exlusive.
// TOP is the default
if ((style & SWT.TOP) != 0)
style = style & ~(SWT.TOP | SWT.BOTTOM) | SWT.TOP;
+ // SINGLE and MULTI are mutually exlusive.
+ // MULTI is the default
+ if ((style & SWT.MULTI) != 0)
+ style = style & ~(SWT.SINGLE | SWT.MULTI) | SWT.MULTI;
// reduce the flash by not redrawing the entire area on a Resize event
- style |= SWT.NO_REDRAW_RESIZE;
+ style |= SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND;
return style;
}
-
-//protected void checkSubclass () {
-// String name = getClass().getName ();
-// String validName = CTabFolder.class.getName();
-// if (!validName.equals(name)) {
-// SWT.error (SWT.ERROR_INVALID_SUBCLASS);
-// }
-//}
-
-/**
-* Adds the listener to receive events.
-* <p>
-*
-* @param listener the listener
-*
-* @exception SWTError <ul>
-* <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
-* <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
-* <li>ERROR_NULL_ARGUMENT when listener is null</li>
-* </ul>
-*/
-public void addSelectionListener(SelectionListener listener) {
+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
+ * be notified when a tab item is closed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ *
+ * @see CTabFolderCloseListener
+ * @see #removeCTabFolderCloseListener(CTabFolderCloseListener)
+ *
+ * @since 3.0
+ */
+public void addCTabFolderCloseListener(CTabFolderCloseListener listener) {
checkWidget();
- if (listener == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- TypedListener typedListener = new TypedListener(listener);
- addListener(SWT.Selection, typedListener);
- addListener(SWT.DefaultSelection, typedListener);
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ // add to array
+ CTabFolderCloseListener[] newListeners = new CTabFolderCloseListener[closeListeners.length + 1];
+ System.arraycopy(closeListeners, 0, newListeners, 0, closeListeners.length);
+ closeListeners = newListeners;
+ closeListeners[closeListeners.length - 1] = listener;
+}
+/**
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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.0
+ */
+public void addCTabFolderMinMaxListener(CTabFolderMinMaxListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ // add to array
+ CTabFolderMinMaxListener[] newListeners = new CTabFolderMinMaxListener[minmaxListeners.length + 1];
+ System.arraycopy(minmaxListeners, 0, newListeners, 0, minmaxListeners.length);
+ minmaxListeners = newListeners;
+ minmaxListeners[minmaxListeners.length - 1] = listener;
}
/**
* Adds the listener to the collection of listeners who will
@@ -284,51 +397,149 @@ public void addSelectionListener(SelectionListener listener) {
* @param listener the listener which should be notified
*
* @exception IllegalArgumentException <ul>
- * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
- * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
- * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
*
* @see CTabFolderListener
- * @see #removeCTabFolderListener
+ * @see #removeCTabFolderListener(CTabFolderListener)
+ *
+ * @deprecated use addCTabFolderCloseListener
*/
public void addCTabFolderListener(CTabFolderListener listener) {
+ addCTabFolderCloseListener(listener);
+ if (closeListeners.length == 1) {
+ // display close button
+ showClose = true;
+ updateItems();
+ redraw();
+ }
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when a the selection list is displayed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ *
+ * @see CTabFolderListListener
+ * @see #removeCTabFolderListListener(CTabFolderListListener)
+ *
+ * @since 3.0
+ */
+public void addCTabFolderListListener(CTabFolderListListener listener) {
checkWidget();
if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
// add to array
- CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length + 1];
- System.arraycopy(tabListeners, 0, newTabListeners, 0, tabListeners.length);
- tabListeners = newTabListeners;
- tabListeners[tabListeners.length - 1] = listener;
- showClose = true;
- setButtonBounds();
+ CTabFolderListListener[] newListeners = new CTabFolderListListener[listListeners.length + 1];
+ System.arraycopy(listListeners, 0, newListeners, 0, listListeners.length);
+ listListeners = newListeners;
+ listListeners[listListeners.length - 1] = listener;
}
-private void closeNotify(CTabItem item, int time) {
- if (item == null) return;
-
- CTabFolderEvent event = new CTabFolderEvent(this);
- event.widget = this;
- event.time = time;
- event.item = item;
- event.doit = true;
- if (tabListeners != null) {
- for (int i = 0; i < tabListeners.length; i++) {
- tabListeners[i].itemClosed(event);
- }
+/**
+ * Adds the listener to receive events.
+ * <p>
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
- if (event.doit) {
- item.dispose();
+ TypedListener typedListener = new TypedListener(listener);
+ addListener(SWT.Selection, typedListener);
+ addListener(SWT.DefaultSelection, typedListener);
+}
+void antialias (int[] shape, RGB lineRGB, RGB innerRGB, RGB outerRGB, GC gc){
+ //don't perform anti-aliasing on Mac because the platform
+ // already does it.
+ if ("carbon".equals(SWT.getPlatform())) return;
+ if (outerRGB != 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++];
+ }
+ RGB from = lineRGB;
+ RGB to = outerRGB;
+ int red = from.red + 4*(to.red - from.red)/5;
+ int green = from.green + 4*(to.green - from.green)/5;
+ int blue = from.blue + 4*(to.blue - from.blue)/5;
+ Color color = new Color(getDisplay(), red, green, blue);
+ gc.setForeground(color);
+ gc.drawPolyline(outer);
+ color.dispose();
+ }
+ if (innerRGB != 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++];
+ }
+ RGB from = lineRGB;
+ RGB to = innerRGB;
+ int red = from.red + 4*(to.red - from.red)/5;
+ int green = from.green + 4*(to.green - from.green)/5;
+ int blue = from.blue + 4*(to.blue - from.blue)/5;
+ Color color = new Color(getDisplay(), red, green, blue);
+ gc.setForeground(color);
+ gc.drawPolyline(inner);
+ color.dispose();
}
}
public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget();
int minWidth = 0;
int minHeight = 0;
-
// preferred width of tab area to show all tabs
GC gc = new GC(this);
+ int selectedMax = 0;
+ int selectedMaxIndex = -1;
for (int i = 0; i < items.length; i++) {
- minWidth += items[i].preferredWidth(gc);
+ int width = items[i].preferredWidth(gc, true);
+ if ( width > selectedMax) {
+ selectedMax = width;
+ selectedMaxIndex = i;
+ }
+ }
+ for (int i = 0; i < items.length; i++) {
+ minWidth += items[i].preferredWidth(gc, i == selectedMaxIndex);
}
gc.dispose();
@@ -341,9 +552,12 @@ public Point computeSize (int wHint, int hHint, boolean changed) {
minHeight = Math.max (minHeight, size.y);
}
}
+
if (minWidth == 0) minWidth = DEFAULT_WIDTH;
if (minHeight == 0) minHeight = DEFAULT_HEIGHT;
+ if (minimized) minHeight = 0;
+
if (wHint != SWT.DEFAULT) minWidth = wHint;
if (hHint != SWT.DEFAULT) minHeight = hHint;
@@ -352,28 +566,26 @@ public Point computeSize (int wHint, int hHint, boolean changed) {
}
public Rectangle computeTrim (int x, int y, int width, int height) {
checkWidget();
- if (items.length == 0) {
- if (!showBorders) return new Rectangle(x, y, width, height);
- int trimX = x - borderRight - 1;
- int trimY = y - borderBottom - 1;
- int trimWidth = width + borderRight + 2;
- int trimHeight = height + borderBottom + 2;
+ if (minimized) {
+ int trimX = x - borderLeft;
+ int trimY = onBottom ? y - borderTop : y - HIGHLIGHT_HEADER - tabHeight - borderTop;
+ int trimWidth = width + borderLeft + borderRight;
+ int trimHeight = borderTop + borderBottom + tabHeight + HIGHLIGHT_HEADER;
return new Rectangle (trimX, trimY, trimWidth, trimHeight);
} else {
+ int style = getStyle();
+ boolean highlight = (style & SWT.BORDER) != 0 && (style & SWT.FLAT) == 0;
int trimX = x - marginWidth - borderLeft;
- int trimY = y - marginHeight - tabHeight - borderTop - 1;
- // -1 is for the line at the bottom of the tabs
- if (onBottom) {
- trimY = y - marginHeight - borderTop;
- }
+ if (highlight) trimX -= HIGHLIGHT_MARGIN;
+ int trimY = onBottom ? y - marginHeight - borderTop : y - marginHeight - HIGHLIGHT_HEADER - tabHeight - borderTop;
+ if (highlight && onBottom) trimX -= HIGHLIGHT_MARGIN;
int trimWidth = width + borderLeft + borderRight + 2*marginWidth;
- int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + 1;
+ if (highlight) trimWidth += 2*HIGHLIGHT_MARGIN;
+ int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + HIGHLIGHT_HEADER;
+ if (highlight) trimHeight += HIGHLIGHT_HEADER + HIGHLIGHT_MARGIN;
return new Rectangle (trimX, trimY, trimWidth, trimHeight);
}
}
-/**
- * Create the specified item at 'index'.
- */
void createItem (CTabItem item, int index) {
if (0 > index || index > getItemCount ()){
SWT.error (SWT.ERROR_INVALID_RANGE);
@@ -392,89 +604,21 @@ void createItem (CTabItem item, int index) {
}
if (items.length == 1) {
topTabIndex = 0;
- resetTabSize(true);
- } else {
- setItemBounds();
- showItem(item);
- }
-
- if (items.length == 1) {
+ if (!updateTabHeight(tabHeight, false)) updateItems();
redraw();
} else {
- redrawTabArea(-1);
- }
-}
-
-private void createArrowBar() {
- // create arrow buttons for scrolling
- arrowBar = new ToolBar(this, SWT.FLAT);
- arrowBar.setVisible(false);
- arrowBar.setBackground(background);
- ToolItem scrollLeft = new ToolItem(arrowBar, SWT.PUSH);
- scrollLeft.setEnabled(false);
- ToolItem scrollRight = new ToolItem(arrowBar, SWT.PUSH);
- scrollRight.setEnabled(false);
-
- scrollLeft.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- scroll_scrollLeft();
- }
- });
- scrollRight.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- scroll_scrollRight();
+ updateItems();
+ // redraw tabs if new item visible
+ if (index == topTabIndex ||
+ (index > topTabIndex && item.x + item.width < getRightItemEdge())){
+ redraw();
}
- });
-
-}
-private void createCloseBar() {
- closeBar = new ToolBar(this, SWT.FLAT);
- closeBar.setVisible(false);
- if (gradientColors != null && gradientColors.length > 0) {
- closeBar.setBackground(gradientColors[gradientColors.length - 1]);
- } else {
- closeBar.setBackground(background);
}
- ToolItem closeItem = new ToolItem(closeBar, SWT.PUSH);
-
- inactiveCloseBar = new ToolBar(this, SWT.FLAT);
- inactiveCloseBar.setVisible(false);
- inactiveCloseBar.setBackground(background);
- ToolItem inactiveCloseItem = new ToolItem(inactiveCloseBar, SWT.PUSH);
-
- closeItem.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- closeNotify(getSelection(), event.time);
- }
- });
- inactiveCloseItem.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- closeNotify(inactiveItem, event.time);
- inactiveCloseBar.setVisible(false);
- inactiveItem = null;
- }
- });
- inactiveCloseBar.addListener (SWT.MouseExit, new Listener() {
- public void handleEvent(Event event) {
- if (inactiveItem != null) {
- Rectangle itemBounds = inactiveItem.getBounds();
- if (itemBounds.contains(event.x, event.y)) return;
- }
- inactiveCloseBar.setVisible(false);
- inactiveItem = null;
- }
- });
-
}
-/**
- * Destroy the specified item.
- */
void destroyItem (CTabItem item) {
if (inDispose) return;
-
int index = indexOf(item);
- if (index == -1) return; // should this trigger an error?
-
+ if (index == -1) return;
insertionIndex = -2;
if (items.length == 1) {
@@ -486,7 +630,6 @@ void destroyItem (CTabItem item) {
if (control != null && !control.isDisposed()) {
control.setVisible(false);
}
- closeBar.setVisible(false);
if (!fixedTabHeight) tabHeight = 0;
redraw();
return;
@@ -504,9 +647,9 @@ void destroyItem (CTabItem item) {
// move the selection if this item is selected
if (selectedIndex == index) {
+ Control control = item.getControl();
selectedIndex = -1;
setSelection(Math.max(0, index - 1), true);
- Control control = item.getControl();
if (control != null && !control.isDisposed()) {
control.setVisible(false);
}
@@ -514,154 +657,614 @@ void destroyItem (CTabItem item) {
selectedIndex --;
}
- setItemBounds();
- redrawTabArea(-1);
+ if (updateItems()) redraw();
}
-private void onKeyDown(Event e) {
- if (e.keyCode != SWT.ARROW_LEFT && e.keyCode != SWT.ARROW_RIGHT) return;
- int leadKey = (getStyle() & SWT.MIRRORED) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
- if (e.keyCode == leadKey) {
- if (selectedIndex > 0) {
- setSelection(selectedIndex - 1, true);
+void drawBackground(GC gc, int[] shape, boolean selected) {
+ Point size = getSize();
+ int height = tabHeight + HIGHLIGHT_HEADER;
+ int y = onBottom ? size.y - borderBottom - height : borderTop;
+ int x = 0;
+ int width = size.x;
+ if (borderLeft > 0) {
+ x += 1; width -= 2;
+ }
+
+ Region clipping = new Region();
+ gc.getClipping(clipping);
+ Region region = new Region();
+ region.add(shape);
+ gc.setClipping(region);
+
+ Color defaultBackground = selected ? selectionBackground : getBackground();
+ Image image = selected ? selectionBgImage : bgImage;
+ Color[] colors = selected ? selectionGradientColors : gradientColors;
+ boolean vertical = selected ? selectionGradientVertical : gradientVertical;
+ int[] percents = selected ? selectionGradientPercents : gradientPercents;
+
+ 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 = 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 gradientHeight = percents[i] * 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 gradientHeight = percents[i] * 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);
+ }
+ }
+ } else { //horizontal gradient
+ 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 {
- if (selectedIndex < items.length - 1) {
- setSelection(selectedIndex + 1, true);
- }
+ // draw a solid background using default background in shape
+ gc.setBackground(defaultBackground);
+ gc.fillRectangle(x, y, width, height);
}
+ gc.setClipping(clipping);
+ clipping.dispose();
+ region.dispose();
}
-/**
- * Dispose the items of the receiver
- */
-private void onDispose() {
- /*
- * Usually when an item is disposed, destroyItem will change the size of the items array,
- * reset the bounds of all the tabs and manage the widget associated with the tab.
- * Since the whole folder is being disposed, this is not necessary. For speed
- * the inDispose flag is used to skip over this part of the item dispose.
- */
- inDispose = true;
+void drawBody(Event event) {
+ GC gc = event.gc;
+ Point size = getSize();
- int length = items.length;
- for (int i = 0; i < length; i++) {
- if (items[i] != null) {
- items[i].dispose();
+ //draw 1 pixel border around outside
+ if (borderLeft > 0) {
+ gc.setForeground(borderColor);
+ 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
}
}
- // clean up resources
- if (tip != null && !tip.isDisposed()) {
- tip.dispose();
- tip = null;
- label = null;
+ // fill in client area
+ if (!minimized){
+ int style = getStyle();
+ int width = size.x - borderLeft - borderRight;
+ int height = size.y - borderTop - borderBottom - tabHeight - HIGHLIGHT_HEADER;
+ int x = xClient - marginWidth;
+ int y = yClient - marginHeight;
+ if (borderLeft > 0 && (style & SWT.FLAT) == 0) {
+ width -= 2*HIGHLIGHT_MARGIN;
+ height -= HIGHLIGHT_MARGIN;
+ if (onBottom) {
+ int x1 = 1;
+ int x2 = size.x - 1;
+ int y1 = size.y - borderBottom - tabHeight - HIGHLIGHT_HEADER;
+ gc.setForeground(selectedIndex == -1 ? getBackground() : selectionBackground);
+ for (int i = 0; i < HIGHLIGHT_MARGIN; i++) {
+ gc.drawPolyline(new int[] {x1+i, y1-1, x1+i, 1+i, x2-1-i, 1+i, x2-1-i, y1});
+ }
+ } else {
+ int x1 = 1;
+ int x2 = size.x - 1;
+ int y2 = borderTop + tabHeight + HIGHLIGHT_HEADER;
+ gc.setForeground(selectedIndex == -1 ? getBackground() : selectionBackground);
+ for (int i = 0; i < HIGHLIGHT_MARGIN; i++) {
+ gc.drawPolyline(new int[] {x1+i, y2, x1+i, size.y-2-i, x2-1-i, size.y-2-i, x2-1-i, y2-1});
+ }
+ }
+ }
+ gc.setBackground(getBackground());
+ gc.fillRectangle(x, y, width, height);
}
-
- if (arrowLeftImage != null) arrowLeftImage.dispose();
- arrowLeftImage = null;
- if (arrowRightImage != null) arrowRightImage.dispose();
- arrowRightImage = null;
- if (closeImage != null) closeImage.dispose();
- closeImage = null;
-
- gradientColors = null;
- gradientPercents = null;
- backgroundImage = null;
+}
- if (borderColor1 != null) borderColor1.dispose();
- borderColor1 = null;
-
- if (borderColor2 != null) borderColor2.dispose();
- borderColor2 = null;
-
- if (borderColor3 != null) borderColor3.dispose();
- borderColor3 = null;
+void drawChevron(GC gc) {
+ if (chevronRect.width == 0 || chevronRect.height == 0) return;
+ Display display = getDisplay();
+ // draw chevron (10x7)
+ int indent = Math.max(1, (tabHeight-11)/2);
+ int x = chevronRect.x + indent - 1;
+ int y = chevronRect.y + indent;
+ switch (chevronImageState) {
+ case NORMAL: {
+ int[] shape = onBottom ? new int[]{x,y+9, x+9,y+9, x+9,y+7, x+5,y+3, x+4,y+3, x,y+7, x,y+9} : new int[]{x,y, x+9,y, x+9,y+2, x+5,y+6, x+4,y+6, x,y+2, x,y};
+ gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.fillPolygon(shape);
+ gc.setForeground(borderColor);
+ gc.drawPolygon(shape);
+ break;
+ }
+ case HOT: {
+ int[] shape = onBottom ? new int[]{x,y+9, x+9,y+9, x+9,y+7, x+5,y+3, x+4,y+3, x,y+7, x,y+9} : new int[] {x,y, x+9,y, x+9,y+2, x+5,y+6, x+4,y+6, x,y+2, x,y};
+ gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.fillPolygon(shape);
+ Color border = new Color(display, CHEVRON_BORDER);
+ gc.setForeground(border);
+ gc.drawPolygon(shape);
+ border.dispose();
+ break;
+ }
+ case SELECTED: {
+ int[] shape = onBottom ? new int[]{x+1,y+10, x+10,y+10, x+10,y+8, x+6,y+4, x+5,y+4, x+1,y+8, x+1,y+10} : new int[] {x+1,y+1, x+10,y+1, x+10,y+3, x+6,y+7, x+5,y+7, x+1,y+3, x+1,y+1};
+ Color fill = new Color(display, CHEVRON_FILL);
+ gc.setBackground(fill);
+ gc.fillPolygon(shape);
+ fill.dispose();
+ Color border = new Color(display, CHEVRON_BORDER);
+ gc.setForeground(border);
+ gc.drawPolygon(shape);
+ border.dispose();
+ break;
+ }
+ }
}
-private void onFocus(Event e) {
- checkWidget();
- if (selectedIndex >= 0) {
- redrawTabArea(selectedIndex);
- } else {
- setSelection(0, true);
+void drawMaximize(GC gc) {
+ if (maxRect.width == 0 || maxRect.height == 0) return;
+ Display display = getDisplay();
+ int indent = Math.max(1, (tabHeight-11)/2);
+ int x = maxRect.x + indent - 1;
+ int y = maxRect.y + indent;
+ switch (maxImageState) {
+ case NORMAL: {
+ if (!maximized) {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y, 7, 9);
+ gc.setForeground(borderColor);
+ gc.drawRectangle(x, y, 7, 9);
+ gc.drawLine(x+1, y+2, x+6, y+2);
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.setForeground(borderColor);
+ 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: {
+ Color border = new Color(display, MINMAX_BORDER);
+ if (!maximized) {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y, 7, 9);
+ gc.setForeground(border);
+ gc.drawRectangle(x, y, 7, 9);
+ gc.drawLine(x+1, y+2, x+6, y+2);
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.setForeground(border);
+ 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);
+ }
+ border.dispose();
+ break;
+ }
+ case SELECTED: {
+ Color fill = new Color(display, MINMAX_FILL);
+ Color border = new Color(display, MINMAX_BORDER);
+ if (!maximized) {
+ gc.setBackground(fill);
+ gc.fillRectangle(x+1, y+1, 7, 9);
+ gc.setForeground(border);
+ gc.drawRectangle(x+1, y+1, 7, 9);
+ gc.drawLine(x+2, y+3, x+7, y+3);
+ } else {
+ gc.setBackground(fill);
+ gc.fillRectangle(x+1, y+4, 5, 4);
+ gc.fillRectangle(x+3, y+1, 5, 4);
+ gc.setForeground(border);
+ 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);
+ }
+ fill.dispose();
+ border.dispose();
+ break;
+ }
}
}
-/**
- * Draw a border around the receiver.
- */
-private void drawBorder(GC gc) {
-
- Rectangle d = super.getClientArea();
-
- if (showBorders) {
- if ((getStyle() & SWT.FLAT) != 0) {
- gc.setForeground(borderColor1);
- gc.drawRectangle(d.x, d.y, d.x + d.width - 1, d.y + d.height - 1);
- } else {
- gc.setForeground(borderColor1);
- gc.drawRectangle(d.x, d.y, d.x + d.width - 3, d.y + d.height - 3);
-
- gc.setForeground(borderColor2);
- gc.drawLine(d.x + 1, d.y + d.height - 2, d.x + d.width - 1, d.y + d.height - 2);
- gc.drawLine(d.x + d.width - 2, d.y + 1, d.x + d.width - 2, d.y + d.height - 1);
-
- gc.setForeground(borderColor3);
- gc.drawLine(d.x + 2, d.y + d.height - 1, d.x + d.width - 2, d.y + d.height - 1);
- gc.drawLine(d.x + d.width - 1, d.y + 2, d.x + d.width - 1, d.y + d.height - 2);
-
- // fill in corners with parent's background
- gc.setForeground(getParent().getBackground());
- gc.drawLine(d.x + d.width - 2, d.y, d.x + d.width - 1, d.y);
- gc.drawLine(d.x + d.width - 1, d.y + 1, d.x + d.width - 1, d.y + 1);
-
- gc.drawLine(d.x, d.y + d.height - 2, d.x, d.y + d.height - 2);
- gc.drawLine(d.x, d.y + d.height - 1, d.x + 1, d.y + d.height - 1);
-
- gc.drawLine(d.x + d.width - 1, d.y + d.height - 1, d.x + d.width - 1, d.y + d.height - 1);
+void drawMinimize(GC gc) {
+ if (minRect.width == 0 || minRect.height == 0) return;
+ Display display = getDisplay();
+ int indent = Math.max(1, (tabHeight-11)/2);
+ int x = minRect.x + indent - 1;
+ int y = minRect.y + indent;
+ switch (minImageState) {
+ case NORMAL: {
+ if (!minimized) {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y, 9, 3);
+ gc.setForeground(borderColor);
+ gc.drawRectangle(x, y, 9, 3);
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.setForeground(borderColor);
+ 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: {
+ Color border = new Color(display, MINMAX_BORDER);
+ if (!minimized) {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y, 9, 3);
+ gc.setForeground(border);
+ gc.drawRectangle(x, y, 9, 3);
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(x, y+3, 5, 4);
+ gc.fillRectangle(x+2, y, 5, 4);
+ gc.setForeground(border);
+ 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);
+ }
+ border.dispose();
+ break;
+ }
+ case SELECTED: {
+ Color fill = new Color(display, MINMAX_FILL);
+ Color border = new Color(display, MINMAX_BORDER);
+ if (!minimized) {
+ gc.setBackground(fill);
+ gc.fillRectangle(x+1, y+1, 9, 3);
+ gc.setForeground(border);
+ gc.drawRectangle(x+1, y+1, 9, 3);
+ } else {
+ gc.setBackground(fill);
+ gc.fillRectangle(x+1, y+4, 5, 4);
+ gc.fillRectangle(x+3, y+1, 5, 4);
+ gc.setForeground(border);
+ 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);
+ }
+ fill.dispose();
+ border.dispose();
+ break;
}
-
}
-
- // draw a separator line
- if (items.length > 0) {
- int lineY = d.y + borderTop + tabHeight;
- if (onBottom) {
- lineY = d.y + d.height - borderBottom - tabHeight - 1;
+}
+void drawTabArea(Event event) {
+ GC gc = event.gc;
+ Point size = getSize();
+ int[] shape = null;
+ 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;
+
+ // Fill in the empty spaces to the right and left of the tabs
+ if (single) {
+ int[] shapeLeft = null;
+ int[] shapeRight = null;
+ if (onBottom) { // single with tabs on bototm
+ //left side
+ shapeLeft = new int[BOTTOM_LEFT_CORNER.length+6];
+ int index = 0;
+ int width2 = (selectedIndex == -1) ? size.x/2 : items[selectedIndex].x - x;
+ shapeLeft[index++] = x;
+ shapeLeft[index++] = y;
+ for (int i = 0; i < BOTTOM_LEFT_CORNER.length/2; i++) {
+ shapeLeft[index++] = x+BOTTOM_LEFT_CORNER[2*i];
+ shapeLeft[index++] = y+height+1+BOTTOM_LEFT_CORNER[2*i+1];
+ }
+ shapeLeft[index++] = x+width2;
+ shapeLeft[index++] = y+height+1;
+ shapeLeft[index++] = x+width2;
+ shapeLeft[index++] = y;
+ //right side
+ int x2 = (selectedIndex == -1) ? x + size.x/2 : items[selectedIndex].x + items[selectedIndex].width;
+ width2 = size.x - borderRight - x2;
+ if (borderLeft == 0) width2 += 1;
+ shapeRight = new int[BOTTOM_RIGHT_CORNER.length+6];
+ index = 0;
+ shapeRight[index++] = x2;
+ shapeRight[index++] = y;
+ shapeRight[index++] = x2;
+ shapeRight[index++] = y+height+1;
+ for (int i = 0; i < BOTTOM_RIGHT_CORNER.length/2; i++) {
+ shapeRight[index++] = x2+width2+BOTTOM_RIGHT_CORNER[2*i];
+ shapeRight[index++] = y+height+1+BOTTOM_RIGHT_CORNER[2*i+1];
+ }
+ shapeRight[index++] = x2+width2;
+ shapeRight[index++] = y;
+ } else { // single with tabs on top
+ //left side
+ shapeLeft = new int[TOP_LEFT_CORNER.length+6];
+ int index = 0;
+ int width2 = (selectedIndex == -1) ? size.x/2 : items[selectedIndex].x - x;
+ shapeLeft[index++] = x;
+ shapeLeft[index++] = y+height+1;
+ for (int i = 0; i < TOP_LEFT_CORNER.length/2; i++) {
+ shapeLeft[index++] = x+TOP_LEFT_CORNER[2*i];
+ shapeLeft[index++] = y+TOP_LEFT_CORNER[2*i+1];
+ }
+ shapeLeft[index++] = x+width2;
+ shapeLeft[index++] = y;
+ shapeLeft[index++] = x+width2;
+ shapeLeft[index++] = y+height+1;
+ //right side
+ int x2 = (selectedIndex == -1) ? x + size.x/2 : items[selectedIndex].x + items[selectedIndex].width;
+ width2 = size.x - borderRight - x2;
+ if (borderLeft == 0) width2 += 1;
+ shapeRight = new int[TOP_RIGHT_CORNER.length+6];
+ index = 0;
+ shapeRight[index++] = x2;
+ shapeRight[index++] = y+height+1;
+ shapeRight[index++] = x2;
+ shapeRight[index++] = y;
+ for (int i = 0; i < TOP_RIGHT_CORNER.length/2; i++) {
+ shapeRight[index++] = x2+width2+TOP_RIGHT_CORNER[2*i];
+ shapeRight[index++] = y+TOP_RIGHT_CORNER[2*i+1];
+ }
+ shapeRight[index++] = x2+width2;
+ shapeRight[index++] = y+height+1;
+ }
+ drawBackground(gc, shapeLeft, false);
+ drawBackground(gc, shapeRight, false);
+ } else { // SWT.MULTI
+ // Fill in the empty space to the right of the last tab
+ CTabItem lastItem = items[items.length -1];
+ int edge = lastItem.x+lastItem.width;
+ if (edge < size.x) {
+ shape = null;
+ if (onBottom) {
+ shape = new int[BOTTOM_RIGHT_CORNER.length+6];
+ int index = 0;
+ shape[index++] = edge;
+ shape[index++] = size.y - borderBottom - tabHeight - 1;
+ shape[index++] = edge;
+ shape[index++] = size.y - borderBottom;
+ for (int i = 0; i < BOTTOM_RIGHT_CORNER.length/2; i++) {
+ shape[index++] = size.x- borderRight + 1+BOTTOM_RIGHT_CORNER[2*i];
+ shape[index++] = size.y - borderBottom + BOTTOM_RIGHT_CORNER[2*i+1];
+ }
+ shape[index++] = size.x - borderRight + 1;
+ shape[index++] = size.y - borderBottom - tabHeight - 1;
+ } else {
+ shape = new int[TOP_RIGHT_CORNER.length+6];
+ int index = 0;
+ shape[index++] = edge;
+ shape[index++] = borderTop + tabHeight + 1;
+ shape[index++] = edge;
+ shape[index++] = borderTop;
+ for (int i = 0; i < TOP_RIGHT_CORNER.length/2; i++) {
+ shape[index++] = size.x - borderRight + 1+TOP_RIGHT_CORNER[2*i];
+ shape[index++] = borderTop+TOP_RIGHT_CORNER[2*i+1];
+ }
+ shape[index++] = size.x - borderRight + 1;
+ shape[index++] = borderTop + tabHeight + 1;
+ }
+ drawBackground(gc, shape, false);
+ }
+ }
+
+ // 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);
+ }
}
- gc.setForeground(borderColor1);
- gc.drawLine(d.x + borderLeft, lineY, d.x + d.width - borderRight, lineY);
}
+
+ // 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 x2 = borderLeft;
+ int y2 = onBottom ? size.y - borderBottom - tabHeight - HIGHLIGHT_HEADER : borderTop + tabHeight + 1;
+ int width2 = size.x - borderLeft - borderRight;
+ int height2 = HIGHLIGHT_HEADER - 1;
+ gc.setBackground(getBackground());
+ gc.fillRectangle(x2, y2, width2, height2);
+ x2 = borderLeft;
+ y2 = (onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight;
+ gc.setForeground(borderColor);
+ gc.drawLine(x2, y2, x2 + width2, y2);
+ }
+
+ drawChevron(gc);
+ drawMinimize(gc);
+ drawMaximize(gc);
+
+ // draw insertion mark
+// if (insertionIndex > -2) {
+// gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
+// if (insertionIndex == -1) {
+// Rectangle bounds = items[0].getBounds();
+// gc.drawLine(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height - 1);
+// gc.drawLine(bounds.x - 2, bounds.y, bounds.x + 2, bounds.y);
+// gc.drawLine(bounds.x - 1, bounds.y + 1, bounds.x + 1, bounds.y + 1);
+// gc.drawLine(bounds.x - 1, bounds.y + bounds.height - 2, bounds.x + 1, bounds.y + bounds.height - 2);
+// gc.drawLine(bounds.x - 2, bounds.y + bounds.height - 1, bounds.x + 2, bounds.y + bounds.height - 1);
+//
+// } else {
+// Rectangle bounds = items[insertionIndex].getBounds();
+// gc.drawLine(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height - 1);
+// gc.drawLine(bounds.x + bounds.width - 2, bounds.y, bounds.x + bounds.width + 2, bounds.y);
+// gc.drawLine(bounds.x + bounds.width - 1, bounds.y + 1, bounds.x + bounds.width + 1, bounds.y + 1);
+// gc.drawLine(bounds.x + bounds.width - 1, bounds.y + bounds.height - 2, bounds.x + bounds.width + 1, bounds.y + bounds.height - 2);
+// gc.drawLine(bounds.x + bounds.width - 2, bounds.y + bounds.height - 1, bounds.x + bounds.width + 2, bounds.y + bounds.height - 1);
+// }
+// }
- gc.setForeground(getForeground());
+
+ // draw outside border area
+ if (onBottom) {
+ shape = new int[BOTTOM_LEFT_CORNER.length + BOTTOM_RIGHT_CORNER.length + 4];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y;
+ for (int i = 0; i < BOTTOM_LEFT_CORNER.length/2; i++) {
+ shape[index++] = x+BOTTOM_LEFT_CORNER[2*i];
+ shape[index++] = y+height+BOTTOM_LEFT_CORNER[2*i+1];
+ if (borderLeft == 0) shape[index-1] += 1;
+ }
+ for (int i = 0; i < BOTTOM_RIGHT_CORNER.length/2; i++) {
+ shape[index++] = x+width+BOTTOM_RIGHT_CORNER[2*i];
+ shape[index++] = y+height+BOTTOM_RIGHT_CORNER[2*i+1];
+ if (borderLeft == 0) shape[index-1] += 1;
+ }
+ shape[index++] = x+width;
+ shape[index++] = y-1;
+ } else {
+ shape = new int[TOP_LEFT_CORNER.length + TOP_RIGHT_CORNER.length + 4];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y+height;
+ for (int i = 0; i < TOP_LEFT_CORNER.length/2; i++) {
+ shape[index++] = x+TOP_LEFT_CORNER[2*i];
+ shape[index++] = y+TOP_LEFT_CORNER[2*i+1];
+ }
+ for (int i = 0; i < TOP_RIGHT_CORNER.length/2; i++) {
+ shape[index++] = x+width+TOP_RIGHT_CORNER[2*i];
+ shape[index++] = y+TOP_RIGHT_CORNER[2*i+1];
+ }
+ shape[index++] = x+width;
+ shape[index++] = y+height+1;
+ }
+ // fill in space outside border line with parent background
+ 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 border line
+ if (borderLeft > 0) {
+ RGB inside = getBackground().getRGB();
+ if (bgImage != null || (gradientColors != null && gradientColors.length > 1 && !gradientVertical)) inside = null;
+ RGB outside = getParent().getBackground().getRGB();
+ antialias(shape, borderColor.getRGB(), inside, outside, gc);
+ gc.setForeground(borderColor);
+ gc.drawPolyline(shape);
+ }
+}
+public boolean getBorderVisible() {
+ checkWidget();
+ return borderLeft == 1;
}
public Rectangle getClientArea() {
checkWidget();
+ if (minimized) return new Rectangle(xClient, yClient, 0, 0);
+ int style = getStyle();
+ boolean highlight = (style & SWT.BORDER) != 0 && (style & SWT.FLAT) == 0;
Point size = getSize();
int width = size.x - borderLeft - borderRight - 2*marginWidth;
+ if (highlight)width -= 2*HIGHLIGHT_MARGIN;
int height = size.y - borderTop - borderBottom - 2*marginHeight;
+ if (highlight)height -= + HIGHLIGHT_MARGIN;
if (items.length == 0) {
return new Rectangle(borderLeft + marginWidth, borderTop + marginHeight, width, height);
}
- height -= tabHeight + 1; //+1 for line under tabs
+ height -= tabHeight+HIGHLIGHT_HEADER;
return new Rectangle(xClient, yClient, width, height);
}
+
/**
- * Returns the height of the tab
- *
- * @return the height of the tab
- *
- * @exception SWTError <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>
+ * Returns <code>false</code> if the receiver is minimized,
+ * and true otherwise.
+ * <p>
+ *
+ * @return the minimized state
+ *
+ * @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>
+ *
+ * @deprecated use getMinimized(boolean)
*/
-public int getTabHeight(){
- checkWidget();
- return tabHeight;
+public boolean getExpanded() {
+ return getMinimized();
}
-
/**
* Return the tab that is located at the specified index.
*
+ * @param index the index of the tab item
* @return the item at the specified index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is out of range</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
*/
public CTabItem getItem (int index) {
//checkWidget();
@@ -670,19 +1273,25 @@ public CTabItem getItem (int index) {
return items [index];
}
/**
-* Gets the item at a point in the widget.
-* <p>
-*
-* @return the item at a point
-*/
+ * Gets the item at a point in the widget.
+ *
+ * @param pt the point in coordinates relative to the CTabFolder
+ * @return the item at a point or null
+ *
+ * @exception SWTError <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>
+ */
public CTabItem getItem (Point pt) {
//checkWidget();
if (items.length == 0) return null;
- int lastItem = getLastItem();
- lastItem = Math.min(items.length - 1, lastItem + 1);
- for (int i = topTabIndex; i <= lastItem; i++) {
- Rectangle bounds = items[i].getBounds();
- if (bounds.contains(pt)) return items[i];
+ Point size = getSize();
+ if (size.x <= borderLeft + borderRight) return null;
+ for (int index = topTabIndex; index < items.length; index++) {
+ CTabItem item = items[index];
+ Rectangle rect = item.getBounds();
+ if (rect.contains(pt)) return item;
}
return null;
}
@@ -690,6 +1299,11 @@ public CTabItem getItem (Point pt) {
* Return the number of tabs in the folder.
*
* @return the number of tabs in the folder
+ *
+ * @exception SWTError <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>
*/
public int getItemCount(){
//checkWidget();
@@ -699,6 +1313,11 @@ public int getItemCount(){
* Return the tab items.
*
* @return the tab items
+ *
+ * @exception SWTError <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>
*/
public CTabItem [] getItems() {
//checkWidget();
@@ -706,28 +1325,62 @@ public CTabItem [] getItems() {
System.arraycopy(items, 0, tabItems, 0, items.length);
return tabItems;
}
-
-private int getLastItem(){
- if (items.length == 0) return -1;
- Rectangle area = getClientArea();
- if (area.width <= 0) return 0;
- Rectangle toolspace = getToolSpace();
- if (toolspace.width == 0) return items.length -1;
- int width = area.width - toolspace.width;
- int index = topTabIndex;
- int tabWidth = items[index].width;
- while (index < items.length - 1) {
- tabWidth += items[index + 1].width;
- if (tabWidth > width) break;
+char getMnemonic (String string) {
+ int index = 0;
+ int length = string.length ();
+ do {
+ while ((index < length) && (string.charAt (index) != '&')) index++;
+ if (++index >= length) return '\0';
+ if (string.charAt (index) != '&') return string.charAt (index);
index++;
- }
- return index;
+ } while (index < length);
+ return '\0';
+}
+/**
+ * Returns <code>true</code> if the receiver is minimized,
+ * and false otherwise.
+ * <p>
+ *
+ * @return the minimized state
+ *
+ * @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>
+ */
+public boolean getMinimized() {
+ checkWidget();
+ return minimized;
+}
+/**
+ * Returns <code>true</code> if the receiver is maximized,
+ * and false otherwise.
+ * <p>
+ *
+ * @return the maximized state
+ *
+ * @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>
+ */
+public boolean getMaximized() {
+ checkWidget();
+ return maximized;
+}
+int getRightItemEdge (){
+ return getSize().x - borderRight - minRect.width - maxRect.width - topRightRect.width - chevronRect.width - 1;
}
/**
* Return the selected tab item, or an empty array if there
* is no selection.
*
* @return the selected tab item
+ *
+ * @exception SWTError <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>
*/
public CTabItem getSelection() {
//checkWidget();
@@ -739,24 +1392,38 @@ public CTabItem getSelection() {
* is no selection.
*
* @return the index of the selected tab item or -1
+ *
+ * @exception SWTError <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>
*/
public int getSelectionIndex() {
//checkWidget();
return selectedIndex;
}
-private Rectangle getToolSpace() {
- boolean showArrows = scroll_leftVisible() || scroll_rightVisible();
- if (!showArrows && topRight == null) return new Rectangle(0, 0, 0, 0);
- Rectangle toolspace;
- if (showArrows) {
- toolspace = arrowBar.getBounds();
- toolspace.width += borderRight;
- if (topRight != null) toolspace.width += topRight.getSize().x;
- } else {
- toolspace = topRight.getBounds();
- toolspace.width += borderRight;
- }
- return toolspace;
+public int getStyle() {
+ int style = super.getStyle();
+ style &= ~(SWT.TOP | SWT.BOTTOM);
+ style |= onBottom ? SWT.BOTTOM : SWT.TOP;
+ style &= ~(SWT.SINGLE | SWT.MULTI);
+ style |= single ? SWT.SINGLE : SWT.MULTI;
+ if (borderLeft != 0) style |= SWT.BORDER;
+ return style;
+}
+/**
+ * Returns the height of the tab
+ *
+ * @return the height of the tab
+ *
+ * @exception SWTError <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>
+ */
+public int getTabHeight(){
+ checkWidget();
+ return tabHeight;
}
/**
* Returns the control in the top right corner of the tab folder.
@@ -780,14 +1447,21 @@ public Control getTopRight() {
* Return the index of the specified tab or -1 if the tab is not
* in the receiver.
*
+ * @param item the tab item for which the index is required
+ *
* @return the index of the specified tab item or -1
*
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
* @exception SWTError <ul>
- * <li>ERROR_NULL_ARGUMENT when the item is null</li>
- * </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>
*/
public int indexOf(CTabItem item) {
- //checkWidget();
+ checkWidget();
if (item == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
@@ -796,8 +1470,7 @@ public int indexOf(CTabItem item) {
}
return -1;
}
-
-private void initAccessible() {
+void initAccessible() {
final Accessible accessible = getAccessible();
accessible.addAccessibleListener(new AccessibleAdapter() {
public void getName(AccessibleEvent e) {
@@ -970,174 +1643,66 @@ private void initAccessible() {
}
});
}
-
-private void setButtonBounds() {
-
- updateArrowBar();
- updateCloseBar();
-
- Rectangle area = super.getClientArea();
-
- int offset = 0;
- if (topRight != null) {
- Point size = topRight.computeSize(SWT.DEFAULT, tabHeight);
- int x = area.x + area.width - borderRight - size.x;
- int y = onBottom ? area.y + area.height - borderBottom - size.y : area.y + borderTop;
- topRight.setBounds(x, y, size.x, size.y);
- offset = size.x;
- }
- boolean leftVisible = scroll_leftVisible();
- boolean rightVisible = scroll_rightVisible();
- if (leftVisible || rightVisible) {
- Point size = arrowBar.computeSize(SWT.DEFAULT, tabHeight);
- int x = area.x + area.width - borderRight - size.x - offset;
- int y = (onBottom) ? area.y + area.height - borderBottom - size.y : area.y + borderTop;
-
- arrowBar.setBounds(x, y, size.x, size.y);
- ToolItem[] items = arrowBar.getItems();
- items[0].setEnabled(leftVisible);
- items[1].setEnabled(rightVisible);
- arrowBar.setVisible(true);
- } else {
- arrowBar.setVisible(false);
- }
-
- // When the close button is right at the edge of the Tab folder, hide it because
- // otherwise it may block off a part of the border on the right
- if (showClose) {
- inactiveCloseBar.setVisible(false);
- CTabItem item = getSelection();
- if (item == null) {
- closeBar.setVisible(false);
- } else {
- int toolbarHeight = tabHeight - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN + 2; // +2 to ignore gap between focus rectangle
- Point size = closeBar.computeSize(SWT.DEFAULT, toolbarHeight);
- int x = item.x + item.width - size.x - 2; // -2 to not overlap focus rectangle and trim
- int y = item.y + Math.max(0, (item.height - toolbarHeight)/2);
- closeBar.setBounds(x, y, size.x, toolbarHeight);
- Rectangle toolspace = getToolSpace();
- Point folderSize = getSize();
- boolean visible = (toolspace.width == 0 || x < toolspace.x) && x + size.x < folderSize.x - borderRight;
- closeBar.setVisible(visible);
- }
- }
+boolean onArrowTraversal (Event event) {
+ int count = items.length;
+ if (count == 0) return false;
+ if (selectedIndex == -1) return false;
+ int offset = (event.detail == SWT.TRAVERSE_ARROW_NEXT) ? 1 : -1;
+ int index = selectedIndex + offset;
+ if (index < 0 || index >= count) return false;
+ setSelection (index, true);
+ //setFocus();
+ return true;
}
-private boolean setItemLocation() {
- if (items.length == 0) return false;
- Rectangle area = super.getClientArea();
- int x = area.x;
- int y = area.y + borderTop;
- if (onBottom) y = Math.max(0, area.y + area.height - borderBottom - tabHeight);
+void onDispose() {
+ /*
+ * Usually when an item is disposed, destroyItem will change the size of the items array,
+ * reset the bounds of all the tabs and manage the widget associated with the tab.
+ * Since the whole folder is being disposed, this is not necessary. For speed
+ * the inDispose flag is used to skip over this part of the item dispose.
+ */
+ inDispose = true;
- boolean changed = false;
- for (int i = topTabIndex - 1; i>=0; i--) {
- // if the first visible tab is not the first tab
- CTabItem tab = items[i];
- x -= tab.width;
- if (!changed && (tab.x != x || tab.y != y) ) changed = true;
- // layout tab items from right to left thus making them invisible
- tab.x = x;
- tab.y = y;
+ int length = items.length;
+ for (int i = 0; i < length; i++) {
+ if (items[i] != null) {
+ items[i].dispose();
+ }
}
- x = area.x + borderLeft;
- for (int i = topTabIndex; i < items.length; i++) {
- // continue laying out remaining, visible items left to right
- CTabItem tab = items[i];
- tab.x = x;
- tab.y = y;
- x = x + tab.width;
- }
- setButtonBounds();
- return changed;
-}
-private void setLastItem(int index) {
- if (index < 0 || index > items.length - 1) return;
- Rectangle area = getClientArea();
- if (area.width <= 0) return;
- int maxWidth = area.width;
- Rectangle toolspace = getToolSpace();
- if (toolspace.width > 0){
- maxWidth -= toolspace.width;
- }
- int tabWidth = items[index].width;
- while (index > 0) {
- tabWidth += items[index - 1].width;
- if (tabWidth > maxWidth) break;
- index--;
- }
- topTabIndex = index;
- setItemLocation();
- redrawTabArea(-1);
-}
-/**
- * Layout the items and store the client area size.
- */
-boolean setItemBounds() {
- boolean changed = false;
- if (isDisposed()) return changed;
- Rectangle area = super.getClientArea();
+ selectionGradientColors = null;
+ selectionGradientPercents = null;
+ selectionBgImage = null;
- xClient = area.x + borderLeft + marginWidth;
- if (onBottom) {
- yClient = area.y + borderTop + marginHeight;
+ selectionBackground = null;
+ selectionForeground = null;
+}
+void onFocus(Event event) {
+ checkWidget();
+ if (selectedIndex >= 0) {
+ redraw();
} else {
- yClient = area.y + borderTop + tabHeight + 1 + marginHeight;
- // +1 is for the line at the bottom of the tabs
- }
-
- if (area.width <= 0 || area.height <= 0 || items.length == 0) return changed;
-
- int[] widths = new int[items.length];
- GC gc = new GC(this);
- for (int i = 0; i < items.length; i++) {
- widths[i] = items[i].preferredWidth(gc);
+ setSelection(0, true);
}
- gc.dispose();
-
- int oldAverageWidth = 0;
- int averageWidth = (area.width - borderLeft - borderRight) / items.length;
- while (averageWidth > oldAverageWidth) {
- int width = area.width - borderLeft - borderRight;
- int count = items.length;
- for (int i = 0; i < items.length; i++) {
- if (widths[i] < averageWidth) {
- width -= widths[i];
- count--;
+}
+void onMenu(Event event) {
+ if (single && selectedIndex != -1) {
+ final CTabFolderEvent e = new CTabFolderEvent(CTabFolder.this);
+ e.widget = this;
+ e.time = event.time;
+ Rectangle rect = items[selectedIndex].getBounds();
+ rect.y += onBottom ? -HIGHLIGHT_HEADER : HIGHLIGHT_HEADER;
+ e.rect = rect;
+ if (listListeners.length == 0) {
+ showList(e.rect, SWT.LEFT);
+ } else {
+ for (int j = 0; j < listListeners.length; j++) {
+ listListeners[j].showList(e);
}
}
- oldAverageWidth = averageWidth;
- if (count > 0) {
- averageWidth = width / count;
- }
}
- averageWidth = Math.max(averageWidth, MIN_TAB_WIDTH * tabHeight);
- for (int i = 0; i < items.length; i++) {
- if (widths[i] > averageWidth) {
- widths[i] = averageWidth;
- }
- }
-
- int totalWidth = 0;
- for (int i = 0; i < items.length; i++) {
- CTabItem tab = items[i];
- if (tab.height != tabHeight || tab.width != widths[i]) changed = true;
- tab.height = tabHeight;
- tab.width = widths[i];
- totalWidth += widths[i];
- }
-
- int areaWidth = area.x + area.width - borderRight;
- if (totalWidth <= areaWidth) {
- topTabIndex = 0;
- }
- if (setItemLocation()) changed = true;
-
- // Is there a gap after last item showing
- if (correctLastItem()) changed = true;
- return changed;
}
-private boolean onMnemonic (Event event) {
+boolean onMnemonic (Event event) {
char key = event.character;
for (int i = 0; i < items.length; i++) {
if (items[i] != null) {
@@ -1152,169 +1717,336 @@ private boolean onMnemonic (Event event) {
}
return false;
}
-/**
- * Paint the receiver.
- */
-private void onPaint(Event event) {
- Font font = getFont();
- if (oldFont == null || !oldFont.equals(font)) {
- oldFont = font;
- resetTabSize(true);
- }
- GC gc = event.gc;
- Rectangle rect = super.getClientArea();
- if (items.length == 0) {
- if (showBorders) {
- if ((getStyle() & SWT.FLAT) != 0) {
- gc.setForeground(borderColor1);
- gc.drawRectangle(rect.x, rect.y, rect.x + rect.width - 1, rect.y + rect.height - 1);
+void onMouseDoubleClick(Event event) {
+ int x = event.x, y = event.y;
+ if (minRect.contains(x, y)) return;
+ if (maxRect.contains(x, y)) return;
+ if (chevronRect.contains(x, y)) return;
+
+ if (showMax) {
+ CTabFolderEvent e = new CTabFolderEvent(this);
+ e.widget = this;
+ e.time = event.time;
+ e.doit = true;
+ boolean restore = maximized;
+ for (int i = 0; i < minmaxListeners.length; i++) {
+ if (restore) {
+ minmaxListeners[i].restore(e);
} else {
- gc.setForeground(borderColor1);
- gc.drawRectangle(rect.x, rect.y, rect.x + rect.width - 3, rect.y + rect.height - 3);
-
- // fill in right and bottom edges with parent's background
- gc.setBackground(getParent().getBackground());
- gc.fillRectangle(rect.x + rect.width - 2, rect.y, 2, rect.height);
- gc.fillRectangle(rect.x, rect.y + rect.height - 2, rect.width, 2);
+ minmaxListeners[i].maximize(e);
}
- gc.setForeground(getForeground());
- }
- return;
- }
-
- // redraw the Border
- drawBorder(gc);
-
- rect.x += borderLeft;
- rect.y += borderTop;
- rect.width -= borderLeft + borderRight;
- rect.height -= borderTop + borderBottom;
- Rectangle clip = gc.getClipping ();
- gc.setClipping(clip.intersection(rect));
-
- // Draw the unselected tabs first.
- for (int i=0; i < items.length; i++) {
- if (i != selectedIndex && event.getBounds().intersects(items[i].getBounds())) {
- items[i].onPaint(gc, false);
}
+ if (e.doit) setMaximized(!restore);
}
- // Selected tab comes last
- if (selectedIndex != -1) {
- items[selectedIndex].onPaint(gc, true);
- }
+
- // draw insertion mark
- if (insertionIndex > -2) {
- gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
- if (insertionIndex == -1) {
- Rectangle bounds = items[0].getBounds();
- gc.drawLine(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height - 1);
- gc.drawLine(bounds.x - 2, bounds.y, bounds.x + 2, bounds.y);
- gc.drawLine(bounds.x - 1, bounds.y + 1, bounds.x + 1, bounds.y + 1);
- gc.drawLine(bounds.x - 1, bounds.y + bounds.height - 2, bounds.x + 1, bounds.y + bounds.height - 2);
- gc.drawLine(bounds.x - 2, bounds.y + bounds.height - 1, bounds.x + 2, bounds.y + bounds.height - 1);
-
- } else {
- Rectangle bounds = items[insertionIndex].getBounds();
- gc.drawLine(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height - 1);
- gc.drawLine(bounds.x + bounds.width - 2, bounds.y, bounds.x + bounds.width + 2, bounds.y);
- gc.drawLine(bounds.x + bounds.width - 1, bounds.y + 1, bounds.x + bounds.width + 1, bounds.y + 1);
- gc.drawLine(bounds.x + bounds.width - 1, bounds.y + bounds.height - 2, bounds.x + bounds.width + 1, bounds.y + bounds.height - 2);
- gc.drawLine(bounds.x + bounds.width - 2, bounds.y + bounds.height - 1, bounds.x + bounds.width + 2, bounds.y + bounds.height - 1);
- }
+ Event e = new Event();
+ e.item = getItem(new Point(event.x, event.y));
+ if (e.item != null) {
+ notifyListeners(SWT.DefaultSelection, e);
}
-
- gc.setForeground(getForeground());
- gc.setBackground(getBackground());
}
-private void redrawTabArea(int index) {
- int x = 0, y = 0, width = 0, height = 0;
- if (index == -1) {
- Rectangle area = super.getClientArea();
- if (area.width == 0 || area.height == 0) return;
- width = area.x + area.width - borderLeft - borderRight;
- height = tabHeight + 1; // +1 causes top line between content and tabs to be redrawn
- x = area.x + borderLeft;
- y = area.y + borderTop;
- if (onBottom) {
- y = Math.max(0, area.y + area.height - borderBottom - height);
+void onMouseHover(Event event) {
+ if (tipShowing) return;
+ showToolTip(event.x, event.y);
+}
+void onMouse(Event event) {
+ int x = event.x, y = event.y;
+ switch (event.type) {
+ case SWT.MouseExit: {
+ if (minImageState != NORMAL) {
+ minImageState = NORMAL;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+ }
+ if (maxImageState != NORMAL) {
+ maxImageState = NORMAL;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+ }
+ if (chevronImageState != NORMAL) {
+ chevronImageState = NORMAL;
+ redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+ update();
+ }
+ for (int i=0; i<items.length; i++) {
+ CTabItem item = items[i];
+ if (i != selectedIndex && item.closeImageState != NONE) {
+ item.closeImageState = NONE;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ if (i == selectedIndex && item.closeImageState != NORMAL) {
+ item.closeImageState = NORMAL;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ }
+ break;
+ }
+ case SWT.MouseDown: {
+ if (minRect.contains(x, y)) {
+ if (event.button != 1) return;
+ minImageState = SELECTED;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+ return;
+ }
+ if (maxRect.contains(x, y)) {
+ if (event.button != 1) return;
+ maxImageState = SELECTED;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+ return;
+ }
+ if (chevronRect.contains(x, y)) {
+ if (event.button != 1) return;
+ chevronImageState = SELECTED;
+ redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+ update();
+ return;
+ }
+ for (int i=0; i<items.length; i++) {
+ CTabItem item = items[i];
+ Rectangle bounds = item.getBounds();
+ if (item.closeRect.contains(x,y)){
+ if (event.button != 1) return;
+ item.closeImageState = SELECTED;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ return;
+ }
+ if (bounds.contains(x, y)) {
+ if (!single && i != topTabIndex && bounds.x + bounds.width >= getRightItemEdge())return;
+ setSelection(i, true);
+ setFocus();
+ return;
+ }
+ }
+ break;
+ }
+ case SWT.MouseMove: {
+ boolean close = false, minimize = false, maximize = false, chevron = false;
+ if (minRect.contains(x, y)) {
+ minimize = true;
+ if (minImageState != HOT) {
+ minImageState = HOT;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+ }
+ }
+ if (maxRect.contains(x, y)) {
+ maximize = true;
+ if (maxImageState != HOT) {
+ maxImageState = HOT;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+ }
+ }
+ if (chevronRect.contains(x, y)) {
+ chevron = true;
+ if (chevronImageState != HOT) {
+ chevronImageState = HOT;
+ redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+ update();
+ }
+ }
+ if (minImageState == HOT && !minimize) {
+ minImageState = NORMAL;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+ }
+ if (maxImageState == HOT && !maximize) {
+ maxImageState = NORMAL;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+ }
+ if (chevronImageState == HOT && !chevron) {
+ chevronImageState = NORMAL;
+ redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+ update();
+ }
+ for (int i=0; i<items.length; i++) {
+ CTabItem item = items[i];
+ close = false;
+ if (item.getBounds().contains(x, y)) {
+ close = true;
+ if (item.closeRect.contains(x, y)) {
+ if (item.closeImageState != HOT) {
+ item.closeImageState = HOT;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ } else {
+ if (item.closeImageState != NORMAL) {
+ item.closeImageState = NORMAL;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ }
+ }
+ if (i != selectedIndex && item.closeImageState != NONE && !close) {
+ item.closeImageState = NONE;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ if (i == selectedIndex && item.closeImageState != NORMAL && !close) {
+ item.closeImageState = NORMAL;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ }
+ }
+ break;
+ }
+ case SWT.MouseUp: {
+ if (event.button != 1) return;
+ if (chevronRect.contains(x, y)) {
+ boolean selected = chevronImageState == SELECTED;
+ chevronImageState = HOT;
+ redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+ update();
+ if (!selected) return;
+ Rectangle rect = new Rectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height);
+ if (single && selectedIndex != -1){
+ rect = items[selectedIndex].getBounds();
+ }
+ rect.y += onBottom ? -HIGHLIGHT_HEADER :HIGHLIGHT_HEADER;
+ if (listListeners.length == 0) {
+ showList(rect, single ? SWT.LEFT : SWT.RIGHT);
+ } else {
+ CTabFolderEvent e = new CTabFolderEvent(this);
+ e.widget = this;
+ e.time = event.time;
+ e.rect = rect;
+
+ for (int i = 0; i < listListeners.length; i++) {
+ listListeners[i].showList(e);
+ }
+ }
+ return;
+ }
+ if (minRect.contains(x, y)) {
+ boolean selected = minImageState == SELECTED;
+ minImageState = HOT;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+ if (!selected) return;
+ CTabFolderEvent e = new CTabFolderEvent(this);
+ e.widget = this;
+ e.time = event.time;
+ e.doit = true;
+ boolean restore = minimized;
+ for (int i = 0; i < minmaxListeners.length; i++) {
+ if (restore) {
+ minmaxListeners[i].restore(e);
+ } else {
+ minmaxListeners[i].minimize(e);
+ }
+ }
+ if (e.doit && !isDisposed()) setMinimized(!restore);
+ return;
+ }
+ if (maxRect.contains(x, y)) {
+ boolean selected = maxImageState == SELECTED;
+ maxImageState = HOT;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+ if (!selected) return;
+ CTabFolderEvent e = new CTabFolderEvent(this);
+ e.widget = this;
+ e.time = event.time;
+ e.doit = true;
+ boolean restore = maximized;
+ for (int i = 0; i < minmaxListeners.length; i++) {
+ if (restore) {
+ minmaxListeners[i].restore(e);
+ } else {
+ minmaxListeners[i].maximize(e);
+ }
+ }
+ if (e.doit && !isDisposed()) setMaximized(!restore);
+ return;
+ }
+ for (int i=0; i<items.length; i++) {
+ CTabItem item = items[i];
+ if (item.closeRect.contains(x,y)){
+ boolean selected = item.closeImageState == SELECTED;
+ item.closeImageState = HOT;
+ redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+ update();
+ if (!selected) return;
+ CTabFolderEvent e = new CTabFolderEvent(this);
+ e.widget = this;
+ e.time = event.time;
+ e.item = item;
+ e.doit = true;
+ for (int j = 0; j < closeListeners.length; j++) {
+ closeListeners[j].itemClosed(e);
+ }
+ if (e.doit) item.dispose();
+ return;
+ }
+ }
+ break;
}
- } else {
- CTabItem item = items[index];
- x = item.x;
- y = item.y;
- Rectangle area = super.getClientArea();
- width = area.x + area.width - x;
- height = item.height;
}
- redraw(x, y, width, height, false);
}
-
-/**
- * Removes the listener.
- *
- * @param listener the listener
- *
- * @exception SWTError
- * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
- * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
- * <li>ERROR_NULL_ARGUMENT when listener is null</li></ul>
- */
-public void removeSelectionListener(SelectionListener listener) {
- checkWidget();
- if (listener == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
+boolean onPageTraversal(Event event) {
+ int count = items.length;
+ if (count == 0) return false;
+ int index = selectedIndex;
+ if (index == -1) {
+ index = 0;
+ } else {
+ int offset = (event.detail == SWT.TRAVERSE_PAGE_NEXT) ? 1 : -1;
+ index = (selectedIndex + offset + count) % count;
}
- removeListener(SWT.Selection, listener);
- removeListener(SWT.DefaultSelection, listener);
+ setSelection (index, true);
+ //setFocus();
+ return true;
}
-/**
- * Removes the listener.
- *
- * @param listener the listener
- *
- * @exception SWTError
- * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
- * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
- * <li>ERROR_NULL_ARGUMENT when listener is null</li></ul>
- */
-public void removeCTabFolderListener(CTabFolderListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- if (tabListeners.length == 0) return;
- int index = -1;
- for (int i = 0; i < tabListeners.length; i++) {
- if (listener == tabListeners[i]){
- index = i;
- break;
+void onPaint(Event event) {
+ Font font = getFont();
+ if (oldFont == null || !oldFont.equals(font)) {
+ // handle case where default font changes
+ oldFont = font;
+ if (!updateTabHeight(tabHeight, false)) {
+ updateItems();
+ redraw();
+ return;
}
}
- if (index == -1) return;
- if (tabListeners.length == 1) {
- tabListeners = new CTabFolderListener[0];
- showClose = false;
- setButtonBounds();
+
+// Useful for debugging paint problems
+//{
+//GC gc = event.gc;
+//Point size = getSize();
+//gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
+//gc.fillRectangle(-10, -10, size.x + 20, size.y+20);
+//}
+
+ GC gc = event.gc;
+ if (items.length == 0) {
+ Point size = getSize();
+ gc.setBackground(getParent().getBackground());
+ gc.fillRectangle(0, 0, size.x, size.y);
return;
}
- CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length - 1];
- System.arraycopy(tabListeners, 0, newTabListeners, 0, index);
- System.arraycopy(tabListeners, index + 1, newTabListeners, index, tabListeners.length - index - 1);
- tabListeners = newTabListeners;
+
+ drawBody(event);
+ drawTabArea(event);
+
+ gc.setForeground(getForeground());
+ gc.setBackground(getBackground());
}
-/**
- * The widget was resized. Adjust the size of the currently selected page.
- */
-private void onResize() {
-
+void onResize() {
if (items.length == 0) {
redraw();
return;
}
-
- if (setItemBounds()) {
- redrawTabArea(-1);
- }
+ if (updateItems()) redraw();
+ showSelection();
Point size = getSize();
if (oldSize == null) {
@@ -1343,27 +2075,185 @@ private void onResize() {
}
}
}
-
+void onTraverse (Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ARROW_NEXT:
+ case SWT.TRAVERSE_ARROW_PREVIOUS:
+ event.doit = onArrowTraversal(event);
+ event.detail = SWT.TRAVERSE_NONE;
+ break;
+ case SWT.TRAVERSE_ESCAPE:
+ case SWT.TRAVERSE_RETURN:
+ case SWT.TRAVERSE_TAB_NEXT:
+ case SWT.TRAVERSE_TAB_PREVIOUS:
+ event.doit = true;
+ break;
+ case SWT.TRAVERSE_MNEMONIC:
+ event.doit = onMnemonic(event);
+ if (event.doit) event.detail = SWT.TRAVERSE_NONE;
+ break;
+ case SWT.TRAVERSE_PAGE_NEXT:
+ case SWT.TRAVERSE_PAGE_PREVIOUS:
+ event.doit = onPageTraversal(event);
+ event.detail = SWT.TRAVERSE_NONE;
+ break;
+ }
+}
+/**
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTError <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.0
+ */
+public void removeCTabFolderCloseListener(CTabFolderCloseListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (closeListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < closeListeners.length; i++) {
+ if (listener == closeListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (closeListeners.length == 1) {
+ closeListeners = new CTabFolderCloseListener[0];
+ return;
+ }
+ CTabFolderCloseListener[] newTabListeners = new CTabFolderCloseListener[closeListeners.length - 1];
+ System.arraycopy(closeListeners, 0, newTabListeners, 0, index);
+ System.arraycopy(closeListeners, index + 1, newTabListeners, index, closeListeners.length - index - 1);
+ closeListeners = newTabListeners;
+}
+/**
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTError <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.0
+ */
+public void removeCTabFolderMinMaxListener(CTabFolderMinMaxListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (minmaxListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < minmaxListeners.length; i++) {
+ if (listener == minmaxListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (minmaxListeners.length == 1) {
+ minmaxListeners = new CTabFolderMinMaxListener[0];
+ return;
+ }
+ CTabFolderMinMaxListener[] newListeners = new CTabFolderMinMaxListener[minmaxListeners.length - 1];
+ System.arraycopy(minmaxListeners, 0, newListeners, 0, index);
+ System.arraycopy(minmaxListeners, index + 1, newListeners, index, minmaxListeners.length - index - 1);
+ minmaxListeners = newListeners;
+}
+/**
+ * Removes the listener.
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ *
+ * @deprecated see removeCTabFolderCloseListener(CTabFolderListener)
+ */
+public void removeCTabFolderListener(CTabFolderListener listener) {
+ removeCTabFolderCloseListener(listener);
+ if (closeListeners.length == 0) {
+ // hide close button
+ closeListeners = new CTabFolderCloseListener[0];
+ showClose = false;
+ updateItems();
+ redraw();
+ return;
+ }
+}
+/**
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTError <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.0
+ */
+public void removeCTabFolderListListener(CTabFolderListListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (listListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < listListeners.length; i++) {
+ if (listener == listListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (listListeners.length == 1) {
+ listListeners = new CTabFolderListListener[0];
+ return;
+ }
+ CTabFolderListListener[] newListeners = new CTabFolderListListener[listListeners.length - 1];
+ System.arraycopy(listListeners, 0, newListeners, 0, index);
+ System.arraycopy(listListeners, index + 1, newListeners, index, listListeners.length - index - 1);
+ listListeners = newListeners;
+}
+/**
+ * Removes the listener.
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ removeListener(SWT.Selection, listener);
+ removeListener(SWT.DefaultSelection, listener);
+}
public void setBackground (Color color) {
+ if (color == null) color = getDisplay().getSystemColor(BACKGROUND);
super.setBackground(color);
- background = color;
- // init inactive close button
- inactiveCloseBar.setBackground(color);
-
- // init scroll buttons
- arrowBar.setBackground(color);
-
- //init topRight control
- if (topRight != null)
- topRight.setBackground(color);
-
- // init close button
- if (gradientColors == null) {
- closeBar.setBackground(color);
- }
+ redraw();
}
/**
- * Specify a gradient of colours to be draw in the background of the selected tab.
+ * Specify a gradient of colours to be draw in the background of the unselected tabs.
* For example to draw a gradient that varies from dark blue to blue and then to
* white, use the following call to setBackground:
* <pre>
@@ -1387,18 +2277,44 @@ public void setBackground (Color color) {
* <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
* </ul>
*/
-
-public void setSelectionBackground(Color[] colors, int[] percents) {
+public void setBackground(Color[] colors, int[] percents) {
+ setBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colours to be draw in the background of the unselected tab.
+ * For example to draw a vertical gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ * display.getSystemColor(SWT.COLOR_BLUE),
+ * display.getSystemColor(SWT.COLOR_WHITE),
+ * display.getSystemColor(SWT.COLOR_WHITE)},
+ * new int[] {25, 50, 100}, true);
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ * in order of appearance left to right. The value <code>null</code> clears the
+ * background gradient. The value <code>null</code> can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal.
+ *
+ * @exception SWTError <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.0
+ */
+public void setBackground(Color[] colors, int[] percents, boolean vertical) {
checkWidget();
if (colors != null) {
if (percents == null || percents.length != colors.length - 1) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
- if (getDisplay().getDepth() < 15) {
- // Don't use gradients on low color displays
- colors = new Color[] { colors[0] };
- percents = new int[] { };
- }
for (int i = 0; i < percents.length; i++) {
if (percents[i] < 0 || percents[i] > 100) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
@@ -1407,10 +2323,15 @@ public void setSelectionBackground(Color[] colors, int[] percents) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
}
+ if (getDisplay().getDepth() < 15) {
+ // Don't use gradients on low color displays
+ colors = new Color[] {colors[0]};
+ percents = new int[] {};
+ }
}
// Are these settings the same as before?
- if (backgroundImage == null) {
+ if (bgImage == null) {
if ((gradientColors != null) && (colors != null) &&
(gradientColors.length == colors.length)) {
boolean same = false;
@@ -1428,33 +2349,37 @@ public void setSelectionBackground(Color[] colors, int[] percents) {
if (!same) break;
}
}
- if (same) return;
+ if (same && this.gradientVertical == vertical) return;
}
} else {
- backgroundImage = null;
+ bgImage = null;
}
// Store the new settings
if (colors == null) {
gradientColors = null;
gradientPercents = null;
- closeBar.setBackground(background);
+ gradientVertical = false;
+ setBackground((Color)null);
} else {
gradientColors = new Color[colors.length];
- for (int i = 0; i < colors.length; ++i)
+ for (int i = 0; i < colors.length; ++i) {
gradientColors[i] = colors[i];
+ }
gradientPercents = new int[percents.length];
- for (int i = 0; i < percents.length; ++i)
+ for (int i = 0; i < percents.length; ++i) {
gradientPercents[i] = percents[i];
- if (getDisplay().getDepth() < 15) closeBar.setBackground(background);
- else closeBar.setBackground(gradientColors[gradientColors.length - 1]);
+ }
+ gradientVertical = vertical;
+ setBackground(gradientColors[gradientColors.length-1]);
}
// Refresh with the new settings
- if (selectedIndex > -1) redrawTabArea(selectedIndex);
+ redraw();
}
/**
- * Set the image to be drawn in the background of the selected tab.
+ * Set the image to be drawn in the background of the unselected tab. Image
+ * is stretched or compressed to cover entire unselected tab area.
*
* @param image the image to be drawn in the background
*
@@ -1463,15 +2388,15 @@ public void setSelectionBackground(Color[] colors, int[] percents) {
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*/
-public void setSelectionBackground(Image image) {
+public void setBackground(Image image) {
checkWidget();
- if (image == backgroundImage) return;
+ if (image == bgImage) return;
if (image != null) {
gradientColors = null;
gradientPercents = null;
}
- backgroundImage = image;
- redrawTabArea(selectedIndex);
+ bgImage = image;
+ redraw();
}
/**
* Toggle the visibility of the border
@@ -1485,48 +2410,144 @@ public void setSelectionBackground(Image image) {
*/
public void setBorderVisible(boolean show) {
checkWidget();
- if (showBorders == show) return;
+ if ((borderLeft == 1) == show) return;
+ borderLeft = borderRight = show ? 1 : 0;
+ borderTop = onBottom ? borderLeft : 0;
+ borderBottom = onBottom ? 0 : borderLeft;
+ Rectangle rectBefore = getClientArea();
+ updateItems();
+ Rectangle rectAfter = getClientArea();
+ if (!rectBefore.equals(rectAfter)) {
+ notifyListeners(SWT.Resize, new Event());
+ }
+ redraw();
+}
+boolean setButtonBounds() {
+ int oldX, oldY, oldWidth, oldHeight;
+ boolean changed = false;
+ Point size = getSize();
- showBorders = show;
- if (showBorders) {
- if ((getStyle() & SWT.FLAT) != 0) {
- borderBottom = borderTop = borderLeft = borderRight = 1;
+ oldX = maxRect.x;
+ oldY = maxRect.y;
+ oldWidth = maxRect.width;
+ oldHeight = maxRect.height;
+ maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0;
+ if (showMax) {
+ maxRect.x = size.x - borderRight - BUTTON_SIZE - 3;
+ if (borderRight > 0) maxRect.x += 1;
+ maxRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+ maxRect.width = BUTTON_SIZE;
+ maxRect.height = tabHeight - 1;
+ }
+ if (oldX != maxRect.x || oldWidth != maxRect.width ||
+ oldY != maxRect.y || oldHeight != maxRect.height) changed = true;
+
+ oldX = minRect.x;
+ oldY = minRect.y;
+ oldWidth = minRect.width;
+ oldHeight = minRect.height;
+ minRect.x = minRect.y = minRect.width = minRect.height = 0;
+ if (showMin) {
+ minRect.x = size.x - borderRight - maxRect.width - BUTTON_SIZE - 3;
+ if (borderRight > 0) minRect.x += 1;
+ minRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+ minRect.width = BUTTON_SIZE;
+ minRect.height = tabHeight - 1;
+ }
+ if (oldX != minRect.x || oldWidth != minRect.width ||
+ oldY != minRect.y || oldHeight != minRect.height) changed = true;
+
+ oldX = topRightRect.x;
+ oldY = topRightRect.y;
+ oldWidth = topRightRect.width;
+ oldHeight = topRightRect.height;
+ topRightRect.x = topRightRect.y = topRightRect.width = topRightRect.height = 0;
+ if (topRight != null) {
+ Point topRightSize = topRight.computeSize(SWT.DEFAULT, tabHeight);
+ if (single && selectedIndex > -1) {
+ CTabItem item = items[selectedIndex];
+ topRightRect.x = Math.min(item.x +item.width + BUTTON_SIZE, size.x - borderRight - minRect.width - maxRect.width - topRightSize.x - 3);
} else {
- borderLeft = borderTop = 1;
- borderRight = borderBottom = 3;
+ topRightRect.x = size.x - borderRight - minRect.width - maxRect.width - topRightSize.x - 3;
}
- } else {
- borderBottom = borderTop = borderLeft = borderRight = 0;
+ topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+ topRightRect.width = topRightSize.x;
+ topRightRect.height = tabHeight - 1;
+ topRight.setBounds(topRightRect);
}
- oldSize = null;
- notifyListeners(SWT.Resize, new Event());
-}
-public void setFont(Font font) {
- checkWidget();
- if (font != null && font.equals(getFont())) return;
- super.setFont(font);
- oldFont = getFont();
- resetTabSize(true);
+ if (oldX != topRightRect.x || oldWidth != topRightRect.width ||
+ oldY != topRightRect.y || oldHeight != topRightRect.height) {
+ changed = true;
+ }
+
+ oldX = chevronRect.x;
+ oldY = chevronRect.y;
+ oldWidth = chevronRect.width;
+ oldHeight = chevronRect.height;
+ chevronRect.x = chevronRect.y = chevronRect.height = chevronRect.width = 0;
+ if (items.length > 1) {
+ if (single && selectedIndex > -1){
+ CTabItem item = items[selectedIndex];
+ chevronRect.x = Math.min(item.x +item.width - 3, size.x - borderRight - minRect.width - maxRect.width - topRightRect.width - BUTTON_SIZE - 3);
+ if (borderRight > 0) chevronRect.x += 1;
+ chevronRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+ chevronRect.width = BUTTON_SIZE;
+ chevronRect.height = tabHeight - 1;
+ } else {
+ int rightEdge = getRightItemEdge();
+ CTabItem item = items[items.length-1];
+ if (topTabIndex > 0 || item.x + item.width >= rightEdge) {
+ chevronRect.x = size.x - borderRight - minRect.width - maxRect.width - topRightRect.width - BUTTON_SIZE - 3;
+ if (borderRight > 0) chevronRect.x += 1;
+ chevronRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+ chevronRect.width = BUTTON_SIZE;
+ chevronRect.height = tabHeight - 1;
+ }
+ }
+ }
+ if (oldX != chevronRect.x || oldWidth != chevronRect.width ||
+ oldY != chevronRect.y || oldHeight != chevronRect.height) changed = true;
+
+ return changed;
}
/**
- * Set the foreground color of the selected tab.
- *
- * @param color the color of the text displayed in the selected tab
- *
+ * Sets the minimized state of the receiver.
+ * <p>
+ *
+ * @param expanded false if folder is to be minimized
+ *
* @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>
+ *
+ * @deprecated use setMinimized(boolean)
*/
-public void setSelectionForeground (Color color) {
+public void setExpanded (boolean expanded) {
+ setMinimized(!expanded);
+}
+void setFirstItem(int index) {
+ if (index < 0 || index > items.length - 1) return;
+ if (index == topTabIndex) return;
+ topTabIndex = index;
+ setItemLocation();
+ redraw();
+}
+public void setFont(Font font) {
checkWidget();
- if (selectionForeground == color) return;
- if (color == null) color = getForeground();
- selectionForeground = color;
- if (selectedIndex > -1) {
- redrawTabArea(selectedIndex);
+ if (font != null && font.equals(getFont())) return;
+ super.setFont(font);
+ oldFont = getFont();
+ if (!updateTabHeight(tabHeight, false)) {
+ updateItems();
+ redraw();
}
}
+public void setForeground (Color color) {
+ if (color == null) color = getDisplay().getSystemColor(FOREGROUND);
+ super.setForeground(color);
+ redraw();
+}
/**
* Display an insert marker before or after the specified tab item.
*
@@ -1554,10 +2575,13 @@ public void setInsertMark(CTabItem item, boolean after) {
*
* A value of -1 will clear the mark.
*
- * @param item the index of the item with which the mark is associated or null
+ * @param index the index of the item with which the mark is associated or null
*
* @param after true if the mark should be displayed after the specified item
*
+ * @exception IllegalArgumentException<ul>
+ * </ul>
+ *
* @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>
@@ -1569,19 +2593,231 @@ public void setInsertMark(int index, boolean after) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
- if (index == -1) {
- index = -2;
+// if (index == -1) {
+// index = -2;
+// } else {
+// index = after ? index : --index;
+// }
+//
+// if (insertionIndex == index) return;
+// int oldIndex = insertionIndex;
+// insertionIndex = index;
+// if (index > -1) redrawTabArea(index);
+// if (oldIndex > 1) redrawTabArea(oldIndex);
+}
+boolean setItemLocation() {
+ if (items.length == 0) return false;
+ Point size = getSize();
+ int y = onBottom ? Math.max(borderBottom, size.y - borderBottom - tabHeight) : borderTop;
+ boolean changed = false;
+ if (single) {
+ int defaultX = size.x + 10; // off screen
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].x != defaultX) changed = true;
+ items[i].x = defaultX;
+ }
+ if (selectedIndex > -1) {
+ CTabItem item = items[selectedIndex];
+ int oldX = item.x, oldY = item.y;
+ int tabWidth = size.x - borderLeft - borderRight - minRect.width - maxRect.width - chevronRect.width;
+ int indent = Math.max(0, (tabWidth-item.width)/2);
+ item.x = borderLeft + indent;
+ item.y = y;
+ if (showClose || item.showClose) {
+ item.closeRect.x = item.x + item.width - BUTTON_SIZE - CTabItem.RIGHT_MARGIN - 8;
+ item.closeRect.y = onBottom ? y : y + CTabItem.TOP_MARGIN;
+ }
+ if (item.x != oldX || item.y != oldY) changed = true;
+ }
} else {
- index = after ? index : --index;
+ int x = -1;
+ for (int i = topTabIndex - 1; i >= 0; i--) {
+ // if the first visible tab is not the first tab
+ CTabItem item = items[i];
+ x -= item.width;
+ if (!changed && (item.x != x || item.y != y) ) changed = true;
+ // layout tab items from right to left thus making them invisible
+ item.x = x;
+ item.y = y;
+ item.closeRect.x = item.x + item.width - BUTTON_SIZE - CTabItem.RIGHT_MARGIN;
+ if (i == selectedIndex) item.closeRect.x -= 8;
+ item.closeRect.y = onBottom ? y : y + CTabItem.TOP_MARGIN;
+ }
+
+ x = borderLeft <= 1 ? 0 : HIGHLIGHT_MARGIN;
+ for (int i = topTabIndex; i < items.length; i++) {
+ // continue laying out remaining, visible items left to right
+ CTabItem item = items[i];
+ item.x = x;
+ item.y = y;
+ item.closeRect.x = item.x + item.width - BUTTON_SIZE - CTabItem.RIGHT_MARGIN;
+ if (i == selectedIndex) item.closeRect.x -= 8;
+ item.closeRect.y = onBottom ? y : y + CTabItem.TOP_MARGIN;
+ x = x + item.width;
+ }
+
+ int rightEdge = getRightItemEdge();
+ if (rightEdge > 0) {
+ CTabItem item = items[items.length - 1];
+ if (item.x + item.width < rightEdge) {
+ setLastItem(items.length - 1);
+ changed = true;
+ }
+ }
+
+ }
+ return changed;
+}
+boolean setItemSize() {
+ if (isDisposed()) return false;
+ Point size = getSize();
+ if (size.x <= 0 || size.y <= 0 || items.length == 0) return false;
+ int style = getStyle();
+ boolean highlight = borderLeft > 0 && (style & SWT.FLAT) == 0;
+ boolean changed = false;
+ xClient = borderLeft + marginWidth;
+ if (highlight) xClient += HIGHLIGHT_MARGIN;
+ if (onBottom) {
+ yClient = borderTop + marginHeight;
+ if (highlight) yClient += HIGHLIGHT_MARGIN;
+ } else {
+ yClient = borderTop + tabHeight + HIGHLIGHT_HEADER + marginHeight;
}
- if (insertionIndex == index) return;
- int oldIndex = insertionIndex;
- insertionIndex = index;
- if (index > -1) redrawTabArea(index);
- if (oldIndex > 1) redrawTabArea(oldIndex);
+ int[] widths = new int[items.length];
+ GC gc = new GC(this);
+ for (int i = 0; i < items.length; i++) {
+ widths[i] = items[i].preferredWidth(gc, i == selectedIndex);
+ }
+ gc.dispose();
+ int tabAreaWidth = size.x - borderLeft - borderRight - minRect.width - maxRect.width - chevronRect.width;
+ if (items.length > 1) {
+ int selectedWidth = selectedIndex == -1 ? 0 : widths[selectedIndex];
+ int count = selectedIndex == -1 ? items.length : items.length - 1;
+ int averageWidth = (tabAreaWidth - selectedWidth) / count;
+ int oldAverageWidth = 0;
+ while (averageWidth > oldAverageWidth) {
+ int width = tabAreaWidth - selectedWidth;
+ for (int i = 0; i < items.length; i++) {
+ if (i == selectedIndex) continue;
+ if (widths[i] < averageWidth) {
+ width -= widths[i];
+ count--;
+ }
+ }
+ oldAverageWidth = averageWidth;
+ if (count > 0) {
+ averageWidth = width / count;
+ }
+ }
+ averageWidth = Math.max(averageWidth, MIN_TAB_WIDTH * tabHeight);
+ for (int i = 0; i < items.length; i++) {
+ if (i == selectedIndex) continue;
+ if (widths[i] > averageWidth) {
+ widths[i] = averageWidth;
+ }
+ }
+ }
+ int totalWidth = 0;
+ for (int i = 0; i < items.length; i++) {
+ CTabItem tab = items[i];
+ if (tab.height != tabHeight || tab.width != widths[i]) changed = true;
+ tab.height = tabHeight;
+ tab.width = widths[i];
+ tab.closeRect.width = tab.closeRect.height = 0;
+ if (showClose || tab.showClose) {
+ tab.closeRect.width = BUTTON_SIZE;
+ tab.closeRect.height = BUTTON_SIZE;
+ }
+ totalWidth += widths[i];
+ }
+ if (totalWidth <= tabAreaWidth) {
+ topTabIndex = 0;
+ }
+ return changed;
+}
+void setLastItem(int index) {
+ if (index < 0 || index > items.length - 1) return;
+ Point size = getSize();
+ if (size.x <= 0) return;
+ int maxWidth = getRightItemEdge() - borderLeft;
+ int tabWidth = items[index].width;
+ while (index > 0) {
+ tabWidth += items[index - 1].width;
+ if (tabWidth >= maxWidth) break;
+ index--;
+ }
+ if (topTabIndex == index) return;
+ topTabIndex = index;
+ setItemLocation();
+ redraw();
+}
+/**
+ *
+ *
+ */
+public void setMaximizeVisible(boolean visible) {
+ checkWidget();
+ if (showMax == visible) return;
+ // display maximize button
+ showMax = visible;
+ updateItems();
+ redraw();
+}
+/**
+ *
+ */
+public void setMaximized(boolean maximize) {
+ checkWidget ();
+ if (this.maximized == maximize) return;
+ if (maximize && this.minimized) setMinimized(false);
+ this.maximized = maximize;
+ redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+ update();
+}
+/**
+ *
+ *
+ */
+public void setMinimizeVisible(boolean visible) {
+ checkWidget();
+ if (showMin == visible) return;
+ // display maximize button
+ showMin = visible;
+ updateItems();
+ redraw();
+}
+/**
+ *
+ */
+public void setMinimized(boolean minimize) {
+ checkWidget ();
+ if (this.minimized == minimize) return;
+ if (minimize && this.maximized) setMaximized(false);
+ this.minimized = minimize;
+ redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+ update();
+}
+/**
+ * Set the selection to the tab at the specified item.
+ *
+ * @param item the tab item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTError <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>
+ */
+public void setSelection(CTabItem item) {
+ checkWidget();
+ if (item == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int index = indexOf(item);
+ setSelection(index);
}
-
/**
* Set the selection to the tab at the specified index.
*
@@ -1595,10 +2831,17 @@ public void setInsertMark(int index, boolean after) {
public void setSelection(int index) {
checkWidget();
if (index < 0 || index >= items.length) return;
- if (selectedIndex == index) return;
+ if (selectedIndex == index) {
+ showItem(items[index]);
+ return;
+ }
int oldIndex = selectedIndex;
selectedIndex = index;
+ if (oldIndex != -1) {
+ items[oldIndex].closeImageState = NONE;
+ }
+ items[selectedIndex].closeImageState = NORMAL;
Control control = items[index].control;
if (control != null && !control.isDisposed()) {
@@ -1612,9 +2855,272 @@ public void setSelection(int index) {
control.setVisible(false);
}
}
- showItem(items[selectedIndex]);
- setButtonBounds();
- redrawTabArea(-1);
+ updateItems();
+ redraw();
+}
+void setSelection(int index, boolean notify) {
+ int oldSelectedIndex = selectedIndex;
+ setSelection(index);
+ if (notify && selectedIndex != oldSelectedIndex && selectedIndex != -1) {
+ Event event = new Event();
+ event.item = getItem(selectedIndex);
+ notifyListeners(SWT.Selection, event);
+ }
+}
+/**
+ * @since 3.0
+ */
+public void setSelectionBackground (Color color) {
+ checkWidget();
+ if (selectionBackground == color) return;
+ if (color == null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
+ selectionBackground = color;
+ if (selectedIndex > -1) redraw();
+}
+/**
+ * Specify a gradient of colours to be draw in the background of the selected tab.
+ * For example to draw a gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ * display.getSystemColor(SWT.COLOR_BLUE),
+ * display.getSystemColor(SWT.COLOR_WHITE),
+ * display.getSystemColor(SWT.COLOR_WHITE)},
+ * new int[] {25, 50, 100});
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ * in order of appearance left to right. The value <code>null</code> clears the
+ * background gradient. The value <code>null</code> can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @exception SWTError <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>
+ */
+public void setSelectionBackground(Color[] colors, int[] percents) {
+ setSelectionBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colours to be draw in the background of the selected tab.
+ * For example to draw a vertical gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ * display.getSystemColor(SWT.COLOR_BLUE),
+ * display.getSystemColor(SWT.COLOR_WHITE),
+ * display.getSystemColor(SWT.COLOR_WHITE)},
+ * new int[] {25, 50, 100}, true);
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ * in order of appearance left to right. The value <code>null</code> clears the
+ * background gradient. The value <code>null</code> can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal.
+ *
+ * @exception SWTError <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.0
+ */
+public void setSelectionBackground(Color[] colors, int[] percents, boolean vertical) {
+ checkWidget();
+ if (colors != null) {
+ if (percents == null || percents.length != colors.length - 1) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ for (int i = 0; i < percents.length; i++) {
+ if (percents[i] < 0 || percents[i] > 100) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (i > 0 && percents[i] < percents[i-1]) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ if (getDisplay().getDepth() < 15) {
+ // Don't use gradients on low color displays
+ colors = new Color[] {colors[0]};
+ percents = new int[] {};
+ }
+ }
+
+ // Are these settings the same as before?
+ if (selectionBgImage == null) {
+ if ((selectionGradientColors != null) && (colors != null) &&
+ (selectionGradientColors.length == colors.length)) {
+ boolean same = false;
+ for (int i = 0; i < selectionGradientColors.length; i++) {
+ if (selectionGradientColors[i] == null) {
+ same = colors[i] == null;
+ } else {
+ same = selectionGradientColors[i].equals(colors[i]);
+ }
+ if (!same) break;
+ }
+ if (same) {
+ for (int i = 0; i < selectionGradientPercents.length; i++) {
+ same = selectionGradientPercents[i] == percents[i];
+ if (!same) break;
+ }
+ }
+ if (same && this.selectionGradientVertical == vertical) return;
+ }
+ } else {
+ selectionBgImage = null;
+ }
+ // Store the new settings
+ if (colors == null) {
+ selectionGradientColors = null;
+ selectionGradientPercents = null;
+ selectionGradientVertical = false;
+ setSelectionBackground((Color)null);
+ } else {
+ selectionGradientColors = new Color[colors.length];
+ for (int i = 0; i < colors.length; ++i) {
+ selectionGradientColors[i] = colors[i];
+ }
+ selectionGradientPercents = new int[percents.length];
+ for (int i = 0; i < percents.length; ++i) {
+ selectionGradientPercents[i] = percents[i];
+ }
+ selectionGradientVertical = vertical;
+ setSelectionBackground(selectionGradientColors[selectionGradientColors.length-1]);
+ }
+
+ // Refresh with the new settings
+ if (selectedIndex > -1) redraw();
+}
+
+/**
+ * Set the image to be drawn in the background of the selected tab. Image
+ * is stretched or compressed to cover entire selection tab area.
+ *
+ * @param image the image to be drawn in the background
+ *
+ * @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>
+ */
+public void setSelectionBackground(Image image) {
+ checkWidget();
+ if (image == selectionBgImage) return;
+ if (image != null) {
+ selectionGradientColors = null;
+ selectionGradientPercents = null;
+ }
+ selectionBgImage = image;
+ if (selectedIndex > -1) redraw();
+}
+/**
+ * Set the foreground color of the selected tab.
+ *
+ * @param color the color of the text displayed in the selected tab
+ *
+ * @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>
+ */
+public void setSelectionForeground (Color color) {
+ checkWidget();
+ if (selectionForeground == color) return;
+ if (color == null) color = getDisplay().getSystemColor(SELECTION_FOREGROUND);
+ selectionForeground = color;
+ if (selectedIndex > -1) redraw();
+}
+/**
+ *
+ * @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 3.0
+ */
+public void setStyle(int style) {
+ checkWidget();
+ int mask = SWT.TOP | SWT.BOTTOM | SWT.SINGLE | SWT.MULTI;
+ style = style & mask;
+ // TOP and BOTTOM are mutually exlusive.
+ // TOP is the default
+ if ((style & SWT.TOP) != 0)
+ style = style & ~SWT.BOTTOM | SWT.TOP;
+ // SINGLE and MULTI are mutually exlusive.
+ // MULTI is the default
+ if ((style & SWT.MULTI) != 0)
+ style = style & ~SWT.SINGLE | SWT.MULTI;
+
+ boolean changed = false;
+ if ((style & SWT.TOP) != 0 || (style & SWT.BOTTOM) != 0) {
+ if (onBottom != ((style & SWT.BOTTOM) != 0)) {
+ onBottom = (style & SWT.BOTTOM) != 0;
+ borderTop = onBottom ? borderLeft : 0;
+ borderBottom = onBottom ? 0 : borderRight;
+ updateTabHeight(tabHeight, true);
+ changed = true;
+ }
+ }
+ if ((style & SWT.SINGLE) != 0 || (style & SWT.MULTI) != 0) {
+ if (single != ((style & SWT.SINGLE) != 0)) {
+ single = (style & SWT.SINGLE) != 0;
+ if (single && selectedIndex == -1 && items.length > 0) {
+ setSelection(0, true);
+ }
+ 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 == NONE) {
+ items[i].closeImageState = NORMAL;
+ }
+ }
+ changed = true;
+ }
+ }
+ if (changed) {
+ Rectangle rectBefore = getClientArea();
+ updateItems();
+ Rectangle rectAfter = getClientArea();
+ if (!rectBefore.equals(rectAfter)) {
+ notifyListeners(SWT.Resize, new Event());
+ }
+ redraw();
+ }
+}
+/**
+ * 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
+ * is greater. Specifying a height of -1 will revert to the default height.
+ *
+ * @param height the pixel value of the height or -1
+ *
+ * @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>
+ * <li>ERROR_INVALID_ARGUMENT - if called with a height of less than 0</li>
+ * </ul>
+ */
+public void setTabHeight(int height) {
+ checkWidget();
+ if (height < -1) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ fixedTabHeight = height > -1;
+ int oldHeight = tabHeight;
+ tabHeight = height;
+ updateTabHeight(oldHeight, false);
}
/**
* Set the control that appears in the top right corner of the tab folder.
@@ -1630,6 +3136,7 @@ public void setSelection(int index) {
* <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>
+ *
*/
public void setTopRight(Control control) {
checkWidget();
@@ -1637,9 +3144,8 @@ public void setTopRight(Control control) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
topRight = control;
- resetTabSize(true);
+ if (updateItems()) redraw();
}
-
/**
* Shows the item. If the item is already showing in the receiver,
* this method simply returns. Otherwise, the items are scrolled until
@@ -1665,26 +3171,78 @@ public void showItem (CTabItem item) {
if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Point size = getSize();
int index = indexOf(item);
- if (index < topTabIndex) {
- topTabIndex = index;
- setItemLocation();
- redrawTabArea(-1);
+ if (size.x <= borderLeft + borderRight || index < topTabIndex) {
+ setFirstItem(index);
return;
}
- Rectangle area = getClientArea();
- if (area.width <= 0) {
- topTabIndex = index;
- return;
- }
- int rightEdge = area.x + area.width;
- Rectangle rect = getToolSpace();
- if (rect.width > 0) {
- rightEdge -= rect.width;
- }
+ int rightEdge = getRightItemEdge();
if (item.x + item.width < rightEdge) return;
setLastItem(index);
}
+void showList (Rectangle rect, int alignment) {
+ final Shell shell = new Shell(getShell(), SWT.BORDER | SWT.ON_TOP);
+ shell.setLayout(new FillLayout());
+ final Table table = new Table(shell, SWT.NONE);
+// table.setBackground(selectionBackground);
+// table.setForeground(selectionForeground);
+ for (int i = 0; i < items.length; i++) {
+ CTabItem tab = items[i];
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setText(tab.getText());
+ item.setImage(tab.getImage());
+ }
+ if (selectedIndex != -1) {
+ table.setSelection(selectedIndex);
+ }
+ Listener listener = new Listener() {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.FocusOut:
+ shell.dispose();
+ break;
+ case SWT.DefaultSelection:
+ case SWT.MouseUp:
+ int index = table.getSelectionIndex();
+ if (index != -1) {
+ setSelection(index, true);
+ //setFocus();
+ }
+ shell.dispose();
+ break;
+ }
+ }
+ };
+ table.addListener(SWT.MouseUp, listener);
+ table.addListener(SWT.DefaultSelection, listener);
+ table.addListener(SWT.FocusOut, listener);
+ Point size = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ Rectangle displayRect = getMonitor().getClientArea();
+ Rectangle clientArea = getClientArea();
+ size.y = Math.min(displayRect.height/3, size.y);
+ shell.setSize(size);
+ Point p1 = getDisplay().map(this, null, clientArea.x, clientArea.y);
+ Point p2 = getDisplay().map(this, null, rect.x, rect.y);
+ int x = 0, y = 0;
+ if (alignment == SWT.LEFT) {
+ x = p2.x;
+ } else { // Left
+ x = p2.x + rect.width - size.x;
+ }
+ if (x < displayRect.x) x = displayRect.x;
+ if (x + size.x > displayRect.x + displayRect.width) x = displayRect.x + displayRect.width - size.x;
+ if (onBottom) {
+ y = p1.y + clientArea.height - size.y;
+ if (y < displayRect.y) y = p2.y + rect.height;
+ } else {
+ y = p1.y;
+ if (y + size.y > displayRect.y + displayRect.height) y = p2.y - size.y;
+ }
+ shell.setLocation(x, y);
+ shell.open();
+ table.setFocus();
+}
/**
* Shows the selection. If the selection is already showing in the receiver,
* this method simply returns. Otherwise, the items are scrolled until
@@ -1706,472 +3264,150 @@ public void showSelection () {
showItem(getSelection());
}
}
-
-char getMnemonic (String string) {
- int index = 0;
- int length = string.length ();
- do {
- while ((index < length) && (string.charAt (index) != '&')) index++;
- if (++index >= length) return '\0';
- if (string.charAt (index) != '&') return string.charAt (index);
- index++;
- } while (index < length);
- return '\0';
-}
-/**
- * Set the selection to the tab at the specified item.
- *
- * @param index the tab item to be selected
- *
- * @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>
- * <li>ERROR_NULL_ARGUMENT - if argument is null</li>
- * </ul>
- */
-public void setSelection(CTabItem item) {
- checkWidget();
- if (item == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- int index = indexOf(item);
- setSelection(index);
-}
-/**
- * Set the selection to the tab at the specified index.
- */
-private void setSelection(int index, boolean notify) {
- int oldSelectedIndex = selectedIndex;
- setSelection(index);
- if (notify && selectedIndex != oldSelectedIndex && selectedIndex != -1) {
- Event event = new Event();
- event.item = getItem(selectedIndex);
- notifyListeners(SWT.Selection, event);
- }
-}
-
-private Image scaleImage (Image image, int oldSize, int newSize) {
- Display display = getDisplay();
- Color foreground = getForeground();
- Color black = display.getSystemColor(SWT.COLOR_BLACK);
- Color background = getBackground();
- PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
- ImageData imageData = new ImageData(newSize, newSize, 4, palette);
- imageData.transparentPixel = 1;
- Image temp = new Image(display, imageData);
- GC gc = new GC(temp);
- gc.setBackground(background);
- gc.fillRectangle(0, 0, newSize, newSize);
- gc.drawImage(image, 0, 0, oldSize, oldSize, 0, 0, newSize, newSize);
- gc.dispose();
- return temp;
-}
-private void updateCloseBar() {
- //Temporary code - need a better way to determine toolBar trim
- int toolbarTrim = 4;
- String platform = SWT.getPlatform();
- if ("photon".equals(platform)) toolbarTrim = 6; //$NON-NLS-1$
- if ("gtk".equals(platform)) toolbarTrim = 8; //$NON-NLS-1$
-
- int maxHeight = tabHeight - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN - toolbarTrim;
- if (maxHeight < 3) return;
- int imageHeight = Math.max(9, maxHeight);
-
- if (closeImage != null) {
- int height = closeImage.getBounds().height;
- if (height == imageHeight) return;
- if (imageHeight > maxHeight && height == maxHeight) return;
- }
-
- if (closeBar != null) closeBar.dispose();
- closeBar = null;
- if (inactiveCloseBar != null) inactiveCloseBar.dispose();
- inactiveCloseBar = null;
- createCloseBar();
-
- ToolItem closeItem = closeBar.getItems()[0];
- ToolItem inactiveCloseItem = inactiveCloseBar.getItems()[0];
-
- if (closeImage != null) closeImage.dispose();
-
- Display display = getDisplay();
- Color foreground = getForeground();
- Color black = display.getSystemColor(SWT.COLOR_BLACK);
- Color background = getBackground();
-
- PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
- ImageData imageData = new ImageData(imageHeight, imageHeight, 4, palette);
- imageData.transparentPixel = 1;
- closeImage = new Image(display, imageData);
- GC gc = new GC(closeImage);
- gc.setBackground(background);
- gc.fillRectangle(0, 0, imageHeight, imageHeight);
- gc.setForeground(black);
-
- //draw an 9x8 'x' centered in image
- int h = (imageHeight / 2 )* 2;
- int inset = (h - 8) / 2;
- gc.drawLine( inset, inset, h - inset - 1, h - inset - 1);
- gc.drawLine( inset + 1, inset, h - inset, h - inset - 1);
- gc.drawLine( inset, h - inset - 1, h - inset - 1, inset);
- gc.drawLine( inset + 1, h - inset - 1, h - inset, inset);
-
- gc.dispose();
+void showToolTip (int x, int y) {
+ final Shell tip = new Shell (getShell(), SWT.ON_TOP);
+ final Label label = new Label (tip, SWT.CENTER);
+ Display display = tip.getDisplay();
+ label.setForeground (display.getSystemColor (SWT.COLOR_INFO_FOREGROUND));
+ label.setBackground (display.getSystemColor (SWT.COLOR_INFO_BACKGROUND));
- if (maxHeight < imageHeight) {
- try {
- //rescale image
- Image temp = scaleImage(closeImage, imageHeight, maxHeight);
- closeImage.dispose();
- closeImage = temp;
- } catch (IllegalArgumentException e) {
- } catch (SWTException e) {
- }
- }
- closeItem.setImage(closeImage);
- inactiveCloseItem.setImage(closeImage);
-}
-private void updateArrowBar() {
- //Temporary code - need a better way to determine toolBar trim
- int toolbarTrim = 4;
- String platform = SWT.getPlatform();
- if ("photon".equals(platform)) toolbarTrim = 6; //$NON-NLS-1$
- if ("gtk".equals(platform)) toolbarTrim = 8; //$NON-NLS-1$
-
- int maxHeight = tabHeight - toolbarTrim;
- if (maxHeight < 3) return;
- int imageHeight = Math.max(9, maxHeight);
-
- if (arrowLeftImage != null) {
- int height = arrowLeftImage.getBounds().height;
- if (height == imageHeight) return;
- if (imageHeight > maxHeight && height == maxHeight) return;
+ if (!updateToolTip(x, y, label)) {
+ tip.dispose();
+ return;
}
-
- if (arrowBar != null) arrowBar.dispose();
- arrowBar = null;
- if (arrowLeftImage != null) arrowLeftImage.dispose();
- if (arrowRightImage != null) arrowRightImage.dispose();
- createArrowBar();
- ToolItem[] items = arrowBar.getItems();
- ToolItem left = items[0];
- ToolItem right = items[1];
-
- Display display = getDisplay();
- Color foreground = getForeground();
- Color black = display.getSystemColor(SWT.COLOR_BLACK);
- Color background = getBackground();
-
- PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
- ImageData imageData = new ImageData(7, imageHeight, 4, palette);
- imageData.transparentPixel = 1;
- arrowLeftImage = new Image(display, imageData);
- GC gc = new GC(arrowLeftImage);
- gc.setBackground(background);
- gc.fillRectangle(0, 0, 7, imageHeight);
- gc.setBackground(black);
- //draw a 9x5 '<' centered vertically in image
- int h = (imageHeight / 2 )* 2;
- int midpoint = h / 2 - 1;
- int[] pointArr = new int[] {6, midpoint - 5,
- 1, midpoint,
- 6, midpoint + 5,};
- gc.fillPolygon(pointArr);
- gc.dispose();
-
- palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), black.getRGB()});
- imageData = new ImageData(7, imageHeight, 4, palette);
- imageData.transparentPixel = 1;
- arrowRightImage = new Image(display, imageData);
- gc = new GC(arrowRightImage);
- gc.setBackground(background);
- gc.fillRectangle(0, 0, 7, imageHeight);
- gc.setBackground(black);
- //draw a 9x5 '>' centered vertically in image
- pointArr = new int[] {1, midpoint - 5,
- 6, midpoint,
- 1, midpoint + 5,};
- gc.fillPolygon(pointArr);
- gc.dispose();
-
- if (maxHeight < imageHeight) {
- try {
- //rescale image
- Image leftTemp = scaleImage(arrowLeftImage, imageHeight, maxHeight);
- arrowLeftImage.dispose();
- arrowLeftImage = leftTemp;
- } catch (IllegalArgumentException e) {
- } catch (SWTException e) {
- }
-
- try {
- Image rightTemp = scaleImage(arrowRightImage, imageHeight, maxHeight);
- arrowRightImage.dispose();
- arrowRightImage = rightTemp;
- } catch (IllegalArgumentException e) {
- } catch (SWTException e) {
- }
- }
- left.setImage(arrowLeftImage);
- right.setImage(arrowRightImage);
-}
-
-private void onMouseDoubleClick(Event event) {
- Event e = new Event();
- e.item = getItem(new Point(event.x, event.y));
- notifyListeners(SWT.DefaultSelection, e);
-}
-/**
- * A mouse button was pressed down.
- * If a tab was hit select the tab.
- */
-private void onMouseDown(Event event) {
- for (int i=0; i<items.length; i++) {
- if (items[i].getBounds().contains(new Point(event.x, event.y))) {
- if (i == selectedIndex) {
- showSelection();
- return;
+ final int [] events = new int[] {SWT.MouseExit, SWT.MouseHover, SWT.MouseMove};
+ final Listener[] listener = new Listener[1];
+ listener[0] = new Listener() {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.MouseHover:
+ case SWT.MouseMove:
+ if (updateToolTip(event.x, event.y, label)) break;
+ // FALL THROUGH
+ case SWT.MouseExit:
+ for (int i = 0; i < events.length; i++) {
+ removeListener(events[i], listener[0]);
+ }
+ tip.dispose();
+ tipShowing = false;
+ break;
}
- forceFocus();
- setSelection(i, true);
- if (isFocusControl()) setFocus();
- return;
- }
- }
-}
-
-private void onMouseExit(Event event) {
- Rectangle inactiveBounds = inactiveCloseBar.getBounds();
- if (inactiveBounds.contains(event.x, event.y)) return;
- inactiveCloseBar.setVisible(false);
- inactiveItem = null;
-
- showToolTip = false;
- toolTipItem = null;
- if (tip != null && !tip.isDisposed() && tip.isVisible()) tip.setVisible(false);
-}
-
-private void onMouseHover(Event event) {
- if (tip == null || tip.isDisposed()) return;
- showToolTip = true;
- showToolTip(event.x, event.y);
-}
-private void showToolTip (int x, int y) {
- CTabItem item = getItem(new Point (x, y));
- if (item != null) {
- if (item == toolTipItem) return;
- toolTipItem = item;
- String tooltip = item.getToolTipText();
- if (tooltip != null) {
- Display display = tip.getDisplay();
- label.setForeground (display.getSystemColor (SWT.COLOR_INFO_FOREGROUND));
- label.setBackground (display.getSystemColor (SWT.COLOR_INFO_BACKGROUND));
- label.setText(tooltip);
- Point labelSize = label.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- labelSize.x += 2; labelSize.y += 2;
- label.setSize(labelSize);
- tip.pack();
- /*
- * On some platforms, there is a minimum size for a shell
- * which may be greater than the label size.
- * To avoid having the background of the tip shell showing
- * around the label, force the label to fill the entire client area.
- */
- Rectangle area = tip.getClientArea();
- label.setSize(area.width, area.height);
- /*
- * Position the tooltip and ensure that it is not located off
- * the screen.
- */
- Point pt = new Point(item.x + item.width / 4, item.y + item.height + 2);
- pt = toDisplay(pt);
- Rectangle rect = display.getBounds();
- Point tipSize = tip.getSize();
- pt.x = Math.max (0, Math.min (pt.x, rect.width - tipSize.x));
- pt.y = Math.max (0, Math.min (pt.y, rect.height - tipSize.y));
- tip.setLocation(pt);
- tip.setVisible(true);
- return;
- }
- }
-
- toolTipItem = null;
- if (tip != null && !tip.isDisposed() && tip.isVisible()) tip.setVisible(false);
-}
-private void onMouseMove(Event event) {
- if (showToolTip) {
- showToolTip(event.x, event.y);
- }
-
- if (!showClose) return;
-
- CTabItem item = null;
- for (int i=0; i<items.length; i++) {
- Rectangle rect = items[i].getBounds();
- if (rect.contains(new Point(event.x, event.y))) {
- item = items[i];
- break;
}
+ };
+ for (int i = 0; i < events.length; i++) {
+ addListener(events[i], listener[0]);
}
- if (item == inactiveItem) return;
-
- inactiveCloseBar.setVisible(false);
- inactiveItem = null;
-
- if (item == null || item == getSelection()) return;
-
- int toolbarHeight = tabHeight - CTabItem.TOP_MARGIN - CTabItem.BOTTOM_MARGIN + 2; // +2 to ignore gap between focus rectangle
- Point size = inactiveCloseBar.computeSize(SWT.DEFAULT, toolbarHeight);
- int x = item.x + item.width - size.x - 2; // -2 to not overlap focus rectangle and trim
- int y = item.y + Math.max(0, (item.height - toolbarHeight)/2);
- Rectangle toolspace = getToolSpace();
- Point folderSize = getSize();
- if ((toolspace.width == 0 || x < toolspace.x) && x + size.x < folderSize.x - borderRight) {
- inactiveCloseBar.setBounds(x, y, size.x, toolbarHeight);
- inactiveCloseBar.setVisible(true);
- inactiveItem = item;
- }
-}
-private void onTraverse (Event event) {
- switch (event.detail) {
- case SWT.TRAVERSE_ESCAPE:
-// TEMPORARY CODE See bug report 17372
-// case SWT.TRAVERSE_RETURN:
- case SWT.TRAVERSE_TAB_NEXT:
- case SWT.TRAVERSE_TAB_PREVIOUS:
- event.doit = true;
- break;
- case SWT.TRAVERSE_MNEMONIC:
- event.doit = onMnemonic(event);
- if (event.doit) event.detail = SWT.TRAVERSE_NONE;
- break;
- case SWT.TRAVERSE_PAGE_NEXT:
- case SWT.TRAVERSE_PAGE_PREVIOUS:
- event.doit = onPageTraversal(event);
- if (event.doit) event.detail = SWT.TRAVERSE_NONE;
- break;
- }
-}
-
-private boolean onPageTraversal(Event event) {
- int count = getItemCount ();
- if (count == 0) return false;
- int index = getSelectionIndex ();
- if (index == -1) {
- index = 0;
- } else {
- int offset = (event.detail == SWT.TRAVERSE_PAGE_NEXT) ? 1 : -1;
- index = (index + offset + count) % count;
- }
- setSelection (index, true);
- return true;
-}
-
-/**
- * Answer true if not all tabs can be visible in the receive
- * thus requiring the scroll buttons to be visible.
- */
-private boolean scroll_leftVisible() {
- return topTabIndex > 0;
-}
-
-/**
- * Answer true if not all tabs can be visible in the receive
- * thus requiring the scroll buttons to be visible.
- */
-private boolean scroll_rightVisible() {
- // only show Scroll buttons if there is more than one item
- // and if we are not already at the last item
- if (items.length < 2) return false;
- Rectangle area = getClientArea();
- int rightEdge = area.x + area.width;
- if (rightEdge <= 0) return false;
- if (topTabIndex > 0) {
- rightEdge -= arrowBar.getSize().x;
- }
- if (topRight != null) {
- rightEdge -= topRight.getSize().x;
- }
- CTabItem item = items[items.length-1];
- return (item.x + item.width > rightEdge);
-}
-
-/**
- * Scroll the tab items to the left.
- */
-private void scroll_scrollLeft() {
- if (items.length == 0) return;
- setLastItem(topTabIndex - 1);
-}
-
-/**
- * Scroll the tab items to the right.
- */
-private void scroll_scrollRight() {
- int lastIndex = getLastItem();
- topTabIndex = lastIndex + 1;
- setItemLocation();
- correctLastItem();
- redrawTabArea(-1);
-}
-private boolean correctLastItem() {
- Rectangle area = getClientArea();
- int rightEdge = area.x + area.width;
- if (rightEdge <= 0) return false;
- Rectangle toolspace = getToolSpace();
- if (toolspace.width > 0) {
- rightEdge -= toolspace.width;
- }
- CTabItem item = items[items.length - 1];
- if (item.x + item.width < rightEdge) {
- setLastItem(items.length - 1);
- return true;
- }
- return false;
+ tipShowing = true;
+ tip.setVisible(true);
}
-/**
- * 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
- * is greater. Specifying a height of 0 will revert to the default height.
- *
- * @param height the pixel value of the height or 0
- *
- * @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>
- * <li>ERROR_INVALID_ARGUMENT - if called with a height of less than 0</li>
- * </ul>
- */
-public void setTabHeight(int height) {
- checkWidget();
- if (height < 0) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+boolean updateItems() {
+ boolean changed = false;
+ if (setItemSize()) changed = true;
+ if (setItemLocation()) changed = true;
+ if (setButtonBounds()) changed = true;
+ if (selectedIndex != -1) {
+ int top = topTabIndex;
+ showItem(items[selectedIndex]);
+ if (top != topTabIndex) changed = true;
}
- fixedTabHeight = true;
- if (tabHeight == height) return;
- tabHeight = height;
- oldSize = null;
- notifyListeners(SWT.Resize, new Event());
+ return changed;
}
-void resetTabSize(boolean checkHeight){
- int oldHeight = tabHeight;
- if (!fixedTabHeight && checkHeight) {
+boolean updateTabHeight(int oldHeight, boolean force){
+ if (!fixedTabHeight) {
int tempHeight = 0;
GC gc = new GC(this);
for (int i=0; i < items.length; i++) {
tempHeight = Math.max(tempHeight, items[i].preferredHeight(gc));
}
gc.dispose();
- if (topRight != null) tempHeight = Math.max(tempHeight, topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
tabHeight = tempHeight;
}
-
- if (tabHeight != oldHeight){
- oldSize = null;
- notifyListeners(SWT.Resize, new Event());
+ if (!force && tabHeight == oldHeight) return false;
+
+ oldSize = null;
+ if (onBottom) {
+ curve = bezier(0, tabHeight + 2,
+ CURVE_LEFT, tabHeight + 2,
+ CURVE_WIDTH - CURVE_RIGHT, 1,
+ CURVE_WIDTH, 1,
+ CURVE_WIDTH);
+ // workaround to get rid of blip at end of bezier
+ int index = -1;
+ for (int i = 0; i < curve.length/2; i++) {
+ if (curve[2*i+1] > tabHeight) {
+ index = i;
+ } else {
+ break;
+ }
+ }
+ if (index > 0) {
+ int[] newCurve = new int[curve.length - 2*(index-1)];
+ System.arraycopy(curve, 2*(index-1), newCurve, 0, newCurve.length);
+ curve = newCurve;
+ }
} else {
- setItemBounds();
- redraw();
+ curve = bezier(0, 0,
+ CURVE_LEFT, 0,
+ CURVE_WIDTH - CURVE_RIGHT, tabHeight + 2,
+ CURVE_WIDTH, tabHeight + 2,
+ CURVE_WIDTH);
+ // workaround to get rid of blip at end of bezier
+ int index = -1;
+ for (int i = 0; i < curve.length/2; i++) {
+ if (curve[2*i+1] > tabHeight) {
+ index = i;
+ break;
+ }
+ }
+ if (index > 0) {
+ int[] newCurve = new int[2*(index-1)];
+ System.arraycopy(curve, 0, newCurve, 0, newCurve.length);
+ curve = newCurve;
+ }
}
+
+ notifyListeners(SWT.Resize, new Event());
+ return true;
}
+boolean updateToolTip (int x, int y, Label label) {
+ CTabItem item = getItem(new Point (x, y));
+ if (item == null) return false;
+ String tooltip = item.getToolTipText();
+ if (tooltip == null) return false;
+ if (tooltip.equals(label.getText())) return true;
+
+ Shell tip = label.getShell();
+ label.setText(tooltip);
+ Point labelSize = label.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ labelSize.x += 2; labelSize.y += 2;
+ label.setSize(labelSize);
+ tip.pack();
+ /*
+ * On some platforms, there is a minimum size for a shell
+ * which may be greater than the label size.
+ * To avoid having the background of the tip shell showing
+ * around the label, force the label to fill the entire client area.
+ */
+ Rectangle area = tip.getClientArea();
+ label.setSize(area.width, area.height);
+ /*
+ * Position the tooltip and ensure that it is not located off
+ * the screen.
+ */
+ Point cursorLocation = getDisplay().getCursorLocation();
+ // Assuming cursor is 21x21 because this is the size of
+ // the arrow cursor on Windows
+ int cursorHeight = 21;
+ Point size = tip.getSize();
+ Rectangle rect = tip.getMonitor().getBounds();
+ Point pt = new Point(cursorLocation.x, cursorLocation.y + cursorHeight + 2);
+ pt.x = Math.max(pt.x, rect.x);
+ if (pt.x + size.x > rect.x + rect.width) pt.x = rect.x + rect.width - size.x;
+ if (pt.y + size.y > rect.y + rect.height) {
+ pt.y = cursorLocation.y - 2 - size.y;
+ }
+ tip.setLocation(pt);
+ return true;
}
+} \ No newline at end of file
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 5dd95f90b1..35ab2f0c79 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
@@ -15,26 +15,35 @@ import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
+
+/**
+* DO NOT USE - UNDER CONSTRUCTION
+*
+*/
+
public class CTabItem extends Item {
CTabFolder parent;
int x,y,width,height = 0;
- String toolTipText;
Control control; // the tab page
-
- private Image disabledImage;
-
- // internal constants
- static final int LEFT_MARGIN = 4;
- static final int RIGHT_MARGIN = 4;
- static final int TOP_MARGIN = 3;
- static final int BOTTOM_MARGIN = 3;
- private static final int INTERNAL_SPACING = 2;
-
- private static final String ellipsis = "..."; //$NON-NLS-1$
+ String toolTipText;
+ Image disabledImage;
String shortenedText;
int shortenedTextWidth;
+ Rectangle closeRect = new Rectangle(0, 0, 0, 0);
+ int closeImageState = CTabFolder.NONE;
+ boolean showClose = false;
+
+ // internal constants
+ static final int LEFT_MARGIN = 7;
+ static final int RIGHT_MARGIN = 6;
+ static final int TOP_MARGIN = 2;
+ static final int BOTTOM_MARGIN = 2;
+ static final int INTERNAL_SPACING = 2;
+ static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC;
+ static final String ellipsis = "..."; //$NON-NLS-1$
+
/**
* Constructs a new instance of this class given its parent
* (which must be a <code>CTabFolder</code>) and a style value
@@ -61,7 +70,7 @@ public class CTabItem extends Item {
* </ul>
*
* @see SWT
- * @see Widget#getStyle
+ * @see Widget#getStyle()
*/
public CTabItem (CTabFolder parent, int style) {
this(parent, style, parent.getItemCount());
@@ -93,30 +102,367 @@ public CTabItem (CTabFolder parent, int style) {
* </ul>
*
* @see SWT
- * @see Widget#getStyle
+ * @see Widget#getStyle()
*/
public CTabItem (CTabFolder parent, int style, int index) {
super (parent, checkStyle(style));
+ showClose = (style & SWT.CLOSE) != 0;
parent.createItem (this, index);
}
-private static int checkStyle(int style) {
+static int checkStyle(int style) {
return SWT.NONE;
}
-
-public void dispose () {
- if (isDisposed()) return;
+static String shortenText(GC gc, String text, int width) {
+ if (gc.textExtent(text, FLAGS).x <= width) return text;
+
+ int ellipseWidth = gc.textExtent(ellipsis, FLAGS).x;
+ int length = text.length();
+ int end = length - 1;
+ while (end > 0) {
+ text = text.substring(0, end);
+ int l1 = gc.textExtent(text, FLAGS).x;
+ if (l1 + ellipseWidth <= width) {
+ return text + ellipsis;
+ }
+ end--;
+ }
+ return text + ellipsis;
+}
+public void dispose() {
+ if (isDisposed ()) return;
+ //if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
parent.destroyItem(this);
super.dispose();
parent = null;
control = null;
toolTipText = null;
+ shortenedText = null;
}
+void drawClose(GC gc) {
+ if (closeRect.width == 0 || closeRect.height == 0) return;
+ Display display = getDisplay();
+
+ // draw X (10x10 or 11x11)
+ int indent = Math.max(1, (parent.tabHeight-11)/2);
+ int x = closeRect.x + indent - 1;
+ int y = closeRect.y + indent;
+ 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(SWT.COLOR_WHITE));
+ gc.fillPolygon(shape);
+ gc.setForeground(CTabFolder.borderColor);
+ 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(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.fillPolygon(shape);
+ Color border = new Color(display, CTabFolder.CLOSE_BORDER);
+ gc.setForeground(border);
+ gc.drawPolygon(shape);
+ border.dispose();
+ 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};
+ Color fill = new Color(display, CTabFolder.CLOSE_FILL);
+ gc.setBackground(fill);
+ gc.fillPolygon(shape);
+ fill.dispose();
+ Color border = new Color(display, CTabFolder.CLOSE_BORDER);
+ gc.setForeground(border);
+ gc.drawPolygon(shape);
+ border.dispose();
+ break;
+ }
+ case CTabFolder.NONE: {
+ int[] shape = new int[] {x,y, x+10,y, x+10,y+10, x,y+10};
+ parent.drawBackground(gc, shape, false);
+ break;
+ }
+ }
+}
+void drawSelected(GC gc ) {
+ Point size = parent.getSize();
+ // Draw selection border across all tabs
+ int parentX = parent.borderLeft;
+ int parentY = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - CTabFolder.HIGHLIGHT_HEADER : parent.borderTop + parent.tabHeight + 1;
+ int parentWidth = size.x - parent.borderLeft - parent.borderRight;
+ int parentHeight = CTabFolder.HIGHLIGHT_HEADER - 1;
+ int[] shape = new int[] {parentX,parentY, parentX+parentWidth,parentY, parentX+parentWidth,parentY+parentHeight, parentX,parentY+parentHeight};
+ parent.drawBackground(gc, shape, true);
+
+ // if selected tab scrolled out of view or partially out of view
+ // draw line and clean up partial tab area
+ int rightTabEdge = parent.getRightItemEdge();
+ if (!parent.single && parent.selectedIndex != parent.topTabIndex && x + width >= rightTabEdge){
+ if (parent.onBottom) {
+ shape = new int[4];
+ int index = 0;
+ shape[index++] = Math.max(0, parent.borderLeft - 1);
+ shape[index++] = y - 1;
+ shape[index++] = size.x - parent.borderRight;
+ shape[index++] = y - 1;
+ } else {
+ shape = new int[4];
+ int index = 0;
+ shape[index++] = Math.max(0, parent.borderLeft - 1);
+ shape[index++] = y + height;
+ shape[index++] = size.x - parent.borderRight;
+ shape[index++] = y + height;
+ }
+ // draw line
+ gc.setForeground(CTabFolder.borderColor);
+ gc.drawPolyline(shape);
+ // if tab partially visible, fill in background for tab
+ shape = new int[] {x,y-1, x,y+height, size.x,y+height, size.x,y-1};
+ parent.drawBackground(gc, shape, false);
+ return;
+ }
+
+ // fill in background for non-rectangular shape
+ shape = new int[] {x,y, x+width,y, x+width,y+height, x,y+height};
+ parent.drawBackground(gc, shape, false);
+
+ // draw selected tab background and outline
+ int extra = CTabFolder.CURVE_WIDTH/2 + 4; // +4 to avoid overlapping with text in next tab
+ shape = null;
+ if (this.parent.onBottom) {
+ int[] left = CTabFolder.BOTTOM_LEFT_CORNER;
+ int[] right = parent.curve;
+ 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++] = x + width - extra + right[2*i];
+ shape[index++] = y + right[2*i+1] - 2;
+ }
+ int temp = 0;
+ for (int i = 0; i < shape.length/2; i++) {
+ if (shape[2*i] > rightTabEdge) {
+ if (temp == 0 && i > 0) {
+ temp = shape[2*i-1];
+ } else {
+ temp = y - 1;
+ }
+ shape[2*i] = rightTabEdge;
+ shape[2*i+1] = temp;
+ }
+ }
+ shape[index++] = rightTabEdge;
+ shape[index++] = y - 1;
+ shape[index++] = x + width + extra;
+ shape[index++] = y - 1;
+ } else {
+ int[] left = CTabFolder.TOP_LEFT_CORNER;
+ int[] right = parent.curve;
+ 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;
+ 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];
+ }
+ for (int i = 0; i < right.length/2; i++) {
+ shape[index++] = x + width - extra + right[2*i];
+ shape[index++] = y + right[2*i+1];
+ }
+ int temp = 0;
+ for (int i = 0; i < shape.length/2; i++) {
+ if (shape[2*i] > rightTabEdge) {
+ if (temp == 0 && i > 0) {
+ temp = shape[2*i-1];
+ } else {
+ temp = y + height + 1;
+ }
+ shape[2*i] = rightTabEdge;
+ shape[2*i+1] = temp;
+ }
+ }
+ shape[index++] = rightTabEdge;
+ shape[index++] = y + height + 1;
+ shape[index++] = x + width + extra;
+ shape[index++] = y + height + 1;
+ }
+ parent.drawBackground(gc, shape, true);
+
+ // Limit drawing area of tab
+ Region r = new Region();
+ r.subtract(r); //clear
+ Region clipping = new Region();
+ gc.getClipping(clipping);
+ r.add(clipping);
+ r.intersect(new Rectangle(x, y, Math.min(width, rightTabEdge-x), height));
+ gc.setClipping(r);
+ // draw Image
+ int xDraw = x + LEFT_MARGIN;
+ Image image = getImage();
+ if (image != null) {
+ Rectangle imageBounds = image.getBounds();
+ 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 (closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING;
+ 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);
+
+ if (parent.showClose || showClose) drawClose(gc);
+
+ // draw a Focus rectangle
+ if (parent.isFocusControl()) {
+ Display display = getDisplay();
+ gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.drawFocus(xDraw-3, textY-2, extent.x+6, extent.y+4);
+ }
+
+ gc.setClipping(clipping);
+ r.dispose();
+ clipping.dispose();
+
+ // draw outline
+ shape[0] = Math.max(0, parent.borderLeft - 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;
+ }
+ RGB inside = parent.selectionBackground.getRGB();
+ if (parent.selectionBgImage != null || (parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1 && !parent.selectionGradientVertical)) inside = null;
+ RGB outside = parent.getBackground().getRGB();
+ if (parent.bgImage != null || (parent.gradientColors != null && parent.gradientColors.length > 1 && !parent.gradientVertical)) outside = null;
+ parent.antialias(shape, CTabFolder.borderColor.getRGB(), inside, outside, gc);
+ gc.setForeground(CTabFolder.borderColor);
+ gc.drawPolyline(shape);
+}
+void drawUnselected(GC gc) {
+ int rightTabEdge = parent.getRightItemEdge();
+ if (x >= parent.getSize().x) return;
+ // Do not draw partial items
+ if (parent.items[parent.topTabIndex] != this && x + width >= rightTabEdge){
+ int x1 = x, y1 = y-1;
+ int x2 = parent.getSize().x, y2 = y + height;
+ int[] shape = new int[]{x1,y1, x1,y2, x2,y2, x2,y1};
+ parent.drawBackground(gc, shape, false);
+ return;
+ }
+ // draw background
+ int[] shape = null;
+ if (parent.indexOf(this) == parent.topTabIndex) {
+ if (this.parent.onBottom) {
+ int[] left = CTabFolder.BOTTOM_LEFT_CORNER;
+ shape = new int[left.length + 6];
+ int index = 0;
+ shape[index++] = x;
+ shape[index++] = y;
+ for(int i = 0; i < left.length/2; i++) {
+ shape[index++] = x + left[2*i];
+ shape[index++] = y + height + left[2*i+1];
+ }
+ shape[index++]= x + width;
+ shape[index++]= y + height;
+ shape[index++]= x + width;
+ shape[index++]= y;
+ } else {
+ int[] left = CTabFolder.TOP_LEFT_CORNER;
+ shape = new int[left.length + 6];
+ 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];
+ }
+ shape[index++] = x + width;
+ shape[index++] = y;
+ shape[index++] = x + width;
+ shape[index++] = y + height;
+ }
+ parent.drawBackground(gc, shape, false);
+ // Shape is non-rectangular, fill in gaps with parent colours
+ Region r = new Region();
+ r.add(new Rectangle(x, y, width, height));
+ r.subtract(shape);
+ gc.setBackground(parent.getParent().getBackground());
+ CTabFolder.fillRegion(gc, r);
+ r.dispose();
+ } else {
+ shape = new int[8];
+ shape[0] = x;
+ shape[1] = y;
+ shape[2] = x;
+ shape[3] = y + height;
+ shape[4] = x + width;
+ shape[5] = y + height;
+ shape[6] = x + width;
+ shape[7] = y;
+ parent.drawBackground(gc, shape, false);
+ }
+
+ // draw border
+ if (parent.indexOf(this) != parent.selectedIndex - 1) {
+ gc.setForeground(CTabFolder.borderColor);
+ gc.drawLine(x + width - 1, y, x + width - 1, y + height);
+ }
+
+ // draw Text
+ int textWidth = width - LEFT_MARGIN - RIGHT_MARGIN;
+ if (closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING;
+ 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, x + LEFT_MARGIN, textY, FLAGS);
+
+ if (parent.showClose || showClose) drawClose(gc);
+}
/**
* Returns a rectangle describing the receiver's size and location
* relative to its parent.
*
- * @param index the index that specifies the column
* @return the receiver's bounding column rectangle
*
* @exception SWTException <ul>
@@ -133,10 +479,10 @@ public Rectangle getBounds () {
*
* @return the control
*
-* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
-* when called from the wrong thread
-* @exception SWTError(ERROR_WIDGET_DISPOSED)
-* when the widget has been disposed
+* @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>
*/
public Control getControl () {
checkWidget();
@@ -146,6 +492,11 @@ public Control getControl () {
* Get the image displayed in the tab if the tab is disabled.
*
* @return the disabled image or null
+ *
+ * @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>
*/
public Image getDisabledImage(){
//checkWidget();
@@ -155,6 +506,11 @@ public Image getDisabledImage(){
* Returns the receiver's parent, which must be a <code>CTabFolder</code>.
*
* @return the receiver's parent
+ *
+ * @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>
*/
public CTabFolder getParent () {
//checkWidget();
@@ -173,249 +529,42 @@ public CTabFolder getParent () {
*/
public String getToolTipText () {
checkWidget();
+ if (toolTipText == null && shortenedText != null) {
+ String text = getText();
+ if (!shortenedText.equals(text)) return text;
+ }
return toolTipText;
}
-/**
- * Paint the receiver.
- */
void onPaint(GC gc, boolean isSelected) {
-
if (width == 0 || height == 0) return;
-
- Display display = getDisplay();
- Color highlightShadow = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
- Color normalShadow = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
-
- int index = parent.indexOf(this);
-
if (isSelected) {
-
- Rectangle bounds = null;
- if (!parent.onBottom) {
- if (index == parent.topTabIndex) {
- bounds = new Rectangle(x + 1, y + 1, width - 2, height - 1);
- } else {
- bounds = new Rectangle(x + 2, y + 1, width - 3, height - 1);
- }
- } else {
- if (index == parent.topTabIndex) {
- bounds = new Rectangle(x + 1, y + 1, width - 2, height - 2);
- } else {
- bounds = new Rectangle(x + 2, y + 1, width - 3, height - 2);
- }
- }
- if (parent.backgroundImage != null) {
- // draw a background image behind the text
- Rectangle imageRect = parent.backgroundImage.getBounds();
- gc.drawImage(parent.backgroundImage, 0, 0, imageRect.width, imageRect.height,
- bounds.x, bounds.y, bounds.width, bounds.height);
- } else if (parent.gradientColors != null) {
- // draw a gradient behind the text
- Color oldBackground = gc.getBackground();
- if (parent.gradientColors.length == 1) {
- if (parent.gradientColors[0] != null) gc.setBackground(parent.gradientColors[0]);
- gc.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height);
- } else {
- Color oldForeground = gc.getForeground();
- Color lastColor = parent.gradientColors[0];
- if (lastColor == null) lastColor = oldBackground;
- for (int i = 0, pos = 0; i < parent.gradientPercents.length; ++i) {
- gc.setForeground(lastColor);
- lastColor = parent.gradientColors[i + 1];
- if (lastColor == null) lastColor = oldBackground;
- gc.setBackground(lastColor);
- int gradientWidth = (parent.gradientPercents[i] * bounds.width / 100) - pos;
- gc.fillGradientRectangle(bounds.x + pos, bounds.y, gradientWidth, bounds.height, false);
- pos += gradientWidth;
- }
- gc.setForeground(oldForeground);
- }
- gc.setBackground(oldBackground);
- }
-
- // draw tab lines
- if (!parent.onBottom) {
- gc.setForeground(normalShadow);
- if (index != parent.topTabIndex) {
- gc.drawLine(x + 1, y, x + 1, y);
- gc.drawLine(x, y + 1, x, y + height - 2);
- gc.drawLine(x, y + height - 1, x, y + height - 1);
- }
- gc.drawLine(x + width - 1, y, x + width - 1, y);
- gc.drawLine(x + width, y + 1, x + width, y + height - 2);
- gc.drawLine(x + width, y + height - 1, x + width, y + height - 1);
-
- gc.setForeground(highlightShadow);
- if (index != parent.topTabIndex) {
- gc.drawLine(x + 2, y, x + 2, y);
- gc.drawLine(x + 1, y + 1, x + 1, y + height - 2);
- gc.drawLine(x + 1, y + height - 1, x + 1, y + height - 1);
- } else {
- gc.drawLine(x, y, x, y + height - 1);
- }
-
- gc.drawLine(x + width - 2, y, x + width - 2, y);
- gc.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2);
- gc.drawLine(x + width - 1, y + height - 1, x + width - 1, y + height - 1);
-
- // light line across top
- if (index != parent.topTabIndex) {
- gc.drawLine(x + 3, y, x + width - 3, y);
- } else {
- gc.drawLine(x + 1, y, x + width - 3, y);
- }
- } else {
- gc.setForeground(normalShadow);
- if (index != parent.topTabIndex) {
- gc.drawLine(x, y, x, y);
- gc.drawLine(x, y + 1, x, y + height - 2);
- gc.drawLine(x + 1, y + height - 1, x + 1, y + height - 1);
- }
- gc.drawLine(x + width, y, x + width, y);
- gc.drawLine(x + width, y + 1, x + width, y + height - 2);
- gc.drawLine(x + width - 1, y + height - 1, x + width - 1, y + height - 1);
-
- gc.setForeground(highlightShadow);
- if (index != parent.topTabIndex) {
- gc.drawLine(x + 1, y, x + 1, y);
- gc.drawLine(x + 1, y + 1, x + 1, y + height - 2);
- gc.drawLine(x + 2, y + height - 1, x + 2, y + height - 1);
- } else {
- gc.drawLine(x, y, x, y + height - 1);
- }
-
- gc.drawLine(x + width - 1, y, x + width - 1, y);
- gc.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2);
- gc.drawLine(x + width - 2, y + height - 1, x + width - 2, y + height - 1);
-
- // light line across top and bottom
- if (index != parent.topTabIndex) {
- gc.drawLine(x + 1, y, x + width - 2, y);
- gc.drawLine(x + 2, y + height - 1, x + width - 3, y + height - 1);
- } else {
- gc.drawLine(x + 1, y, x + width - 2, y);
- gc.drawLine(x + 1, y + height - 1, x + width - 3, y + height - 1);
- }
- }
- if (parent.isFocusControl()) {
- // draw a focus rectangle
- int x1, y1, width1, height1;
- if (!parent.onBottom) {
- if (index == parent.topTabIndex) {
- x1 = x + 1; y1 = y + 1; width1 = width - 2; height1 = height - 1;
- } else {
- x1 = x + 2; y1 = y + 1; width1 = width - 3; height1 = height - 1;
- }
- } else {
- if (index == parent.topTabIndex) {
- x1 = x + 1; y1 = y + 1; width1 = width - 2; height1 = height - 2;
- } else {
- x1 = x + 2; y1 = y + 1; width1 = width - 3; height1 = height - 2;
- }
- }
- gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
- gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- gc.drawFocus(x1, y1, width1, height1);
- }
+ drawSelected(gc);
} else {
- // draw tab lines for unselected items
- gc.setForeground(normalShadow);
- if (!parent.onBottom) {
- if (index != parent.topTabIndex && index != parent.getSelectionIndex() + 1) {
- gc.drawLine(x, y, x, y + (height / 2));
- }
- } else {
- if (index != parent.topTabIndex && index != parent.getSelectionIndex() + 1) {
- gc.drawLine(x, y + (height / 2), x, y + height - 1);
- }
- }
-
+ drawUnselected(gc);
}
-
- // draw Image
- int xDraw = x + LEFT_MARGIN;
-
- Image image = getImage();
- if (!isSelected && image != null) {
- Image temp = getDisabledImage();
- if (temp != null){
- image = temp;
- }
- }
- if (image != null) {
- Rectangle imageBounds = image.getBounds();
- int imageX = xDraw;
- int imageHeight = Math.min(height - BOTTOM_MARGIN - TOP_MARGIN, imageBounds.height);
- int imageY = y + (height - imageHeight) / 2;
- int imageWidth = imageBounds.width * imageHeight / imageBounds.height;
- gc.drawImage(image,
- imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height,
- imageX, imageY, imageWidth, imageHeight);
- xDraw += imageWidth + INTERNAL_SPACING;
- }
-
- // draw Text
- int textWidth = x + width - xDraw - RIGHT_MARGIN;
- if (isSelected && parent.showClose) {
- textWidth = x + width - xDraw - parent.closeBar.getSize().x - RIGHT_MARGIN;
- }
- if (shortenedText == null || shortenedTextWidth != textWidth) {
- shortenedText = shortenText(gc, getText(), textWidth);
- shortenedTextWidth = textWidth;
- }
- String text = shortenedText;
-
- if (isSelected && parent.selectionForeground != null) {
- gc.setForeground(parent.selectionForeground);
- } else {
- gc.setForeground(parent.getForeground());
- }
- int textY = y + (height - gc.textExtent(text, SWT.DRAW_MNEMONIC).y) / 2;
- gc.drawText(text, xDraw, textY, SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC);
-
- gc.setForeground(parent.getForeground());
}
-private static String shortenText(GC gc, String text, int width) {
- if (gc.textExtent(text, SWT.DRAW_MNEMONIC).x <= width) return text;
-
- int ellipseWidth = gc.textExtent(ellipsis, SWT.DRAW_MNEMONIC).x;
- int length = text.length();
- int end = length - 1;
- while (end > 0) {
- text = text.substring(0, end);
- int l1 = gc.textExtent(text, SWT.DRAW_MNEMONIC).x;
- if (l1 + ellipseWidth <= width) {
- return text + ellipsis;
- }
- end--;
- }
- return text + ellipsis;
-}
-/**
- * Answer the preferred height of the receiver for the GC.
- */
int preferredHeight(GC gc) {
Image image = getImage();
- int height = 0;
- if (image != null) height = image.getBounds().height;
+ int h = (image == null) ? 0 : image.getBounds().height;
String text = getText();
- height = Math.max(height, gc.textExtent(text, SWT.DRAW_MNEMONIC).y);
- return height + TOP_MARGIN + BOTTOM_MARGIN;
+ h = Math.max(h, gc.textExtent(text, FLAGS).y);
+ return h + TOP_MARGIN + BOTTOM_MARGIN;
}
-/**
- * Answer the preferred width of the receiver for the GC.
- */
-int preferredWidth(GC gc) {
- int width = 0;
+int preferredWidth(GC gc, boolean isSelected) {
+ int w = 0;
Image image = getImage();
- if (image != null) width += image.getBounds().width;
+ if (isSelected && image != null) w += image.getBounds().width;
String text = getText();
if (text != null) {
- if (image != null) width += INTERNAL_SPACING;
- width += gc.textExtent(text, SWT.DRAW_MNEMONIC).x;
+ if (w > 0) w += INTERNAL_SPACING;
+ w += gc.textExtent(text, FLAGS).x;
+ }
+ if (parent.showClose || showClose) {
+ if (w > 0) w += INTERNAL_SPACING;
+ w += CTabFolder.BUTTON_SIZE;
}
- if (parent.showClose) width += INTERNAL_SPACING + preferredHeight(gc); // closebar will be square and will fill preferred height
- return width + LEFT_MARGIN + RIGHT_MARGIN;
+ if (isSelected) w += 8; // why 8?
+ return w + LEFT_MARGIN + RIGHT_MARGIN;
}
/**
* Sets the control that is used to fill the client area of
@@ -451,12 +600,6 @@ public void setControl (Control control) {
this.control.setVisible(false);
}
}
-}
-public void setImage (Image image) {
- checkWidget();
- if (image != null && image.equals(getImage())) return;
- super.setImage(image);
- parent.resetTabSize(true);
}
/**
* Sets the image that is displayed if the tab item is disabled.
@@ -471,19 +614,25 @@ public void setImage (Image image) {
*/
public void setDisabledImage (Image image) {
checkWidget();
+ // !!! this image is never being used
if (image != null && image.equals(getDisabledImage())) return;
disabledImage = image;
+ //parent.redraw();
+}
+public void setImage (Image image) {
+ checkWidget();
+ if (image != null && image.equals(getImage())) return;
+ super.setImage(image);
+ if (!parent.updateTabHeight(parent.tabHeight, false)) {
+ parent.updateItems();
+ }
parent.redraw();
}
-
/**
* Set the widget text.
* <p>
* This method sets the widget label. The label may include
* mnemonic characters but must not contain line delimiters.
- * The mnemonic indicator character '&amp' can be escaped by
- * doubling it in the string, causing a single '&amp' to be
- * displayed.
*
* @param string the new label for the widget
*
@@ -501,7 +650,8 @@ public void setText (String string) {
super.setText(string);
shortenedText = null;
shortenedTextWidth = 0;
- parent.resetTabSize(false);
+ parent.updateItems();
+ parent.redraw();
}
/**
* Sets the receiver's tool tip text to the argument, which