Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Nemkin2018-04-17 06:47:14 +0000
committerLars Vogel2019-05-09 12:12:10 +0000
commitf4fefe951c03e6c980c7df998f97a8e5d5cca89e (patch)
treef73f8561ebffd6d1def39e39ee433e9e77067fc7
parent3e03fdee49752a153d59a3a1481c0677016d2bf4 (diff)
downloadeclipse.platform.swt-f4fefe951c03e6c980c7df998f97a8e5d5cca89e.tar.gz
eclipse.platform.swt-f4fefe951c03e6c980c7df998f97a8e5d5cca89e.tar.xz
eclipse.platform.swt-f4fefe951c03e6c980c7df998f97a8e5d5cca89e.zip
Bug 545874 - [Win32] Remove emulated Link widget code
Remove emulation code that was previously used on pre-XP systems and also to implement custom link color and preferred size measurement. On Vista, these features are available natively. In particular: * Remove custom layout, painting, hit testing. * Remove custom Accessible. * Simplify text parsing. * Use NM_CUSTOMDRAW for custom link color and enabled=false. * Use LM_GETIDEALSIZE for layout measurements. * Extract getFocusItem/setFocusItem methods to help with multi-link tabbing (not supported natively). Change-Id: I6b788230bc34a0c7003cc35f7cb7e13d6d84a90b Signed-off-by: Nikita Nemkin <nikita@nemkin.ru>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java2
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java792
2 files changed, 167 insertions, 627 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
index 2e77e7ecf9..a3d5f93cba 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
@@ -775,7 +775,7 @@ public class OS extends C {
public static final int LISS_HOT = 0x2;
public static final int LISS_SELECTED = 0x3;
public static final int LISS_SELECTEDNOTFOCUS = 0x5;
- public static final int LM_GETIDEALHEIGHT = 0x701;
+ public static final int LM_GETIDEALSIZE = 0x701;
public static final int LM_SETITEM = 0x702;
public static final int LM_GETITEM = 0x703;
public static final int LCID_SUPPORTED = 0x2;
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 11ffbedc50..dd4fea796c 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
@@ -14,8 +14,9 @@
*******************************************************************************/
package org.eclipse.swt.widgets;
+import java.util.*;
+
import org.eclipse.swt.*;
-import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
@@ -44,16 +45,9 @@ import org.eclipse.swt.internal.win32.*;
*/
public class Link extends Control {
String text;
- 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 LAST_FALLBACK_LINK_FOREGROUND = new RGB (0, 51, 153);
+ char [] mnemonics;
static final long /*int*/ LinkProc;
static final TCHAR LinkClass = new TCHAR (0, OS.WC_LINK, true);
static {
@@ -166,49 +160,30 @@ long /*int*/ callWindowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, lo
return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam);
}
-@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+@Override
+Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
checkWidget ();
- if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
- if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
int width, height;
- if (useCommonControl()) {
+ /*
+ * When the text is empty, LM_GETIDEALSIZE returns zero width and height,
+ * but SWT convention is to return zero width and line height.
+ */
+ if (text.isEmpty()) {
long /*int*/ hDC = OS.GetDC (handle);
long /*int*/ newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
long /*int*/ oldFont = OS.SelectObject (hDC, newFont);
- if (text.length () > 0) {
- char [] buffer = parse (text).toCharArray ();
- RECT rect = new RECT ();
- int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
- if (wHint != SWT.DEFAULT) {
- flags |= OS.DT_WORDBREAK;
- rect.right = wHint;
- }
- OS.DrawText (hDC, buffer, buffer.length, rect, flags);
- width = rect.right - rect.left;
- height = rect.bottom;
- } else {
- TEXTMETRIC lptm = new TEXTMETRIC ();
- OS.GetTextMetrics (hDC, lptm);
- width = 0;
- height = lptm.tmHeight;
- }
+ TEXTMETRIC lptm = new TEXTMETRIC ();
+ OS.GetTextMetrics (hDC, lptm);
+ width = 0;
+ height = lptm.tmHeight;
if (newFont != 0) OS.SelectObject (hDC, oldFont);
OS.ReleaseDC (handle, hDC);
} else {
- int layoutWidth = layout.getWidth ();
- //TEMPORARY CODE
- if (wHint == 0) {
- layout.setWidth (1);
- Rectangle rect = DPIUtil.autoScaleUp(layout.getBounds ());
- width = 0;
- height = rect.height;
- } else {
- layout.setWidth (DPIUtil.autoScaleDown(wHint));
- Rectangle rect = DPIUtil.autoScaleUp(layout.getBounds ());
- width = rect.width;
- height = rect.height;
- }
- layout.setWidth (layoutWidth);
+ SIZE size = new SIZE ();
+ int maxWidth = (wHint == SWT.DEFAULT) ? 0x7fffffff : wHint;
+ OS.SendMessage (handle, OS.LM_GETIDEALSIZE, maxWidth, size);
+ width = size.cx;
+ height = size.cy;
}
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
@@ -222,131 +197,35 @@ long /*int*/ callWindowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, lo
void createHandle () {
super.createHandle ();
state |= THEME_BACKGROUND;
- 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 ((style & SWT.MIRRORED) != 0) {
- layout.setOrientation (SWT.RIGHT_TO_LEFT);
- }
- initAccessible ();
-}
-
-void drawWidget (GC gc, RECT rect) {
- drawBackground (gc.handle, rect);
- int selStart = selection.x;
- int selEnd = selection.y;
- if (selStart > selEnd) {
- selStart = selection.y;
- selEnd = selection.x;
- }
- // temporary code to disable text selection
- selStart = selEnd = -1;
- if (!OS.IsWindowEnabled (handle)) gc.setForeground (disabledColor);
- layout.draw (gc, 0, 0, selStart, selEnd, null, null);
- if (hasFocus () && focusIndex != -1) {
- Rectangle [] rects = getRectanglesInPixels (focusIndex);
- for (int i = 0; i < rects.length; i++) {
- Rectangle rectangle = DPIUtil.autoScaleDown(rects [i]);
- gc.drawFocus (rectangle.x, rectangle.y, rectangle.width, rectangle.height);
- }
- }
- if (hooks (SWT.Paint) || filters (SWT.Paint)) {
- Event event = new Event ();
- event.gc = gc;
- event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
- sendEvent (SWT.Paint, event);
- event.gc = null;
- }
}
@Override
void enableWidget (boolean enabled) {
- if (useCommonControl(enabled)) {
- LITEM item = new LITEM ();
- item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
- item.stateMask = OS.LIS_ENABLED;
- item.state = enabled ? OS.LIS_ENABLED : 0;
- while (OS.SendMessage (handle, OS.LM_SETITEM, 0, item) != 0) {
- item.iLink++;
- }
- }
- styleLinkParts(enabled);
- redraw ();
- /*
- * Feature in Windows. For some reason, setting
- * LIS_ENABLED state using LM_SETITEM causes the
- * SysLink to become enabled. To be specific,
- * calling IsWindowEnabled() returns true. The
- * fix is disable the SysLink after LM_SETITEM.
- */
super.enableWidget (enabled);
+ /*
+ * Feature in Windows. SysLink32 control doesn't natively
+ * provide disabled state. Emulate it with custom draw.
+ */
+ OS.InvalidateRect (handle, null, true);
}
-void initAccessible () {
- Accessible accessible = getAccessible ();
- accessible.addAccessibleListener (new AccessibleAdapter () {
- @Override
- public void getName (AccessibleEvent e) {
- e.result = parse (text);
- }
- });
-
- accessible.addAccessibleControlListener (new AccessibleControlAdapter () {
- @Override
- public void getChildAtPoint (AccessibleControlEvent e) {
- e.childID = ACC.CHILDID_SELF;
- }
-
- @Override
- public void getLocation (AccessibleControlEvent e) {
- Rectangle rect = display.mapInPixels (getParent (), null, getBoundsInPixels ());
- e.x = rect.x;
- e.y = rect.y;
- e.width = rect.width;
- e.height = rect.height;
+int getFocusItem () {
+ LITEM item = new LITEM ();
+ item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+ item.stateMask = OS.LIS_FOCUSED;
+ while (OS.SendMessage (handle, OS.LM_GETITEM, 0, item) != 0) {
+ if ((item.state & OS.LIS_FOCUSED) != 0) {
+ return item.iLink;
}
-
- @Override
- public void getChildCount (AccessibleControlEvent e) {
- e.detail = 0;
- }
-
- @Override
- public void getRole (AccessibleControlEvent e) {
- e.detail = ACC.ROLE_LINK;
- }
-
- @Override
- public void getState (AccessibleControlEvent e) {
- e.detail = ACC.STATE_FOCUSABLE;
- if (hasFocus ()) e.detail |= ACC.STATE_FOCUSED;
- }
-
- @Override
- public void getDefaultAction (AccessibleControlEvent e) {
- e.result = SWT.getMessage ("SWT_Press"); //$NON-NLS-1$
- }
-
- @Override
- public void getSelection (AccessibleControlEvent e) {
- if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
- }
-
- @Override
- public void getFocus (AccessibleControlEvent e) {
- if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
- }
- });
+ item.iLink++;
+ }
+ return -1;
}
/**
@@ -362,10 +241,6 @@ void initAccessible () {
*/
public Color getLinkForeground () {
checkWidget ();
- return internalGetLinkForeground();
-}
-
-Color internalGetLinkForeground() {
if (linkForeground != -1) {
return Color.win32_new (display, linkForeground);
}
@@ -377,35 +252,6 @@ String getNameText () {
return getText ();
}
-Rectangle [] getRectanglesInPixels (int linkIndex) {
- int lineCount = layout.getLineCount ();
- Rectangle [] rects = new Rectangle [lineCount];
- int [] lineOffsets = layout.getLineOffsets ();
- Point point = offsets [linkIndex];
- int lineStart = 1;
- while (point.x > lineOffsets [lineStart]) lineStart++;
- int lineEnd = 1;
- while (point.y > lineOffsets [lineEnd]) lineEnd++;
- int index = 0;
- if (lineStart == lineEnd) {
- rects [index++] = DPIUtil.autoScaleUp(layout.getBounds (point.x, point.y));
- } else {
- rects [index++] = DPIUtil.autoScaleUp(layout.getBounds (point.x, lineOffsets [lineStart]-1));
- rects [index++] = DPIUtil.autoScaleUp(layout.getBounds (lineOffsets [lineEnd-1], point.y));
- if (lineEnd - lineStart > 1) {
- for (int i = lineStart; i < lineEnd - 1; i++) {
- rects [index++] = DPIUtil.autoScaleUp(layout.getLineBounds (i));
- }
- }
- }
- if (rects.length != index) {
- Rectangle [] tmp = new Rectangle [index];
- System.arraycopy (rects, 0, tmp, 0, index);
- rects = tmp;
- }
- return rects;
-}
-
/**
* Returns the receiver's text, which will be an empty
* string if it has never been set.
@@ -426,36 +272,9 @@ public String getText () {
boolean mnemonicHit (char key) {
if (mnemonics != null) {
char uckey = Character.toUpperCase (key);
- String parsedText = parse(text);
- for (int i = 0; i < mnemonics.length - 1; i++) {
- if (mnemonics[i] != -1) {
- char mnemonic = parsedText.charAt(mnemonics[i]);
- if (uckey == Character.toUpperCase (mnemonic)) {
- if (!setFocus ()) return false;
- if (useCommonControl()) {
- int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
- LITEM item = new LITEM ();
- item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
- item.stateMask = OS.LIS_FOCUSED;
- while (item.iLink < mnemonics.length) {
- if (item.iLink != i) OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
- item.iLink++;
- }
- item.iLink = i;
- item.state = OS.LIS_FOCUSED;
- OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
-
- /* Feature in Windows. For some reason, setting the focus to
- * any item but first causes the control to clear the WS_TABSTOP
- * bit. The fix is always to reset the bit.
- */
- OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
- } else {
- focusIndex = i;
- redraw ();
- }
- return true;
- }
+ for (int i = 0; i < mnemonics.length; i++) {
+ if (uckey == mnemonics[i]) {
+ return setFocus () && setFocusItem (i);
}
}
}
@@ -466,36 +285,31 @@ boolean mnemonicHit (char key) {
boolean mnemonicMatch (char key) {
if (mnemonics != null) {
char uckey = Character.toUpperCase (key);
- String parsedText = parse(text);
- for (int i = 0; i < mnemonics.length - 1; i++) {
- if (mnemonics[i] != -1) {
- char mnemonic = parsedText.charAt(mnemonics[i]);
- if (uckey == Character.toUpperCase (mnemonic)) {
- return true;
- }
+ for (int i = 0; i < mnemonics.length; i++) {
+ if (uckey == mnemonics[i]) {
+ return true;
}
}
}
return false;
}
-String parse (String string) {
+void parse (String string) {
int length = string.length ();
- offsets = new Point [length / 4];
- ids = new String [length / 4];
- mnemonics = new int [length / 4 + 1];
- StringBuffer result = new StringBuffer ();
- char [] buffer = new char [length];
- string.getChars (0, string.length (), buffer, 0);
+ // The shortest link length is 7 characters (<a></a>).
+ ids = new String [length / 7];
+ mnemonics = new char [length / 7];
int index = 0, state = 0, linkIndex = 0;
- int start = 0, tagStart = 0, linkStart = 0, endtagStart = 0, refStart = 0;
+ int linkStart = 0, linkEnd = 0, refStart = 0, refEnd = 0;
+ char mnemonic = 0;
while (index < length) {
- char c = Character.toLowerCase (buffer [index]);
+ char c = Character.toLowerCase (string.charAt (index));
switch (state) {
case 0:
if (c == '<') {
- tagStart = index;
state++;
+ } else if (c == '&') {
+ state = 16;
}
break;
case 1:
@@ -517,7 +331,7 @@ String parse (String string) {
break;
case 3:
if (c == '<') {
- endtagStart = index;
+ linkEnd = index;
state++;
}
break;
@@ -529,15 +343,16 @@ String parse (String string) {
break;
case 6:
if (c == '>') {
- mnemonics [linkIndex] = parseMnemonics (buffer, start, tagStart, result);
- int offset = result.length ();
- parseMnemonics (buffer, linkStart, endtagStart, result);
- offsets [linkIndex] = new Point (offset, result.length () - 1);
- if (ids [linkIndex] == null) {
- ids [linkIndex] = new String (buffer, linkStart, endtagStart - linkStart);
+ if (refStart == 0) {
+ refStart = linkStart;
+ refEnd = linkEnd;
+ }
+ ids [linkIndex] = string.substring(refStart, refEnd);
+ if (mnemonic != 0) {
+ mnemonics [linkIndex] = mnemonic;
}
linkIndex++;
- start = tagStart = linkStart = endtagStart = refStart = index + 1;
+ linkStart = linkEnd = refStart = refEnd = mnemonic = 0;
state = 0;
} else {
state = 3;
@@ -565,7 +380,7 @@ String parse (String string) {
break;
case 12:
if (c == '"') {
- ids[linkIndex] = new String (buffer, refStart, index - refStart);
+ refEnd = index;
state = 2;
}
break;
@@ -582,59 +397,27 @@ String parse (String string) {
case 15:
if (c == '"') state = 2;
break;
+ case 16:
+ if (c == '<') {
+ state = 1;
+ } else {
+ state = 0;
+ if (c != '&') mnemonic = Character.toUpperCase (c);
+ }
+ break;
default:
state = 0;
break;
}
index++;
}
- if (start < length) {
- int tmp = parseMnemonics (buffer, start, tagStart, result);
- int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length, result);
- if (mnemonic == -1) mnemonic = tmp;
- mnemonics [linkIndex] = mnemonic;
- } else {
- mnemonics [linkIndex] = -1;
- }
- if (offsets.length != linkIndex) {
- Point [] newOffsets = new Point [linkIndex];
- System.arraycopy (offsets, 0, newOffsets, 0, linkIndex);
- offsets = newOffsets;
- String [] newIDs = new String [linkIndex];
- System.arraycopy (ids, 0, newIDs, 0, linkIndex);
- ids = newIDs;
- int [] newMnemonics = new int [linkIndex + 1];
- System.arraycopy (mnemonics, 0, newMnemonics, 0, linkIndex + 1);
- mnemonics = newMnemonics;
- }
- return result.toString ();
-}
-
-int parseMnemonics (char[] buffer, int start, int end, StringBuffer result) {
- int mnemonic = -1, index = start;
- while (index < end) {
- if (buffer [index] == '&') {
- if (index + 1 < end && buffer [index + 1] == '&') {
- result.append (buffer [index]);
- index++;
- } else {
- mnemonic = result.length();
- }
- } else {
- result.append (buffer [index]);
- }
- index++;
- }
- return mnemonic;
+ ids = Arrays.copyOf(ids, linkIndex);
+ mnemonics = Arrays.copyOf(mnemonics, linkIndex);
}
@Override
void releaseWidget () {
super.releaseWidget ();
- if (layout != null) layout.dispose ();
- layout = null;
- disabledColor = null;
- offsets = null;
ids = null;
mnemonics = null;
text = null;
@@ -665,6 +448,27 @@ public void removeSelectionListener (SelectionListener listener) {
eventTable.unhook (SWT.DefaultSelection, listener);
}
+boolean setFocusItem (int index) {
+ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ LITEM item = new LITEM ();
+ item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+ item.stateMask = OS.LIS_FOCUSED;
+ while (item.iLink < ids.length) {
+ if (item.iLink != index) OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
+ item.iLink++;
+ }
+ item.iLink = index;
+ item.state = OS.LIS_FOCUSED;
+ long /*int*/ result = OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
+
+ /* Feature in Windows. For some reason, setting the focus to
+ * any item but first causes the control to clear the WS_TABSTOP
+ * bit. The fix is always to reset the bit.
+ */
+ OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+ return result != 0;
+}
+
/**
* Sets the link foreground color to the color specified
* by the argument, or to the default system color for the link
@@ -692,9 +496,6 @@ public void setLinkForeground (Color color) {
}
if (pixel == linkForeground) return;
linkForeground = pixel;
- if (OS.IsWindowEnabled (handle)) {
- styleLinkParts(true);
- }
OS.InvalidateRect (handle, null, true);
}
@@ -744,44 +545,9 @@ public void setText (String string) {
if ((state & HAS_AUTO_DIRECTION) != 0) {
updateTextDirection (AUTO_TEXT_DIRECTION);
}
-
- boolean enabled = OS.IsWindowEnabled (handle);
- String parsedText = parse (text);
- /*
- * Bug in Windows. For some reason, when SetWindowText()
- * is used to set the text of a link control to the empty
- * string, the old text remains. The fix is to set the
- * text to a space instead.
- */
- if (string.length () == 0) string = " "; //$NON-NLS-1$
TCHAR buffer = new TCHAR (getCodePage (), string, true);
OS.SetWindowText (handle, buffer);
-
- 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 {
- redraw ();
- }
+ parse(string);
}
@Override
@@ -789,15 +555,6 @@ int resolveTextDirection() {
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)) {
@@ -812,14 +569,6 @@ boolean updateTextDirection(int textDirection) {
return false;
}
-boolean useCommonControl() {
- return useCommonControl(OS.IsWindowEnabled(handle));
-}
-
-boolean useCommonControl(boolean enabled) {
- return linkForeground == -1 && !enabled;
-}
-
@Override
int widgetStyle () {
int bits = super.widgetStyle ();
@@ -840,182 +589,61 @@ long /*int*/ windowProc () {
LRESULT WM_CHAR (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_CHAR (wParam, lParam);
if (result != null) return result;
- if (!useCommonControl()) {
- if (focusIndex == -1) return result;
- switch ((int)/*64*/wParam) {
- case ' ':
- case SWT.CR:
- Event event = new Event ();
- event.text = ids [focusIndex];
- sendSelectionEvent (SWT.Selection, event, true);
- break;
- case SWT.TAB:
- boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
- if (next) {
- if (focusIndex < offsets.length - 1) {
- focusIndex++;
- redraw ();
- }
- } else {
- if (focusIndex > 0) {
- focusIndex--;
- redraw ();
- }
- }
- break;
- }
- } else {
- switch ((int)/*64*/wParam) {
- case ' ':
- case SWT.CR:
- case SWT.TAB:
- /*
- * NOTE: Call the window proc with WM_KEYDOWN rather than WM_CHAR
- * so that the key that was ignored during WM_KEYDOWN is processed.
- * This allows the application to cancel an operation that is normally
- * performed in WM_KEYDOWN from WM_CHAR.
- */
- long /*int*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
- return new LRESULT (code);
- }
-
+ switch ((int)/*64*/wParam) {
+ case ' ':
+ case SWT.CR:
+ case SWT.TAB:
+ /*
+ * NOTE: Call the window proc with WM_KEYDOWN rather than WM_CHAR
+ * so that the key that was ignored during WM_KEYDOWN is processed.
+ * This allows the application to cancel an operation that is normally
+ * performed in WM_KEYDOWN from WM_CHAR.
+ */
+ long /*int*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+ return new LRESULT (code);
}
return result;
}
@Override
LRESULT WM_GETDLGCODE (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
- if (result != null) return result;
- int index, count;
- long /*int*/ code = 0;
- if (useCommonControl()) {
- LITEM item = new LITEM ();
- item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
- item.stateMask = OS.LIS_FOCUSED;
- index = 0;
- while (OS.SendMessage (handle, OS.LM_GETITEM, 0, item) != 0) {
- if ((item.state & OS.LIS_FOCUSED) != 0) {
- index = item.iLink;
- }
- item.iLink++;
- }
- count = item.iLink;
- code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
- } else {
- index = focusIndex;
- count = offsets.length;
- }
+ long /*int*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+ int count = ids.length;
if (count == 0) {
- return new LRESULT (code | OS.DLGC_STATIC);
- }
- boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
- if (next && index < count - 1) {
- return new LRESULT (code | OS.DLGC_WANTTAB);
- }
- if (!next && index > 0) {
- return new LRESULT (code | OS.DLGC_WANTTAB);
+ code |= OS.DLGC_STATIC;
+ } else if (count > 1) {
+ int limit = (OS.GetKeyState (OS.VK_SHIFT) < 0) ? 0 : count - 1;
+ if (getFocusItem() != limit) {
+ code |= OS.DLGC_WANTTAB;
+ }
}
- return result;
-}
-
-@Override
-LRESULT WM_GETFONT (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_GETFONT (wParam, lParam);
- if (result != null) return result;
- long /*int*/ code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
- if (code != 0) return new LRESULT (code);
- if (font == 0) font = defaultFont ();
- return new LRESULT (font);
+ return new LRESULT (code);
}
@Override
LRESULT WM_KEYDOWN (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_KEYDOWN (wParam, lParam);
if (result != null) return result;
- if (useCommonControl()) {
- switch ((int)/*64*/wParam) {
- case OS.VK_SPACE:
- case OS.VK_RETURN:
- case OS.VK_TAB:
- /*
- * Ensure that the window proc does not process VK_SPACE,
- * VK_RETURN or VK_TAB so that it can be handled in WM_CHAR.
- * This allows the application to cancel an operation that
- * is normally performed in WM_KEYDOWN from WM_CHAR.
- */
- return LRESULT.ZERO;
- }
+ switch ((int)/*64*/wParam) {
+ case OS.VK_SPACE:
+ case OS.VK_RETURN:
+ case OS.VK_TAB:
+ /*
+ * Ensure that the window proc does not process VK_SPACE,
+ * VK_RETURN or VK_TAB so that it can be handled in WM_CHAR.
+ * This allows the application to cancel an operation that
+ * is normally performed in WM_KEYDOWN from WM_CHAR.
+ */
+ return LRESULT.ZERO;
}
return result;
}
@Override
LRESULT WM_KILLFOCUS (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
- if (!useCommonControl()) redraw ();
- return result;
-}
-
-@Override
-LRESULT WM_LBUTTONDOWN (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
- if (result == LRESULT.ZERO) return result;
- if (!useCommonControl()) {
- if (focusIndex != -1) setFocus ();
- int x = OS.GET_X_LPARAM (lParam);
- int y = OS.GET_Y_LPARAM (lParam);
- int offset = layout.getOffset (DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y), null);
- int oldSelectionX = selection.x;
- int oldSelectionY = selection.y;
- selection.x = offset;
- selection.y = -1;
- if (oldSelectionX != -1 && oldSelectionY != -1) {
- if (oldSelectionX > oldSelectionY) {
- int temp = oldSelectionX;
- oldSelectionX = oldSelectionY;
- oldSelectionY = temp;
- }
- Rectangle rect = DPIUtil.autoScaleUp(layout.getBounds (oldSelectionX, oldSelectionY)); // To Pixels
- redrawInPixels (rect.x, rect.y, rect.width, rect.height, false);
- }
- for (int j = 0; j < offsets.length; j++) {
- Rectangle [] rects = getRectanglesInPixels (j);
- for (int i = 0; i < rects.length; i++) {
- Rectangle rect = rects [i];
- if (rect.contains (x, y)) {
- if (j != focusIndex) {
- redraw ();
- }
- focusIndex = mouseDownIndex = j;
- return result;
- }
- }
- }
- }
- return result;
-}
-
-@Override
-LRESULT WM_LBUTTONUP (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
- if (result == LRESULT.ZERO) return result;
- if (!useCommonControl()) {
- if (mouseDownIndex == -1) return result;
- int x = OS.GET_X_LPARAM (lParam);
- int y = OS.GET_Y_LPARAM (lParam);
- Rectangle [] rects = getRectanglesInPixels (mouseDownIndex);
- for (int i = 0; i < rects.length; i++) {
- Rectangle rect = rects [i];
- if (rect.contains (x, y)) {
- Event event = new Event ();
- event.text = ids [mouseDownIndex];
- sendSelectionEvent (SWT.Selection, event, true);
- break;
- }
- }
- }
- mouseDownIndex = -1;
+ int focusItem = getFocusItem();
+ LRESULT result = super.WM_KILLFOCUS(wParam, lParam);
+ setFocusItem(focusItem);
return result;
}
@@ -1033,83 +661,6 @@ LRESULT WM_NCHITTEST (long /*int*/ wParam, long /*int*/ lParam) {
}
@Override
-LRESULT WM_MOUSEMOVE (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
- if (!useCommonControl()) {
- int x = OS.GET_X_LPARAM (lParam);
- int y = OS.GET_Y_LPARAM (lParam);
- if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
- int oldSelection = selection.y;
- selection.y = layout.getOffset (DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y), null);
- if (selection.y != oldSelection) {
- int newSelection = selection.y;
- if (oldSelection > newSelection) {
- int temp = oldSelection;
- oldSelection = newSelection;
- newSelection = temp;
- }
- Rectangle rect = DPIUtil.autoScaleUp(layout.getBounds (oldSelection, newSelection));// To Pixels
- redrawInPixels (rect.x, rect.y, rect.width, rect.height, false);
- }
- } else {
- for (int j = 0; j < offsets.length; j++) {
- Rectangle [] rects = getRectanglesInPixels (j);
- for (int i = 0; i < rects.length; i++) {
- Rectangle rect = rects [i];
- if (rect.contains (x, y)) {
- setCursor (display.getSystemCursor (SWT.CURSOR_HAND));
- return result;
- }
- }
- }
- setCursor (null);
- }
- }
- return result;
-}
-
-@Override
-LRESULT WM_PAINT (long /*int*/ wParam, long /*int*/ lParam) {
- if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
- if (useCommonControl()) {
- return super.WM_PAINT (wParam, lParam);
- }
-
- PAINTSTRUCT ps = new PAINTSTRUCT ();
- GCData data = new GCData ();
- data.ps = ps;
- data.hwnd = handle;
- GC gc = new_GC (data);
- if (gc != null) {
- int width = ps.right - ps.left;
- int height = ps.bottom - ps.top;
- if (width != 0 && height != 0) {
- RECT rect = new RECT ();
- OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
- drawWidget (gc, rect);
- }
- gc.dispose ();
- }
- return LRESULT.ZERO;
-}
-
-@Override
-LRESULT WM_PRINTCLIENT (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
- if (!useCommonControl()) {
- RECT rect = new RECT ();
- OS.GetClientRect (handle, rect);
- GCData data = new GCData ();
- data.device = display;
- data.foreground = getForegroundPixel ();
- GC gc = GC.win32_new (wParam, data);
- drawWidget (gc, rect);
- gc.dispose ();
- }
- return result;
-}
-
-@Override
LRESULT WM_SETCURSOR(long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_SETCURSOR (wParam, lParam);
if (result != null) return result;
@@ -1121,65 +672,54 @@ LRESULT WM_SETCURSOR(long /*int*/ wParam, long /*int*/ lParam) {
@Override
LRESULT WM_SETFOCUS (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_SETFOCUS (wParam, lParam);
- if (!useCommonControl()) redraw ();
- return result;
-}
-
-@Override
-LRESULT WM_SETFONT (long /*int*/ wParam, long /*int*/ lParam) {
- layout.setFont (Font.win32_new (display, wParam));
- if (lParam != 0) OS.InvalidateRect (handle, null, true);
- return super.WM_SETFONT (font = wParam, lParam);
-}
-
-@Override
-LRESULT WM_SIZE (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.WM_SIZE (wParam, lParam);
- RECT rect = new RECT ();
- OS.GetClientRect (handle, rect);
- layout.setWidth (DPIUtil.autoScaleDown(rect.right > 0 ? rect.right : -1));
- if (!useCommonControl()) {
- redraw ();
- }
- return result;
-}
-
-@Override
-LRESULT wmColorChild (long /*int*/ wParam, long /*int*/ lParam) {
- LRESULT result = super.wmColorChild (wParam, lParam);
/*
- * Feature in Windows. When a SysLink is disabled, it does
- * not gray out the non-link portion of the text. The fix
- * is to set the text color to the system gray color.
+ * Feature in Windows. Upon receiving focus, SysLink control
+ * always activates the first link. This leads to surprising
+ * behavior in multi-link controls.
*/
- if (useCommonControl()) {
- if (!OS.IsWindowEnabled (handle)) {
- OS.SetTextColor (wParam, OS.GetSysColor (OS.COLOR_GRAYTEXT));
- if (result == null) {
- int backPixel = getBackgroundPixel ();
- OS.SetBkColor (wParam, backPixel);
- long /*int*/ hBrush = findBrush (backPixel, OS.BS_SOLID);
- return new LRESULT (hBrush);
- }
+ if (ids.length > 1) {
+ if (OS.GetKeyState (OS.VK_TAB) < 0) {
+ boolean shift = OS.GetKeyState (OS.VK_SHIFT) < 0;
+ setFocusItem(shift ? ids.length - 1 : 0);
}
}
- return result;
+ return super.WM_SETFOCUS (wParam, lParam);
}
@Override
LRESULT wmNotifyChild (NMHDR hdr, long /*int*/ wParam, long /*int*/ lParam) {
- if (useCommonControl()) {
- switch (hdr.code) {
- case OS.NM_RETURN:
- case OS.NM_CLICK:
- NMLINK item = new NMLINK ();
- OS.MoveMemory (item, lParam, NMLINK.sizeof);
- Event event = new Event ();
- event.text = ids [item.iLink];
- sendSelectionEvent (SWT.Selection, event, true);
- break;
- }
+ switch (hdr.code) {
+ case OS.NM_RETURN:
+ case OS.NM_CLICK:
+ NMLINK item = new NMLINK ();
+ OS.MoveMemory (item, lParam, NMLINK.sizeof);
+ Event event = new Event ();
+ event.text = ids [item.iLink];
+ sendSelectionEvent (SWT.Selection, event, true);
+ break;
+ case OS.NM_CUSTOMDRAW:
+ NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
+ OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+ switch (nmcd.dwDrawStage) {
+ case OS.CDDS_PREPAINT:
+ if (!OS.IsWindowEnabled (handle) || linkForeground != -1) {
+ return new LRESULT(OS.CDRF_NOTIFYITEMDRAW);
+ }
+ break;
+ case OS.CDDS_ITEMPREPAINT:
+ /*
+ * Feature in Windows. SysLink32 control doesn't natively
+ * provide disabled state. Emulate it with custom draw.
+ */
+ if (!OS.IsWindowEnabled (handle)) {
+ OS.SetTextColor (nmcd.hdc, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+ }
+ else if (linkForeground != -1 && nmcd.dwItemSpec != -1) {
+ OS.SetTextColor(nmcd.hdc, linkForeground);
+ }
+ break;
+ }
+ break;
}
return super.wmNotifyChild (hdr, wParam, lParam);
}

Back to the top