diff options
author | Knut Radloff <kradloff> | 2003-07-15 15:21:56 +0000 |
---|---|---|
committer | Knut Radloff <kradloff> | 2003-07-15 15:21:56 +0000 |
commit | 6e328f67bc48bae3babf2d21c4d4332857a0675c (patch) | |
tree | bcfc9f7be8e755967e50f479c0123bd654a85f46 | |
parent | 85e3e91f7c5ab2935864a23260c5b4863a9eb03c (diff) | |
download | eclipse.platform.swt-6e328f67bc48bae3babf2d21c4d4332857a0675c.tar.gz eclipse.platform.swt-6e328f67bc48bae3babf2d21c4d4332857a0675c.tar.xz eclipse.platform.swt-6e328f67bc48bae3babf2d21c4d4332857a0675c.zip |
Fixes bug 37608
4 files changed, 222 insertions, 30 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index fc1fe9b3c9..8aa978f4f5 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -140,6 +140,7 @@ public class StyledText extends Canvas { int lastTextChangeReplaceLineCount; // text changed handler int lastTextChangeReplaceCharCount; boolean isBidi; + boolean isMirrored; boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color Image leftCaretBitmap = null; Image rightCaretBitmap = null; @@ -1600,8 +1601,8 @@ public StyledText(Composite parent, int style) { super.setForeground(getForeground()); super.setBackground(getBackground()); Display display = getDisplay(); - boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0; - isBidi = StyledTextBidi.isBidiPlatform() || isRightOriented; + isMirrored = (getStyle() & SWT.MIRRORED) != 0; + isBidi = StyledTextBidi.isBidiPlatform() || isMirrored; if ((style & SWT.READ_ONLY) != 0) { setEditable(false); } @@ -1623,7 +1624,7 @@ public StyledText(Composite parent, int style) { } else { createCaretBitmaps(); - if (isRightOriented) { + if (isMirrored) { BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI); } new Caret(this, SWT.NULL); @@ -1642,6 +1643,18 @@ public StyledText(Composite parent, int style) { String platform= SWT.getPlatform(); isCarbon = "carbon".equals(platform); + StyledTextBidi.addOrientationListener(this, + new Runnable() { + public void run() { + setOrientation(SWT.LEFT_TO_RIGHT); + } + }, + new Runnable() { + public void run() { + setOrientation(SWT.RIGHT_TO_LEFT); + } + } + ); // set the caret width, the height of the caret will default to the line height calculateScrollBars(); createKeyBindings(); @@ -2243,7 +2256,7 @@ void createKeyBindings() { setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); - if ((getStyle() & SWT.MIRRORED) == 0) { + if (isMirrored() == false) { setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS); setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT); setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS); @@ -2267,7 +2280,7 @@ void createKeyBindings() { setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); - if ((getStyle() & SWT.MIRRORED) == 0) { + if (isMirrored() == false) { setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT); setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); @@ -2306,7 +2319,7 @@ void createKeyBindings() { */ void createCaretBitmaps() { int caretWidth = BIDI_CARET_WIDTH; - int gcStyle = getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); + int gcStyle = isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; Display display = getDisplay(); if (caretPalette == null) { @@ -3252,7 +3265,7 @@ void doVisualPrevious() { // check if caret location is at the visual beginning of the line if (columnX <= XINSET && horizontalScrollOffset == 0) { return; - } + } String lineText = content.getLine(line); int lineLength = lineText.length(); GC gc = getGC(); @@ -3274,7 +3287,7 @@ void doVisualPrevious() { } else if (visualOffset == 0) { - boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0; + boolean isRightOriented = isMirrored(); //move to visual line end (i.e., behind L2R character/in front of R2L character at visual 0) if ((isRightOriented && bidi.isRightToLeft(offsetInLine) == false) || @@ -3358,7 +3371,7 @@ void doVisualNext() { visualOffset++; offsetInLine = bidi.getLogicalOffset(visualOffset); if (offsetInLine > 0 && offsetInLine < lineLength) { - boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0; + boolean isRightOriented = isMirrored(); if (isRightOriented) { boolean leftToRightStart = bidi.isRightToLeft(offsetInLine) == false && bidi.isRightToLeft(offsetInLine - 1); if (leftToRightStart) { @@ -5118,6 +5131,7 @@ void handleDispose() { if (isBidi()) { StyledTextBidi.removeLanguageListener(this); } + StyledTextBidi.removeOrientationListener(this); } /** * Scrolls the widget horizontally. @@ -5646,6 +5660,16 @@ boolean isLineDelimiter(int offset) { return offsetInLine > content.getLine(line).length(); } /** + * Returns whether the widget is mirrored (right oriented/right to left + * writing order). + * + * @return isMirrored true=the widget is right oriented, false=the widget + * is left oriented + */ +boolean isMirrored() { + return isMirrored; +} +/** * Returns whether or not the given lines are visible. * <p> * @@ -5882,7 +5906,7 @@ void performPaint(GC gc,int startLine,int startY, int renderHeight) { Color foreground = getForeground(); int lineCount = content.getLineCount(); int paintY = 0; - int gcStyle = getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); + int gcStyle = isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; if (isSingleLine()) { lineCount = 1; @@ -6897,7 +6921,7 @@ void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) { int lineStartOffset = content.getOffsetAtLine(caretLine); int offsetInLine = caretOffset - lineStartOffset; GC gc = null; - boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0; + boolean isRightOriented = isMirrored(); if (bidi == null) { gc = getGC(); @@ -7405,6 +7429,44 @@ void setMouseWordSelectionAnchor() { } } /** + * Sets the widget orientation (writing order). Text will be right aligned + * for right to left writing order. + * <p> + * + * @param newOrientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT + */ +void setOrientation(int orientation) { + if ((orientation & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)) == 0) { + return; + } + if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && (orientation & SWT.LEFT_TO_RIGHT) != 0) { + return; + } + if ((orientation & SWT.RIGHT_TO_LEFT) != 0) { + if (isMirrored()) { + return; + } + isMirrored = true; + } else { + if (isMirrored() == false) { + return; + } + isMirrored = false; + } + StyledTextBidi.setOrientation(this, orientation); + isBidi = StyledTextBidi.isBidiPlatform() || isMirrored(); + initializeRenderer(); + if (isBidi()) { + caretDirection = SWT.NULL; + createCaretBitmaps(); + setBidiCaretDirection(); + } + setCaretLocation(); + keyActionMap.clear(); + createKeyBindings(); + super.redraw(); +} +/** * Adjusts the maximum and the page size of the scroll bars to * reflect content width/length changes. */ @@ -8269,4 +8331,4 @@ void wordWrapResize(int oldClientAreaWidth) { // word wrap may have changed on one of the visible lines super.redraw(); } -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java index e76ba3a1d0..04d9f83d80 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java @@ -183,6 +183,20 @@ static void addLanguageListener(Control control, Runnable runnable) { BidiUtil.addLanguageListener(control.handle, runnable); } /** + * Adds a listener that is called when the widget orientation (writing order) + * is changed by the user. + * <p> + * + * @param control Control to add the keyboard language listener for. + * @param LTRRunnable the listener that is called when writing order is + * switched to "left to right" (left oriented text). + * @param RTLRunnable the listener that is called when writing order is + * switched to "right to left" (right oriented text). + */ +static void addOrientationListener(Control control, Runnable LTRRunnable, Runnable RTLRunnable) { + BidiUtil.addOrientationListener(control.handle, LTRRunnable, RTLRunnable); +} +/** * Answers the direction of the active keyboard language - either * L2R or R2L. The active keyboard language determines the direction * of the caret and can be changed by the user (e.g., via Alt-Shift on @@ -249,6 +263,15 @@ static void removeLanguageListener(Control control) { BidiUtil.removeLanguageListener(control.handle); } /** + * Removes the orientation listener for the specified window. + * <p> + * + * @param control window to remove the listener from. + */ +static void removeOrientationListener(Control control) { + BidiUtil.removeOrientationListener(control.handle); +} +/** * Calculates render positions using the glyph distance values in the dx array. */ private void calculateRenderPositions() { @@ -1049,6 +1072,16 @@ void setKeyboardLanguage(int logicalIndex) { BidiUtil.setKeyboardLanguage(language); } /** + * Sets the orientation (writing order) of the specified control. Text will + * be right aligned for right to left writing order. + * <p> + * + * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT + */ +static void setOrientation(Control control, int orientation) { + BidiUtil.setOrientation(control.handle, orientation); +} +/** * Returns a string representation of the receiver. * <p> * diff --git a/bundles/org.eclipse.swt/Eclipse SWT/emulated/bidi/org/eclipse/swt/internal/BidiUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/emulated/bidi/org/eclipse/swt/internal/BidiUtil.java index 44e937c82f..fa1e01366f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/emulated/bidi/org/eclipse/swt/internal/BidiUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/emulated/bidi/org/eclipse/swt/internal/BidiUtil.java @@ -45,6 +45,11 @@ public static void addLanguageListener(int hwnd, Runnable runnable) { } /* * Not implemented. + */ +public static void addOrientationListener(int hwnd, Runnable LTRRunnable, Runnable RTLRunnable) { +} +/* + * Not implemented. * */ public static void drawGlyphs(GC gc, char[] renderBuffer, int[] renderDx, int x, int y) { @@ -95,7 +100,16 @@ public static void removeLanguageListener(int hwnd) { /* * Not implemented. */ +public static void removeOrientationListener(int hwnd) { +} +/* + * Not implemented. + */ public static void setKeyboardLanguage(int language) { } - +/* + * Not implemented. + */ +public static void setOrientation(int hwnd, int orientation) { +} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java index 8082fe6f1a..38385df8eb 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java @@ -37,7 +37,8 @@ public class BidiUtil { // variables used for providing a listener mechanism for keyboard language // switching - static Hashtable map = new Hashtable (); + static Hashtable languageMap = new Hashtable (); + static Hashtable keyMap = new Hashtable (); static Hashtable oldProcMap = new Hashtable (); /* * This code is intentionally commented. In order @@ -98,16 +99,30 @@ public class BidiUtil { * monitored. * <p> * - * @param int the handle of the Control that is listening for keyboard language + * @param hwnd the handle of the Control that is listening for keyboard language * changes * @param runnable the code that should be executed when a keyboard language change * occurs */ -public static void addLanguageListener (int hwnd, Runnable runnable) { - map.put (new Integer (hwnd), runnable); - int oldProc = OS.GetWindowLong (hwnd, OS.GWL_WNDPROC); - oldProcMap.put (new Integer(hwnd), new Integer(oldProc)); - OS.SetWindowLong (hwnd, OS.GWL_WNDPROC, callback.getAddress ()); +public static void addLanguageListener(int hwnd, Runnable runnable) { + languageMap.put(new Integer(hwnd), runnable); + subclass(hwnd); +} +/** + * Adds a widget orientation (writing order) listener. The listener will get notified + * when the user switches the writing order using Ctrl-Shift. + * <p> + * + * @param hwnd the handle of the Control that is listening for widget orientation + * changes + * @param LTRRunnable the listener that is called when writing order is + * switched to "left to right" (left oriented text). + * @param RTLRunnable the listener that is called when writing order is + * switched to "right to left" (right oriented text). + */ +public static void addOrientationListener(int hwnd, Runnable LTRRunnable, Runnable RTLRunnable) { + keyMap.put(new Integer(hwnd), new Runnable[] {LTRRunnable, RTLRunnable}); + subclass(hwnd); } /** * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test. @@ -405,7 +420,7 @@ public static int getKeyboardLanguage() { * * @return integer array with an entry for each installed language */ -public static int[] getKeyboardLanguageList() { +static int[] getKeyboardLanguageList() { int maxSize = 10; int[] tempList = new int[maxSize]; int size = OS.GetKeyboardLayoutList(maxSize, tempList); @@ -479,13 +494,23 @@ public static boolean isKeyboardBidi() { * * @param hwnd the handle of the Control that is listening for keyboard language changes */ -public static void removeLanguageListener (int hwnd) { - map.remove (new Integer (hwnd)); - Integer proc = (Integer)oldProcMap.remove (new Integer (hwnd)); - if (proc == null) return; - OS.SetWindowLong (hwnd, OS.GWL_WNDPROC, proc.intValue()); +public static void removeLanguageListener(int hwnd) { + languageMap.remove(new Integer(hwnd)); + unsubclass(hwnd); } /** + * Removes the widget orientation (writing order) listener for the specified + * control. + * <p> + * + * @param hwnd the handle of the Control that is listening for widget + * orientation changes + */ +public static void removeOrientationListener(int hwnd) { + keyMap.remove(new Integer(hwnd)); + unsubclass(hwnd); +} +/** * Switch the keyboard language to the specified language type. We do * not distinguish between mulitple bidi or multiple non-bidi languages, so * set the keyboard to the first language of the given type. @@ -524,6 +549,36 @@ public static void setKeyboardLanguage(int language) { } } /** + * Sets the orientation (writing order) of the specified control. Text will + * be right aligned for right to left writing order. + * <p> + * + * @param hwnd the handle of the Control to change the orientation of + * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT + */ +public static void setOrientation (int hwnd, int orientation) { + int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); + if ((orientation & SWT.RIGHT_TO_LEFT) != 0) { + bits |= OS.WS_EX_LAYOUTRTL; + } else { + bits &= ~OS.WS_EX_LAYOUTRTL; + } + OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits); +} +/** + * Override the window proc. + * + * @param hwnd control to override the window proc of + */ +static void subclass(int hwnd) { + Integer key = new Integer(hwnd); + if (oldProcMap.get(key) == null) { + int oldProc = OS.GetWindowLong(hwnd, OS.GWL_WNDPROC); + oldProcMap.put(key, new Integer(oldProc)); + OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, callback.getAddress()); + } +} +/** * Reverse the character array. Used for right orientation. * * @param charArray character array to reverse @@ -571,7 +626,21 @@ static void translateOrder(int[] orderArray, int glyphCount, boolean isRightOrie } } /** - * Window proc to intercept keyboard language switch event (WS_INPUTLANGCHANGE). + * Remove the overridden the window proc. + * + * @param hwnd control to remove the window proc override for + */ +static void unsubclass(int hwnd) { + Integer key = new Integer(hwnd); + if (languageMap.get(key) == null && keyMap.get(key) == null) { + Integer proc = (Integer) oldProcMap.remove(key); + if (proc == null) return; + OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, proc.intValue()); + } +} +/** + * Window proc to intercept keyboard language switch event (WS_INPUTLANGCHANGE) + * and widget orientation changes. * Run the Control's registered runnable when the keyboard language is switched. * * @param hwnd handle of the control that is listening for the keyboard language @@ -579,13 +648,27 @@ static void translateOrder(int[] orderArray, int glyphCount, boolean isRightOrie * @param msg window message */ static int windowProc (int hwnd, int msg, int wParam, int lParam) { + Integer key = new Integer (hwnd); switch (msg) { case 0x51 /*OS.WM_INPUTLANGCHANGE*/: - Runnable runnable = (Runnable) map.get (new Integer (hwnd)); + Runnable runnable = (Runnable) languageMap.get (key); if (runnable != null) runnable.run (); break; - } - Integer oldProc = (Integer)oldProcMap.get(new Integer(hwnd)); + case OS.WM_KEYDOWN: + if (wParam == OS.VK_SHIFT) { + if (OS.GetKeyState (OS.VK_CONTROL) < 0) { + Runnable[] runnables = (Runnable[]) keyMap.get (key); + if (runnables == null) break; + if (OS.GetKeyState (0xA0 /* VK_LSHIFT */) < 0) { + if (runnables[0] != null) runnables[0].run (); + } else { + if (runnables[1] != null) runnables[1].run (); + } + } + } + break; + } + Integer oldProc = (Integer)oldProcMap.get(key); return OS.CallWindowProc (oldProc.intValue(), hwnd, msg, wParam, lParam); } |