Bug 401015 - [CSS] Add support for styling hyperlinks in Links
Added new API for all platforms:
+ setLinkForeground(Color color) to set the color for
the hyperlink parts of the Link widget.
+ getLinkForeground() returns the link color.
Change-Id: I721a6ef921cdd754a255b5bd8f082bf7170a269d
Signed-off-by: Conrad Groth <info@conrad-groth.de>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Link.java
index 40295d4..f80dff8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Link.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Link.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Conrad Groth - Bug 401015 - [CSS] Add support for styling hyperlinks in Links
*******************************************************************************/
package org.eclipse.swt.widgets;
@@ -43,7 +44,8 @@
Point [] offsets;
String [] ids;
int [] mnemonics;
- NSColor linkColor;
+ double /*float*/ [] linkForeground;
+ NSColor defaultLinkColor;
int focusIndex;
boolean ignoreNextMouseUp;
@@ -111,35 +113,6 @@
}
@Override
-boolean textView_clickOnLink_atIndex(long /*int*/ id, long /*int*/ sel, long /*int*/ textView, long /*int*/ link, long /*int*/ charIndex) {
- NSString str = new NSString (link);
- Event event = new Event ();
- event.text = str.getString();
- sendSelectionEvent (SWT.Selection, event, true);
- // Widget may be disposed at this point.
- if (isDisposed()) return true;
- for (int i = 0; i < offsets.length; i++) {
- if ((charIndex >= offsets[i].x) && (charIndex <= offsets[i].y)) {
- focusIndex = i;
- break;
- }
- }
- redrawWidget(view, false);
- ignoreNextMouseUp = true;
- return true;
-}
-
-@Override
-boolean sendMouseEvent (NSEvent nsEvent, int type, boolean send) {
- if (type == SWT.MouseMove) {
- if (view.window().firstResponder().id != view.id) {
- mouseMoved(view.id, OS.sel_mouseMoved_, nsEvent.id);
- }
- }
- return super.sendMouseEvent(nsEvent, type, send);
-}
-
-@Override
public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget ();
if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
@@ -227,7 +200,7 @@
super.createWidget ();
text = "";
NSDictionary dict = ((NSTextView)view).linkTextAttributes();
- linkColor = new NSColor(dict.valueForKey(OS.NSForegroundColorAttributeName));
+ defaultLinkColor = new NSColor(dict.valueForKey(OS.NSForegroundColorAttributeName));
offsets = new Point [0];
ids = new String [0];
mnemonics = new int [0];
@@ -269,6 +242,15 @@
}
@Override
+void enableWidget (boolean enabled) {
+ super.enableWidget (enabled);
+ NSTextView widget = (NSTextView) view;
+ widget.setTextColor (getTextColor (enabled));
+ setLinkColor (enabled);
+ redrawWidget (view, false);
+}
+
+@Override
Cursor findCursor () {
Cursor cursor = super.findCursor();
if (cursor != null) return cursor;
@@ -281,28 +263,32 @@
return null;
}
-@Override
-void enableWidget (boolean enabled) {
- super.enableWidget (enabled);
- NSColor nsColor = null;
- if (enabled) {
- if (foreground == null) {
- nsColor = NSColor.textColor ();
- } else {
- nsColor = NSColor.colorWithDeviceRed (foreground [0], foreground [1], foreground [2], foreground[3]);
- }
- } else {
- nsColor = NSColor.disabledControlTextColor();
+/**
+ * Returns the link foreground color.
+ *
+ * @return the receiver's link 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.105
+ */
+public Color getLinkForeground () {
+ checkWidget ();
+ return Color.cocoa_new (display, display.getNSColorRGB (getLinkForegroundColor ()));
+}
+
+NSColor getLinkForegroundColor () {
+ if (linkForeground != null) {
+ return NSColor.colorWithDeviceRed (linkForeground[0], linkForeground[1], linkForeground[2], linkForeground[3]);
}
- NSTextView widget = (NSTextView)view;
- widget.setTextColor(nsColor);
- NSDictionary linkTextAttributes = widget.linkTextAttributes();
- int count = (int)/*64*/linkTextAttributes.count();
- NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity(count);
- dict.setDictionary(linkTextAttributes);
- dict.setValue(enabled ? linkColor : nsColor, OS.NSForegroundColorAttributeName);
- widget.setLinkTextAttributes(dict);
- redrawWidget(view, false);
+ return defaultLinkColor;
+}
+
+@Override
+String getNameText () {
+ return getText ();
}
NSRect[] getRectangles(int linkIndex) {
@@ -354,12 +340,6 @@
return result;
}
-@Override
-String getNameText () {
- return getText ();
-}
-
-
/**
* Returns the receiver's text, which will be an empty
* string if it has never been set.
@@ -376,6 +356,17 @@
return text;
}
+NSColor getTextColor (boolean enabled) {
+ if (enabled) {
+ if (foreground == null) {
+ return NSColor.textColor ();
+ }
+ return NSColor.colorWithDeviceRed (foreground [0], foreground [1], foreground [2], foreground[3]);
+ } else {
+ return NSColor.disabledControlTextColor();
+ }
+}
+
@Override
void mouseUp(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
/*
@@ -390,59 +381,6 @@
super.mouseUp(id, sel, theEvent);
}
-@Override
-boolean shouldDrawInsertionPoint(long /*int*/ id, long /*int*/ sel) {
- return false;
-}
-
-@Override
-void register () {
- super.register ();
- display.addWidget(scrollView, this);
-}
-
-@Override
-void releaseHandle () {
- super.releaseHandle ();
- if (scrollView != null) scrollView.release();
- scrollView = null;
-}
-
-@Override
-void releaseWidget () {
- super.releaseWidget ();
- offsets = null;
- ids = null;
- mnemonics = null;
- text = null;
- linkColor = null;
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the control is selected by the user.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException <ul>
- * <li>ERROR_NULL_ARGUMENT - if the listener is null</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>
- *
- * @see SelectionListener
- * @see #addSelectionListener
- */
-public void removeSelectionListener (SelectionListener listener) {
- checkWidget ();
- if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
- if (eventTable == null) return;
- eventTable.unhook (SWT.Selection, listener);
- eventTable.unhook (SWT.DefaultSelection, listener);
-}
-
String parse (String string) {
int length = string.length ();
offsets = new Point [length / 4];
@@ -593,6 +531,55 @@
}
@Override
+void register () {
+ super.register ();
+ display.addWidget(scrollView, this);
+}
+
+@Override
+void releaseHandle () {
+ super.releaseHandle ();
+ if (scrollView != null) scrollView.release();
+ scrollView = null;
+}
+
+@Override
+void releaseWidget () {
+ super.releaseWidget ();
+ offsets = null;
+ ids = null;
+ mnemonics = null;
+ text = null;
+ defaultLinkColor = null;
+ linkForeground = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+@Override
void scrollWheel(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
super.scrollWheel(id, sel, theEvent);
parent.scrollWheel(parent.view.id, sel, theEvent);
@@ -642,13 +629,13 @@
}
@Override
-void setBackgroundColor(NSColor nsColor) {
- setBackground(nsColor);
-}
-
-@Override
-void setBackgroundImage(NSImage image) {
- ((NSTextView) view).setDrawsBackground(image == null);
+boolean sendMouseEvent (NSEvent nsEvent, int type, boolean send) {
+ if (type == SWT.MouseMove) {
+ if (view.window().firstResponder().id != view.id) {
+ mouseMoved(view.id, OS.sel_mouseMoved_, nsEvent.id);
+ }
+ }
+ return super.sendMouseEvent(nsEvent, type, send);
}
void setBackground(NSColor nsColor) {
@@ -662,6 +649,16 @@
}
@Override
+void setBackgroundColor(NSColor nsColor) {
+ setBackground(nsColor);
+}
+
+@Override
+void setBackgroundImage(NSImage image) {
+ ((NSTextView) view).setDrawsBackground(image == null);
+}
+
+@Override
void setFont(NSFont font) {
((NSTextView) view).setFont(font);
}
@@ -669,13 +666,49 @@
@Override
void setForeground (double /*float*/ [] color) {
if (!getEnabled ()) return;
- NSColor nsColor;
- if (color == null) {
- nsColor = NSColor.textColor ();
- } else {
- nsColor = NSColor.colorWithDeviceRed (color [0], color [1], color [2], 1);
+ ((NSTextView) view).setTextColor (getTextColor (true));
+}
+
+void setLinkColor (boolean enabled) {
+ NSTextView widget = (NSTextView) view;
+ NSDictionary linkTextAttributes = widget.linkTextAttributes ();
+ int count = (int)/*64*/linkTextAttributes.count ();
+ NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity (count);
+ dict.setDictionary (linkTextAttributes);
+ dict.setValue (enabled ? getLinkForegroundColor () : getTextColor (false), OS.NSForegroundColorAttributeName);
+ widget.setLinkTextAttributes (dict);
+}
+
+/**
+ * Sets the link foreground color to the color specified
+ * by the argument, or to the default system color for the link
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </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.105
+ */
+public void setLinkForeground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
}
- ((NSTextView) view).setTextColor (nsColor);
+ double /*float*/ [] linkForeground = color != null ? color.handle : null;
+ if (equals (linkForeground, this.linkForeground)) return;
+ this.linkForeground = linkForeground;
+ if (getEnabled ()) {
+ setLinkColor (true);
+ }
+ redrawWidget (view, false);
}
@Override
@@ -748,6 +781,30 @@
}
@Override
+boolean shouldDrawInsertionPoint(long /*int*/ id, long /*int*/ sel) {
+ return false;
+}
+
+@Override
+boolean textView_clickOnLink_atIndex(long /*int*/ id, long /*int*/ sel, long /*int*/ textView, long /*int*/ link, long /*int*/ charIndex) {
+ NSString str = new NSString (link);
+ Event event = new Event ();
+ event.text = str.getString();
+ sendSelectionEvent (SWT.Selection, event, true);
+ // Widget may be disposed at this point.
+ if (isDisposed()) return true;
+ for (int i = 0; i < offsets.length; i++) {
+ if ((charIndex >= offsets[i].x) && (charIndex <= offsets[i].y)) {
+ focusIndex = i;
+ break;
+ }
+ }
+ redrawWidget(view, false);
+ ignoreNextMouseUp = true;
+ return true;
+}
+
+@Override
NSView topView () {
return scrollView;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
index d558dea..5172fcf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Conrad Groth - Bug 401015 - [CSS] Add support for styling hyperlinks in Links
*******************************************************************************/
package org.eclipse.swt.widgets;
@@ -149,7 +150,6 @@
OS.gtk_widget_set_has_window (handle, true);
OS.gtk_widget_set_can_focus (handle, true);
layout = new TextLayout (display);
- linkColor = display.getSystemColor(SWT.COLOR_LINK_FOREGROUND);
disabledColor = new Color (display, LINK_DISABLED_FOREGROUND);
offsets = new Point [0];
ids = new String [0];
@@ -191,12 +191,7 @@
void enableWidget (boolean enabled) {
super.enableWidget (enabled);
if (isDisposed ()) return;
- TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
- linkStyle.underline = true;
- for (int i = 0; i < offsets.length; i++) {
- Point point = offsets [i];
- layout.setStyle (linkStyle, point.x, point.y);
- }
+ styleLinkParts();
redraw ();
}
@@ -262,6 +257,22 @@
});
}
+/**
+ * Returns the link foreground color.
+ *
+ * @return the receiver's link 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.105
+ */
+public Color getLinkForeground () {
+ checkWidget ();
+ return linkColor != null ? linkColor : display.getSystemColor(SWT.COLOR_LINK_FOREGROUND);
+}
+
@Override
String getNameText () {
return getText ();
@@ -717,6 +728,37 @@
layout.setFont (Font.gtk_new (display, font));
}
+/**
+ * Sets the link foreground color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </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.105
+ */
+public void setLinkForeground (Color color) {
+ checkWidget();
+ if (color != null) {
+ if (color.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color.equals(linkColor)) return;
+ } else if (linkColor == null) return;
+ linkColor = color;
+ if (getEnabled()) {
+ styleLinkParts();
+ redraw();
+ }
+}
+
@Override
void setOrientation (boolean create) {
super.setOrientation (create);
@@ -768,13 +810,10 @@
layout.setText (parse (string));
focusIndex = offsets.length > 0 ? 0 : -1;
selection.x = selection.y = -1;
- boolean enabled = (state & DISABLED) == 0;
- TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
- linkStyle.underline = true;
+ styleLinkParts();
int [] bidiSegments = new int [offsets.length*2];
for (int i = 0; i < offsets.length; i++) {
Point point = offsets [i];
- layout.setStyle (linkStyle, point.x, point.y);
bidiSegments[i*2] = point.x;
bidiSegments[i*2+1] = point.y+1;
}
@@ -796,6 +835,16 @@
fixStyle (handle);
}
+void styleLinkParts() {
+ boolean enabled = (state & DISABLED) == 0;
+ TextStyle linkStyle = new TextStyle (null, enabled ? getLinkForeground() : disabledColor, null);
+ linkStyle.underline = true;
+ for (int i = 0; i < offsets.length; i++) {
+ Point point = offsets [i];
+ layout.setStyle (linkStyle, point.x, point.y);
+ }
+}
+
@Override
int traversalCode (int key, GdkEventKey event) {
if (offsets.length == 0) return 0;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
index c1b6cd8..e672bd8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 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
@@ -7,15 +7,16 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Conrad Groth - Bug 401015 - [CSS] Add support for styling hyperlinks in Links
*******************************************************************************/
package org.eclipse.swt.widgets;
-import org.eclipse.swt.internal.BidiUtil;
-import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.events.*;
import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
/**
* Instances of this class represent a selectable
@@ -41,19 +42,20 @@
*/
public class Link extends Control {
String text;
- TextLayout layout;
- Color linkColor, disabledColor;
+ TextLayout layout; // always track the current layout, even if we don't need it.
+ Color disabledColor;
+ int linkForeground = -1;
Point [] offsets;
Point selection;
String [] ids;
int [] mnemonics;
int focusIndex, mouseDownIndex;
long /*int*/ font;
- static final RGB LINK_FOREGROUND = new RGB (0, 51, 153);
+ static final RGB LAST_FALLBACK_LINK_FOREGROUND = new RGB (0, 51, 153);
static final long /*int*/ LinkProc;
static final TCHAR LinkClass = new TCHAR (0, OS.WC_LINK, true);
static {
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (isCommonControlAvailable()) {
WNDCLASS lpWndClass = new WNDCLASS ();
OS.GetClassInfo (0, LinkClass, lpWndClass);
LinkProc = lpWndClass.lpfnWndProc;
@@ -182,7 +184,7 @@
if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
int width, height;
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
long /*int*/ hDC = OS.GetDC (handle);
long /*int*/ newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
long /*int*/ oldFont = OS.SelectObject (hDC, newFont);
@@ -233,32 +235,23 @@
void createHandle () {
super.createHandle ();
state |= THEME_BACKGROUND;
- if (OS.COMCTL32_MAJOR < 6) {
- layout = new TextLayout (display);
- if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
- linkColor = Color.win32_new (display, OS.GetSysColor (OS.COLOR_HOTLIGHT));
- } else {
- linkColor = new Color (display, LINK_FOREGROUND);
- }
- disabledColor = Color.win32_new (display, OS.GetSysColor (OS.COLOR_GRAYTEXT));
- offsets = new Point [0];
- ids = new String [0];
- mnemonics = new int [0];
- selection = new Point (-1, -1);
- focusIndex = mouseDownIndex = -1;
- }
+ layout = new TextLayout (display);
+ disabledColor = Color.win32_new (display, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+ offsets = new Point [0];
+ ids = new String [0];
+ mnemonics = new int [0];
+ selection = new Point (-1, -1);
+ focusIndex = mouseDownIndex = -1;
}
@Override
void createWidget () {
super.createWidget ();
text = "";
- if (OS.COMCTL32_MAJOR < 6) {
- if ((style & SWT.MIRRORED) != 0) {
- layout.setOrientation (SWT.RIGHT_TO_LEFT);
- }
- initAccessible ();
+ if ((style & SWT.MIRRORED) != 0) {
+ layout.setOrientation (SWT.RIGHT_TO_LEFT);
}
+ initAccessible ();
}
void drawWidget (GC gc, RECT rect) {
@@ -294,7 +287,7 @@
@Override
void enableWidget (boolean enabled) {
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl(enabled)) {
LITEM item = new LITEM ();
item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
item.stateMask = OS.LIS_ENABLED;
@@ -302,14 +295,8 @@
while (OS.SendMessage (handle, OS.LM_SETITEM, 0, item) != 0) {
item.iLink++;
}
- } else {
- TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
- linkStyle.underline = true;
- for (int i = 0; i < offsets.length; i++) {
- Point point = offsets [i];
- layout.setStyle (linkStyle, point.x, point.y);
- }
}
+ styleLinkParts(enabled);
redraw ();
/*
* Feature in Windows. For some reason, setting
@@ -378,6 +365,32 @@
});
}
+/**
+ * Returns the link foreground color.
+ *
+ * @return the receiver's link 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.105
+ */
+public Color getLinkForeground () {
+ checkWidget ();
+ return internalGetLinkForeground();
+}
+
+Color internalGetLinkForeground() {
+ if (linkForeground != -1) {
+ return Color.win32_new (display, linkForeground);
+ }
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+ return Color.win32_new (display, OS.GetSysColor (OS.COLOR_HOTLIGHT));
+ }
+ return new Color (display, LAST_FALLBACK_LINK_FOREGROUND);
+}
+
@Override
String getNameText () {
return getText ();
@@ -438,7 +451,7 @@
char mnemonic = parsedText.charAt(mnemonics[i]);
if (uckey == Character.toUpperCase (mnemonic)) {
if (!setFocus ()) return false;
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
LITEM item = new LITEM ();
item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
@@ -639,8 +652,6 @@
super.releaseWidget ();
if (layout != null) layout.dispose ();
layout = null;
- if (linkColor != null) linkColor.dispose ();
- linkColor = null;
disabledColor = null;
offsets = null;
ids = null;
@@ -674,6 +685,39 @@
}
/**
+ * Sets the link foreground color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </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.105
+ */
+public void setLinkForeground (Color color) {
+ checkWidget ();
+ int pixel = -1;
+ if (color != null) {
+ if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ pixel = color.handle;
+ }
+ if (pixel == linkForeground) return;
+ linkForeground = pixel;
+ if (OS.IsWindowEnabled (handle)) {
+ styleLinkParts(true);
+ }
+ OS.InvalidateRect (handle, null, true);
+}
+
+/**
* Sets the receiver's text.
* <p>
* The string can contain both regular text and hyperlinks. A hyperlink
@@ -718,8 +762,9 @@
updateTextDirection (AUTO_TEXT_DIRECTION);
}
- if (OS.COMCTL32_MAJOR >= 6) {
- boolean enabled = OS.IsWindowEnabled (handle);
+ boolean enabled = OS.IsWindowEnabled (handle);
+ String parsedText = parse (text);
+ if (isCommonControlAvailable()) {
/*
* Bug in Windows. For some reason, when SetWindowText()
* is used to set the text of a link control to the empty
@@ -729,34 +774,31 @@
if (string.length () == 0) string = " "; //$NON-NLS-1$
TCHAR buffer = new TCHAR (getCodePage (), string, true);
OS.SetWindowText (handle, buffer);
- parse (text);
+ }
+
+ layout.setText (parsedText);
+ focusIndex = offsets.length > 0 ? 0 : -1;
+ selection.x = selection.y = -1;
+ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ if (offsets.length > 0) {
+ bits |= OS.WS_TABSTOP;
+ } else {
+ bits &= ~OS.WS_TABSTOP;
+ }
+ OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+ styleLinkParts(enabled);
+ TextStyle mnemonicStyle = new TextStyle (null, null, null);
+ mnemonicStyle.underline = true;
+ for (int i = 0; i < mnemonics.length; i++) {
+ int mnemonic = mnemonics [i];
+ if (mnemonic != -1) {
+ layout.setStyle (mnemonicStyle, mnemonic, mnemonic);
+ }
+ }
+
+ if (useCommonControl()) {
enableWidget (enabled);
} else {
- layout.setText (parse (text));
- focusIndex = offsets.length > 0 ? 0 : -1;
- selection.x = selection.y = -1;
- int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
- if (offsets.length > 0) {
- bits |= OS.WS_TABSTOP;
- } else {
- bits &= ~OS.WS_TABSTOP;
- }
- OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
- boolean enabled = OS.IsWindowEnabled (handle);
- TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
- linkStyle.underline = true;
- for (int i = 0; i < offsets.length; i++) {
- Point point = offsets [i];
- layout.setStyle (linkStyle, point.x, point.y);
- }
- TextStyle mnemonicStyle = new TextStyle (null, null, null);
- mnemonicStyle.underline = true;
- for (int i = 0; i < mnemonics.length; i++) {
- int mnemonic = mnemonics [i];
- if (mnemonic != -1) {
- layout.setStyle (mnemonicStyle, mnemonic, mnemonic);
- }
- }
redraw ();
}
}
@@ -766,6 +808,15 @@
return BidiUtil.resolveTextDirection(text);
}
+void styleLinkParts(boolean enabled) {
+ TextStyle linkStyle = new TextStyle (null, enabled ? internalGetLinkForeground() : disabledColor, null);
+ linkStyle.underline = true;
+ for (int i = 0; i < offsets.length; i++) {
+ Point point = offsets [i];
+ layout.setStyle (linkStyle, point.x, point.y);
+ }
+}
+
@Override
boolean updateTextDirection(int textDirection) {
if (super.updateTextDirection(textDirection)) {
@@ -780,6 +831,18 @@
return false;
}
+boolean useCommonControl() {
+ return useCommonControl(OS.IsWindowEnabled(handle));
+}
+
+boolean useCommonControl(boolean enabled) {
+ return linkForeground == -1 && !enabled && isCommonControlAvailable();
+}
+
+static boolean isCommonControlAvailable() {
+ return OS.COMCTL32_MAJOR >= 6;
+}
+
@Override
int widgetStyle () {
int bits = super.widgetStyle ();
@@ -788,7 +851,7 @@
@Override
TCHAR windowClass () {
- return OS.COMCTL32_MAJOR >= 6 ? LinkClass : display.windowClass;
+ return isCommonControlAvailable() ? LinkClass : display.windowClass;
}
@Override
@@ -800,7 +863,7 @@
LRESULT WM_CHAR (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_CHAR (wParam, lParam);
if (result != null) return result;
- if (OS.COMCTL32_MAJOR < 6) {
+ if (!useCommonControl()) {
if (focusIndex == -1) return result;
switch ((int)/*64*/wParam) {
case ' ':
@@ -849,7 +912,7 @@
if (result != null) return result;
int index, count;
long /*int*/ code = 0;
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
LITEM item = new LITEM ();
item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
item.stateMask = OS.LIS_FOCUSED;
@@ -893,7 +956,7 @@
LRESULT WM_KEYDOWN (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_KEYDOWN (wParam, lParam);
if (result != null) return result;
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
switch ((int)/*64*/wParam) {
case OS.VK_SPACE:
case OS.VK_RETURN:
@@ -913,7 +976,7 @@
@Override
LRESULT WM_KILLFOCUS (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
- if (OS.COMCTL32_MAJOR < 6) redraw ();
+ if (!useCommonControl()) redraw ();
return result;
}
@@ -921,7 +984,7 @@
LRESULT WM_LBUTTONDOWN (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
if (result == LRESULT.ZERO) return result;
- if (OS.COMCTL32_MAJOR < 6) {
+ if (!useCommonControl()) {
if (focusIndex != -1) setFocus ();
int x = OS.GET_X_LPARAM (lParam);
int y = OS.GET_Y_LPARAM (lParam);
@@ -960,7 +1023,7 @@
LRESULT WM_LBUTTONUP (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
if (result == LRESULT.ZERO) return result;
- if (OS.COMCTL32_MAJOR < 6) {
+ if (!useCommonControl()) {
if (mouseDownIndex == -1) return result;
int x = OS.GET_X_LPARAM (lParam);
int y = OS.GET_Y_LPARAM (lParam);
@@ -989,15 +1052,13 @@
* returns HTTRANSPARENT when mouse is over plain text. The fix is
* to always return HTCLIENT.
*/
- if (OS.COMCTL32_MAJOR >= 6) return new LRESULT (OS.HTCLIENT);
-
- return result;
+ return new LRESULT (OS.HTCLIENT);
}
@Override
LRESULT WM_MOUSEMOVE (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
- if (OS.COMCTL32_MAJOR < 6) {
+ if (!useCommonControl()) {
int x = OS.GET_X_LPARAM (lParam);
int y = OS.GET_Y_LPARAM (lParam);
if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
@@ -1033,7 +1094,7 @@
@Override
LRESULT WM_PAINT (long /*int*/ wParam, long /*int*/ lParam) {
if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
return super.WM_PAINT (wParam, lParam);
}
@@ -1058,7 +1119,7 @@
@Override
LRESULT WM_PRINTCLIENT (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
- if (OS.COMCTL32_MAJOR < 6) {
+ if (!useCommonControl()) {
RECT rect = new RECT ();
OS.GetClientRect (handle, rect);
GCData data = new GCData ();
@@ -1074,15 +1135,13 @@
@Override
LRESULT WM_SETFOCUS (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_SETFOCUS (wParam, lParam);
- if (OS.COMCTL32_MAJOR < 6) redraw ();
+ if (!useCommonControl()) redraw ();
return result;
}
@Override
LRESULT WM_SETFONT (long /*int*/ wParam, long /*int*/ lParam) {
- if (OS.COMCTL32_MAJOR < 6) {
- layout.setFont (Font.win32_new (display, wParam));
- }
+ layout.setFont (Font.win32_new (display, wParam));
if (lParam != 0) OS.InvalidateRect (handle, null, true);
return super.WM_SETFONT (font = wParam, lParam);
}
@@ -1090,10 +1149,10 @@
@Override
LRESULT WM_SIZE (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_SIZE (wParam, lParam);
- if (OS.COMCTL32_MAJOR < 6) {
- RECT rect = new RECT ();
- OS.GetClientRect (handle, rect);
- layout.setWidth (rect.right > 0 ? rect.right : -1);
+ RECT rect = new RECT ();
+ OS.GetClientRect (handle, rect);
+ layout.setWidth (rect.right > 0 ? rect.right : -1);
+ if (!useCommonControl()) {
redraw ();
}
return result;
@@ -1107,7 +1166,7 @@
* not gray out the non-link portion of the text. The fix
* is to set the text color to the system gray color.
*/
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
if (!OS.IsWindowEnabled (handle)) {
OS.SetTextColor (wParam, OS.GetSysColor (OS.COLOR_GRAYTEXT));
if (result == null) {
@@ -1123,7 +1182,7 @@
@Override
LRESULT wmNotifyChild (NMHDR hdr, long /*int*/ wParam, long /*int*/ lParam) {
- if (OS.COMCTL32_MAJOR >= 6) {
+ if (useCommonControl()) {
switch (hdr.code) {
case OS.NM_RETURN:
case OS.NM_CLICK:
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Link.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Link.java
index 48246d6..4c2c9f6 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Link.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Link.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 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
@@ -12,12 +12,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Link;
import org.junit.Before;
@@ -152,4 +154,15 @@
} catch (IllegalArgumentException e) {
}
}
+
+@Test
+public void test_setLinkForegroundLorg_eclipse_swt_graphics_Color() {
+ assertNotNull(link.getLinkForeground());
+ Color color = new Color(control.getDisplay(), 12, 34, 56);
+ link.setLinkForeground(color);
+ assertEquals(color, link.getLinkForeground());
+ link.setLinkForeground(null);
+ assertFalse(link.getForeground().equals(color));
+ color.dispose();
+}
}