BugĀ 510728 - [CSS] Allow styling of tree headers via CSS
Add the API for all platforms and implemented Windows.
Change-Id: I714b8961c9db7c9648a29b0b4cb638cf4f16942f
Signed-off-by: Conrad Groth <info@conrad-groth.de>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java
index c2dc4e5..a59c10e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java
@@ -2621,10 +2621,9 @@
* Sets the header background color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only on Windows and GTK3
- * platforms table header background can be changed. If the native header
- * has a 3D look an feel (e.g. Windows 7), this method will cause the header
- * to look FLAT irrespective of the state of the table style.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
@@ -2654,7 +2653,9 @@
* Sets the header foreground color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only Windows table header foreground can be changed.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java
index 672e6ac..2039e16 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -88,6 +88,7 @@
Rectangle imageBounds;
TreeItem insertItem;
boolean insertBefore;
+ double /*float*/ [] headerBackground, headerForeground;
/* Used to control drop feedback when DND.FEEDBACK_EXPAND and DND.FEEDBACK_SCROLL is set/not set */
boolean shouldExpand = true, shouldScroll = true;
@@ -1542,6 +1543,46 @@
}
/**
+ * Returns the header background color.
+ *
+ * @return the receiver's header background color.
+ *
+ * @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.106
+ */
+public Color getHeaderBackground () {
+ checkWidget ();
+ return getHeaderBackgroundColor ();
+}
+
+private Color getHeaderBackgroundColor () {
+ return headerBackground != null ? Color.cocoa_new (display, headerBackground) : defaultBackground ();
+}
+
+/**
+ * Returns the header foreground color.
+ *
+ * @return the receiver's header foreground color.
+ *
+ * @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.106
+ */
+public Color getHeaderForeground () {
+ checkWidget ();
+ return getHeaderForegroundColor ();
+}
+
+private Color getHeaderForegroundColor () {
+ return headerForeground != null ? Color.cocoa_new (display, headerForeground) : defaultForeground ();
+}
+
+/**
* Returns the height of the receiver's header
*
* @return the height of the header or zero if the header is not visible
@@ -2866,6 +2907,70 @@
}
/**
+ * Sets the header background color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderBackground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ double /*float*/ [] headerBackground = color != null ? color.handle : null;
+ if (equals (headerBackground, this.headerBackground)) return;
+ this.headerBackground = headerBackground;
+ if (getHeaderVisible()) {
+ redrawWidget (view, false);
+ }
+}
+
+/**
+ * Sets the header foreground color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderForeground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ double /*float*/ [] headerForeground = color != null ? color.handle : null;
+ if (equals (headerForeground, this.headerForeground)) return;
+ this.headerForeground = headerForeground;
+ if (getHeaderVisible()) {
+ redrawWidget (view, false);
+ }
+}
+
+/**
* Marks the receiver's header as visible if the argument is <code>true</code>,
* and marks it invisible otherwise.
* <p>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
index cea7494..21da5ed 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
@@ -3415,10 +3415,9 @@
* Sets the header background color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only on Windows and GTK3
- * platforms table header background can be changed. If the native header
- * has a 3D look an feel (e.g. Windows 7), this method will cause the header
- * to look FLAT irrespective of the state of the table style.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
@@ -3453,23 +3452,27 @@
headerCSSBackground = css;
String finalCss = display.gtk_css_create_css_color_string (headerCSSBackground, headerCSSForeground, SWT.BACKGROUND);
for (TableColumn column : columns) {
- long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
- // Create provider as we need it attached to the proper context which is not the widget one
- long /*int*/ provider = OS.gtk_css_provider_new ();
- OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- OS.g_object_unref (provider);
- OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
- OS.gtk_style_context_invalidate(context);
+ if (column != null) {
+ long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
+ // Create provider as we need it attached to the proper context which is not the widget one
+ long /*int*/ provider = OS.gtk_css_provider_new ();
+ OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ OS.g_object_unref (provider);
+ OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
+ OS.gtk_style_context_invalidate(context);
+ }
}
}
- // redrawn not necessary, GTK handles the css update
+ // Redraw not necessary, GTK handles the CSS update.
}
/**
* Sets the header foreground color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only Windows table header foreground can be changed.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
@@ -3503,16 +3506,18 @@
headerCSSForeground = css;
String finalCss = display.gtk_css_create_css_color_string (headerCSSBackground, headerCSSForeground, SWT.FOREGROUND);
for (TableColumn column : columns) {
- long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
- // Create provider as we need it attached to the proper context which is not the widget one
- long /*int*/ provider = OS.gtk_css_provider_new ();
- OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- OS.g_object_unref (provider);
- OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
- OS.gtk_style_context_invalidate(context);
+ if (column != null) {
+ long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
+ // Create provider as we need it attached to the proper context which is not the widget one
+ long /*int*/ provider = OS.gtk_css_provider_new ();
+ OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ OS.g_object_unref (provider);
+ OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
+ OS.gtk_style_context_invalidate(context);
+ }
}
}
- // redrawn not necessary, GTK handles the css update
+ // Redraw not necessary, GTK handles the CSS update.
}
/**
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
index f2800e1..9bf1b1d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -95,6 +95,8 @@
int pixbufHeight, pixbufWidth;
TreeItem topItem;
double cachedAdjustment, currentAdjustment;
+ Color headerBackground, headerForeground;
+ String headerCSSBackground, headerCSSForeground;
static final int ID_COLUMN = 0;
static final int CHECKED_COLUMN = 1;
@@ -1448,6 +1450,38 @@
}
/**
+ * Returns the header background color.
+ *
+ * @return the receiver's header background color.
+ *
+ * @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.106
+ */
+public Color getHeaderBackground () {
+ checkWidget ();
+ return headerBackground != null ? headerBackground : display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+}
+
+/**
+ * Returns the header foreground color.
+ *
+ * @return the receiver's header foreground color.
+ *
+ * @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.106
+ */
+public Color getHeaderForeground () {
+ checkWidget ();
+ return headerForeground != null ? headerForeground : display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+}
+
+/**
* Returns the height of the receiver's header
*
* @return the height of the header or zero if the header is not visible
@@ -3421,6 +3455,115 @@
}
/**
+ * Sets the header background color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderBackground (Color color) {
+ checkWidget();
+ if (color != null) {
+ if (color.isDisposed ())
+ error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color.equals(headerBackground))
+ return;
+ } else if (headerBackground == null) return;
+ headerBackground = color;
+ if (OS.GTK3) {
+ GdkRGBA background;
+ if (headerBackground != null) {
+ background = display.toGdkRGBA(headerBackground.handle);
+ } else {
+ background = display.toGdkRGBA(display.COLOR_LIST_BACKGROUND);
+ }
+ String name = OS.GTK_VERSION >= OS.VERSION(3, 20, 0) ? "button" : "GtkButton";
+ // background works for 3.18 and later, background-color only as of 3.20
+ String css = name + " {background: " + display.gtk_rgba_to_css_string(background) + ";}\n";
+ headerCSSBackground = css;
+ String finalCss = display.gtk_css_create_css_color_string (headerCSSBackground, headerCSSForeground, SWT.BACKGROUND);
+ for (TreeColumn column : columns) {
+ if (column != null) {
+ long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
+ // Create provider as we need it attached to the proper context which is not the widget one
+ long /*int*/ provider = OS.gtk_css_provider_new ();
+ OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ OS.g_object_unref (provider);
+ OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
+ OS.gtk_style_context_invalidate(context);
+ }
+ }
+ }
+ // Redraw not necessary, GTK handles the CSS update.
+}
+
+/**
+ * Sets the header foreground color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderForeground (Color color) {
+ checkWidget();
+ if (color != null) {
+ if (color.isDisposed ())
+ error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color.equals(headerForeground))
+ return;
+ } else if (headerForeground == null) return;
+ headerForeground = color;
+ if (OS.GTK3) {
+ GdkRGBA foreground;
+ if (headerForeground != null) {
+ foreground = display.toGdkRGBA(headerForeground.handle);
+ } else {
+ foreground = display.toGdkRGBA(display.COLOR_LIST_FOREGROUND);
+ }
+ String name = OS.GTK_VERSION >= OS.VERSION(3, 20, 0) ? "button" : "GtkButton";
+ String css = name + " {color: " + display.gtk_rgba_to_css_string(foreground) + ";}";
+ headerCSSForeground = css;
+ String finalCss = display.gtk_css_create_css_color_string (headerCSSBackground, headerCSSForeground, SWT.FOREGROUND);
+ for (TreeColumn column : columns) {
+ if (column != null) {
+ long /*int*/ context = OS.gtk_widget_get_style_context(column.buttonHandle);
+ // Create provider as we need it attached to the proper context which is not the widget one
+ long /*int*/ provider = OS.gtk_css_provider_new ();
+ OS.gtk_style_context_add_provider (context, provider, OS.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ OS.g_object_unref (provider);
+ OS.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
+ OS.gtk_style_context_invalidate(context);
+ }
+ }
+ }
+ // Redraw not necessary, GTK handles the CSS update.
+}
+
+/**
* Marks the receiver's header as visible if the argument is <code>true</code>,
* and marks it invisible otherwise.
* <p>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
index cc6214b..bf24847 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
@@ -4641,10 +4641,9 @@
* Sets the header background color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only on Windows and GTK3
- * platforms table header background can be changed. If the native header
- * has a 3D look an feel (e.g. Windows 7), this method will cause the header
- * to look FLAT irrespective of the state of the table style.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
@@ -4675,7 +4674,9 @@
* Sets the header foreground color to the color specified
* by the argument, or to the default system color if the argument is null.
* <p>
- * Note: This is custom paint operation and only Windows table header foreground can be changed.
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
* </p>
* @param color the new color (or null)
*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
index 63d4d66..c41a8d3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -93,10 +93,13 @@
boolean ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus;
boolean ignoreDrawSelection, ignoreDrawHot, ignoreFullSelection, explorerTheme;
boolean createdAsRTL;
+ boolean headerItemDragging;
int scrollWidth, selectionForeground;
long /*int*/ headerToolTipHandle, itemToolTipHandle;
long /*int*/ lastTimerID = -1;
int lastTimerCount;
+ int headerBackground = -1;
+ int headerForeground = -1;
static final boolean ENABLE_TVS_EX_FADEINOUTEXPANDOS = System.getProperty("org.eclipse.swt.internal.win32.enableFadeInOutExpandos") != null;
static final int TIMER_MAX_COUNT = 8;
static final int INSET = 3;
@@ -2341,6 +2344,10 @@
itemCount = -1;
}
+private boolean customHeaderDrawing() {
+ return headerBackground != -1 || headerForeground != -1;
+}
+
@Override
int defaultBackground () {
return OS.GetSysColor (OS.COLOR_WINDOW);
@@ -2932,6 +2939,46 @@
}
/**
+ * Returns the header background color.
+ *
+ * @return the receiver's header background color.
+ *
+ * @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.106
+ */
+public Color getHeaderBackground () {
+ checkWidget ();
+ return Color.win32_new (display, getHeaderBackgroundPixel());
+}
+
+private int getHeaderBackgroundPixel() {
+ return headerBackground != -1 ? headerBackground : defaultBackground();
+}
+
+/**
+ * Returns the header foreground color.
+ *
+ * @return the receiver's header foreground color.
+ *
+ * @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.106
+ */
+public Color getHeaderForeground () {
+ checkWidget ();
+ return Color.win32_new (display, getHeaderForegroundPixel());
+}
+
+private int getHeaderForegroundPixel() {
+ return headerForeground != -1 ? headerForeground : defaultForeground();
+}
+
+/**
* Returns the height of the receiver's header
*
* @return the height of the header or zero if the header is not visible
@@ -4279,6 +4326,7 @@
linesVisible = show;
if (hwndParent == 0 && linesVisible) customDraw = true;
OS.InvalidateRect (handle, null, true);
+ OS.InvalidateRect (hwndHeader, null, true);
}
@Override
@@ -4783,6 +4831,72 @@
}
/**
+ * Sets the header background color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderBackground (Color color) {
+ checkWidget ();
+ int pixel = -1;
+ if (color != null) {
+ if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ pixel = color.handle;
+ }
+ if (pixel == headerBackground) return;
+ headerBackground = pixel;
+ if (getHeaderVisible()) {
+ OS.InvalidateRect (hwndHeader, null, true);
+ }
+}
+
+/**
+ * Sets the header foreground color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a hint and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </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>
+ * </ul>
+ * @since 3.106
+ */
+public void setHeaderForeground (Color color) {
+ checkWidget ();
+ int pixel = -1;
+ if (color != null) {
+ if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ pixel = color.handle;
+ }
+ if (pixel == headerForeground) return;
+ headerForeground = pixel;
+ if (getHeaderVisible()) {
+ OS.InvalidateRect (hwndHeader, null, true);
+ }
+}
+
+/**
* Marks the receiver's header as visible if the argument is <code>true</code>,
* and marks it invisible otherwise.
* <p>
@@ -7853,6 +7967,142 @@
}
break;
}
+ case OS.NM_CUSTOMDRAW: {
+ NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW();
+ OS.MoveMemory(nmcd, lParam, NMCUSTOMDRAW.sizeof);
+ switch (nmcd.dwDrawStage) {
+ case OS.CDDS_PREPAINT: {
+ /* Drawing here will be deleted by further drawing steps, even with OS.CDRF_SKIPDEFAULT.
+ Changing the TextColor and returning OS.CDRF_NEWFONT has no effect. */
+ return new LRESULT (customHeaderDrawing() ? OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT : OS.CDRF_DODEFAULT);
+ }
+ case OS.CDDS_ITEMPREPAINT: {
+ // draw background
+ RECT rect = new RECT();
+ OS.SetRect(rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+ int pixel = getHeaderBackgroundPixel();
+ if ((nmcd.uItemState & OS.CDIS_SELECTED) != 0) {
+ pixel = getDifferentColor(pixel);
+ } else if (columns[(int) nmcd.dwItemSpec] == sortColumn && sortDirection != SWT.NONE) {
+ pixel = getSlightlyDifferentColor(pixel);
+ }
+ long /*int*/ brush = OS.CreateSolidBrush(pixel);
+ OS.FillRect(nmcd.hdc, rect, brush);
+ OS.DeleteObject(brush);
+
+ return new LRESULT(OS.CDRF_SKIPDEFAULT); // if we got here, we will paint everything ourself
+ }
+ case OS.CDDS_POSTPAINT: {
+ // get the cursor position
+ POINT cursorPos = new POINT();
+ OS.GetCursorPos(cursorPos);
+ OS.MapWindowPoints(0, hwndHeader, cursorPos, 1);
+
+ // drawing all cells
+ int highlightedHeaderDividerX = -1;
+ int lastColumnRight = -1;
+ RECT [] rects = new RECT [columnCount];
+ for (int i=0; i<columnCount; i++) {
+ rects [i] = new RECT ();
+ OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, rects [i]);
+ if (rects[i].right > lastColumnRight) {
+ lastColumnRight = rects[i].right;
+ }
+
+ if (columns[i] == sortColumn && sortDirection != SWT.NONE) {
+ // the display.getSortImage looks terrible after scaling up.
+ long /*int*/ pen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor(OS.COLOR_3DDKSHADOW));
+ long /*int*/ oldPen = OS.SelectObject (nmcd.hdc, pen);
+ int center = rects[i].left + (rects[i].right - rects[i].left) / 2;
+ int leg = 3;
+ if (sortDirection == SWT.UP) {
+ OS.Polyline(nmcd.hdc, new int[] {center-leg, 1+leg, center+1, 0}, 2);
+ OS.Polyline(nmcd.hdc, new int[] {center+leg, 1+leg, center-1, 0}, 2);
+ } else if (sortDirection == SWT.DOWN) {
+ OS.Polyline(nmcd.hdc, new int[] {center-leg, 1, center+1, 1+leg+1}, 2);
+ OS.Polyline(nmcd.hdc, new int[] {center+leg, 1, center-1, 1+leg+1}, 2);
+ }
+ OS.SelectObject (nmcd.hdc, oldPen);
+ OS.DeleteObject (pen);
+ }
+
+ /* Windows 7 and 10 always draw a nearly invisible vertical line between the columns, even if lines are disabled.
+ This line uses no fixed color constant, but calculates it from the background color.
+ The method getSlightlyDifferentColor gives us a color, that is near enough to the windows algorithm. */
+ long /*int*/ pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), getSlightlyDifferentColor(getHeaderBackgroundPixel()));
+ long /*int*/ oldPen = OS.SelectObject (nmcd.hdc, pen);
+ OS.Polyline(nmcd.hdc, new int[] {rects[i].right-1, rects[i].top, rects[i].right-1, rects[i].bottom}, 2);
+ OS.SelectObject (nmcd.hdc, oldPen);
+ OS.DeleteObject (pen);
+
+ if (linesVisible) {
+ pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), OS.GetSysColor(OS.COLOR_3DFACE));
+ oldPen = OS.SelectObject (nmcd.hdc, pen);
+ OS.Polyline(nmcd.hdc, new int[] {rects[i].right, rects[i].top, rects[i].right, rects[i].bottom}, 2);
+ OS.SelectObject (nmcd.hdc, oldPen);
+ OS.DeleteObject (pen);
+ }
+
+ if (headerItemDragging && highlightedHeaderDividerX == -1) {
+ int distanceToLeftBorder = cursorPos.x - rects[i].left;
+ int distanceToRightBorder = rects[i].right - cursorPos.x;
+ if (distanceToLeftBorder >= 0 && distanceToRightBorder >= 0) {
+ // the cursor is in the current rectangle
+ highlightedHeaderDividerX = distanceToLeftBorder <= distanceToRightBorder ? rects[i].left-1 : rects[i].right;
+ }
+ }
+
+ int x = rects[i].left + INSET + 2;
+ if (columns[i].image != null) {
+ GCData data = new GCData();
+ data.device = display;
+ GC gc = GC.win32_new (nmcd.hdc, data);
+ int y = Math.max (0, (nmcd.bottom - columns[i].image.getBoundsInPixels().height) / 2);
+ gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y));
+ x += columns[i].image.getBoundsInPixels().width + 12;
+ gc.dispose ();
+ }
+
+ if (columns[i].text != null) {
+ int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+ if ((columns[i].style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+ if ((columns[i].style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+ TCHAR buffer = new TCHAR (getCodePage (), columns[i].text, false);
+ OS.SetBkMode(nmcd.hdc, OS.TRANSPARENT);
+ OS.SetTextColor(nmcd.hdc, getHeaderForegroundPixel());
+ RECT textRect = new RECT();
+ textRect.left = x;
+ textRect.top = rects[i].top;
+ textRect.right = rects[i].right;
+ textRect.bottom = rects[i].bottom;
+ OS.DrawText (nmcd.hdc, buffer, buffer.length (), textRect, flags);
+ }
+ }
+
+ if (lastColumnRight < nmcd.right) {
+ // draw background of the 'no column' area
+ RECT rect = new RECT();
+ lastColumnRight += linesVisible ? 1 : 0;
+ OS.SetRect(rect, lastColumnRight, nmcd.top, nmcd.right, nmcd.bottom);
+ long /*int*/ brush = OS.CreateSolidBrush(getHeaderBackgroundPixel());
+ OS.FillRect(nmcd.hdc, rect, brush);
+ OS.DeleteObject(brush);
+ }
+
+ // always draw the highlighted border at the end, to avoid overdrawing by other borders.
+ if (highlightedHeaderDividerX != -1) {
+ long /*int*/ pen = OS.CreatePen (OS.PS_SOLID, 4, OS.GetSysColor(OS.COLOR_HIGHLIGHT));
+ long /*int*/ oldPen = OS.SelectObject (nmcd.hdc, pen);
+ OS.Polyline(nmcd.hdc, new int[] {highlightedHeaderDividerX, nmcd.top, highlightedHeaderDividerX, nmcd.bottom}, 2);
+ OS.SelectObject (nmcd.hdc, oldPen);
+ OS.DeleteObject (pen);
+ }
+
+ return new LRESULT(OS.CDRF_DODEFAULT);
+ }
+ }
+ break;
+ }
case OS.NM_RELEASEDCAPTURE: {
if (!ignoreColumnMove) {
for (int i=0; i<columnCount; i++) {
@@ -7874,10 +8124,12 @@
ignoreColumnMove = true;
return LRESULT.ONE;
}
+ headerItemDragging = true;
}
break;
}
case OS.HDN_ENDDRAG: {
+ headerItemDragging = false;
NMHEADER phdn = new NMHEADER ();
OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
if (phdn.iItem != -1 && phdn.pitem != 0) {