From 68ca086f2aba085285f36f384cd60ae8bd3d36e4 Mon Sep 17 00:00:00 2001 From: Moshe WAJNBERG Date: Mon, 11 Feb 2013 17:01:51 +0100 Subject: Bug 383185: [BDL] Provide API for consuming plugins for handling structured text display and base text direction enforcement --- bundles/org.eclipse.jface/META-INF/MANIFEST.MF | 3 +- .../util/BaseTextDirectionSegmentListener.java | 77 ++++++ .../src/org/eclipse/jface/util/BidiUtils.java | 295 +++++++++++++++++++++ .../jface/util/StructuredTextSegmentListener.java | 75 ++++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 bundles/org.eclipse.jface/src/org/eclipse/jface/util/BaseTextDirectionSegmentListener.java create mode 100644 bundles/org.eclipse.jface/src/org/eclipse/jface/util/BidiUtils.java create mode 100644 bundles/org.eclipse.jface/src/org/eclipse/jface/util/StructuredTextSegmentListener.java diff --git a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF index f5d0ded8cdd..169fa64e27b 100644 --- a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF @@ -35,7 +35,8 @@ Export-Package: org.eclipse.jface, org.eclipse.jface.wizard.images Require-Bundle: org.eclipse.swt;bundle-version="[3.6.0,4.0.0)";visibility:=reexport, org.eclipse.core.commands;bundle-version="[3.4.0,4.0.0)";visibility:=reexport, - org.eclipse.equinox.common;bundle-version="[3.3.0,4.0.0)" + org.eclipse.equinox.common;bundle-version="[3.3.0,4.0.0)", + org.eclipse.equinox.bidi;bundle-version="0.9.0";resolution:=optional Bundle-RequiredExecutionEnvironment: J2SE-1.4, CDC-1.1/Foundation-1.1 Import-Package: javax.xml.parsers, diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BaseTextDirectionSegmentListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BaseTextDirectionSegmentListener.java new file mode 100644 index 00000000000..12842928f52 --- /dev/null +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BaseTextDirectionSegmentListener.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.util; + +import org.eclipse.swt.events.SegmentListener; +import org.eclipse.swt.events.SegmentEvent; +/** + * This class defines the segment listener in order to enforce Base Text Direction (BTD) support + * + * @since 3.9 + */ +public final class BaseTextDirectionSegmentListener implements SegmentListener { + + private String textDirection; + + /** + * Creates a new segment listener instance in order to enforce Base Text Direction (BTD) support + * + * @param textDir the text direction + * Possible values are: + * + */ + protected BaseTextDirectionSegmentListener(String textDir) { + super(); + textDirection = textDir; + } + + public void getSegments(SegmentEvent event) { + if (BidiUtils.LEFT_TO_RIGHT.equalsIgnoreCase(textDirection) + || BidiUtils.RIGHT_TO_LEFT.equalsIgnoreCase(textDirection) + || BidiUtils.AUTO.equalsIgnoreCase(textDirection)) { + + int length = event.lineText.length(); + if (length > 0) { + event.segments = new int[2]; + event.segments[0] = 0; + event.segments[1] = length; + event.segmentsChars = new char[2]; + event.segmentsChars[0] = isRTLValue(event.lineText) ? BidiUtils.RLE : BidiUtils.LRE; + event.segmentsChars[1] = BidiUtils.PDF; + } + } + } + + private boolean isRTLValue(String stringValue){ + + if (stringValue == null || stringValue.length() == 0 || BidiUtils.LEFT_TO_RIGHT.equalsIgnoreCase(textDirection)) + return false; + + else if (BidiUtils.RIGHT_TO_LEFT.equalsIgnoreCase(textDirection)) + return true; + + for (int i = 0; i < stringValue.length(); i++) { + if (Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT + || Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC + || Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_ARABIC_NUMBER) + return true; + else if (Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_LEFT_TO_RIGHT) { + return false; + } + } + return false; + } +} diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BidiUtils.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BidiUtils.java new file mode 100644 index 00000000000..e492c640e51 --- /dev/null +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BidiUtils.java @@ -0,0 +1,295 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.util; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.swt.events.SegmentListener; +import org.eclipse.swt.widgets.Text; + +/** + * This class provides API to handle Base Text Direction (BTD) and + * Structured Text support for SWT Text widgets. + * + * @since 3.9 + */ +public final class BidiUtils { + + /** + * Left To Right Base Text Direction + */ + public static final String LEFT_TO_RIGHT = "ltr"; //$NON-NLS-1$ + + /** + * Right To Left Base Text Direction + */ + public static final String RIGHT_TO_LEFT = "rtl";//$NON-NLS-1$ + + /** + * Auto (Contextual) Base Text Direction + */ + public static final String AUTO = "auto";//$NON-NLS-1$ + + /** + * Bidi support is enabled + */ + public static final String BIDI_SUPPORT_ON = "y";//$NON-NLS-1$ + + /** + * Bidi support is disabled + */ + public static final String BIDI_SUPPORT_OFF = "n";//$NON-NLS-1$ + + /** + * Base Text Direction defined in {@link BidiUtils#getTextDirection()} + * + */ + public static final String BTD_DEFAULT = "default";//$NON-NLS-1$ + + /** + * Segment listener for LTR Base Text Direction + */ + private static final SegmentListener BASE_TEXT_DIRECTION_LTR = new BaseTextDirectionSegmentListener(LEFT_TO_RIGHT); + + /** + * Segment listener for RTL Base Text Direction + */ + private static final SegmentListener BASE_TEXT_DIRECTION_RTL = new BaseTextDirectionSegmentListener(RIGHT_TO_LEFT); + + + /** + * Segment listener for Auto (Contextual) Base Text Direction + */ + private static final SegmentListener BASE_TEXT_DIRECTION_AUTO = new BaseTextDirectionSegmentListener(AUTO); + + /** + * The map containing all the structured text segment listeners + */ + private static final Map structuredTextSegmentListenerMap = new HashMap(); + + /** + * The LRE char + */ + protected static final char LRE = 0x202A; + + /** + * The LRM char + */ + protected static final char LRM = 0x200E; + + /** + * The PDF char + */ + protected static final char PDF = 0x202C; + + /** + * The RLE char + */ + protected static final char RLE = 0x202B; + + /** + * Singleton. + */ + private static BidiUtils instance; + + /** + * Return the singleton instance of this class. + * + * @return the singleton instance + * + */ + public static BidiUtils getInstance() { + if (instance == null) { + instance = new BidiUtils(); + } + + return instance; + } + + private String bidiSupport = BIDI_SUPPORT_OFF; + private String textDirection = "";//$NON-NLS-1$ + + /** + * @return the textDirection. + *

+ * Possible values are: + *

+ * + * + */ + public String getTextDirection() { + return textDirection; + } + + /** + * @param textDirection the text direction to set. + *

+ * Possible values are: + *

+ */ + public void setTextDirection(String textDirection) { + if (textDirection != null + && !textDirection.equals(this.textDirection)) { + this.textDirection = textDirection; + } + } + + /** + * @return the bidiSupport. + *

+ * Possible values are: + *

+ */ + public String getBidiSupport() { + return bidiSupport; + } + + /** + * @param bidiSupport the bidi support to set. + * + *

+ * Possible values are: + *

+ */ + public void setBidiSupport(String bidiSupport) { + if (bidiSupport != null + && !bidiSupport.equals(this.bidiSupport)) { + this.bidiSupport = bidiSupport; + } + } + + /** + * @param field the SWT Text field to process. + * @param handlingType the type of handling + * + *

+ * Possible values are: + *

+ *

+ * One should use this API as follows: + *

+ *

+	 * 				Text inputField = new Text(shell, SWT.NONE);
+	 * 				BidiUtils.applyBidiProcessing(inputField, BidiUtils.BTD_DEFAULT);
+	 * 
+	 * 				Text emailField = new Text(shell, SWT.NONE);	  			
+	 * 				BidiUtils.applyBidiProcessing(emailField, BidiUtils.EMAIL);
+	 * 			  
+ *

+ * The 3 values {@link BidiUtils#LEFT_TO_RIGHT}, + * {@link BidiUtils#RIGHT_TO_LEFT} {@link BidiUtils#AUTO} are + * usable whatever Bidi support is on or off. + *

+ * The remaining values are usable only if bidi support is on. + *

+ * The 4 first values {@link BidiUtils#LEFT_TO_RIGHT}, + * {@link BidiUtils#RIGHT_TO_LEFT}, {@link BidiUtils#AUTO} and + * {@link BidiUtils#BTD_DEFAULT} are for Base Text Direction + * handling. The remaining values are for Structured Text + * handling. + *

+ * Note: + * {@link org.eclipse.swt.widgets.Text#addSegmentListener(SegmentListener)} + * is currently only implemented on Windows and GTK. + */ + public static void applyBidiProcessing(Text field, String handlingType) { + SegmentListener listener = null; + if ((listener = getSegmentListener(handlingType)) != null) { + field.addSegmentListener(listener); + } + } + + private static SegmentListener getSegmentListener(String handlingType) { + SegmentListener listener = null; + if (LEFT_TO_RIGHT.equals(handlingType)) { + listener = BASE_TEXT_DIRECTION_LTR; + } + else if (RIGHT_TO_LEFT.equals(handlingType)) { + listener = BASE_TEXT_DIRECTION_RTL; + } + else if (AUTO.equals(handlingType)) { + listener = BASE_TEXT_DIRECTION_AUTO; + } + else { + if (BIDI_SUPPORT_ON.equals(getInstance().getBidiSupport())) { + if (BTD_DEFAULT.equals(handlingType)) { + if (LEFT_TO_RIGHT.equals(getInstance().getTextDirection())) { + listener = BASE_TEXT_DIRECTION_LTR; + } + else if (RIGHT_TO_LEFT.equals(getInstance().getTextDirection())) { + listener = BASE_TEXT_DIRECTION_RTL; + } + else if (AUTO.equals(getInstance().getTextDirection())) { + listener = BASE_TEXT_DIRECTION_AUTO; + } + } + + Object handler = structuredTextSegmentListenerMap.get(handlingType); + if (handler != null) { + listener = (SegmentListener) handler; + } + else { + listener = new StructuredTextSegmentListener(handlingType); + structuredTextSegmentListenerMap.put(handlingType, listener); + } + } + } + return listener; + } +} diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/util/StructuredTextSegmentListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/StructuredTextSegmentListener.java new file mode 100644 index 00000000000..a02e6ca4438 --- /dev/null +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/util/StructuredTextSegmentListener.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.util; + +import org.eclipse.swt.events.SegmentListener; +import org.eclipse.swt.events.SegmentEvent; +import org.eclipse.equinox.bidi.advanced.ISTextExpert; +import org.eclipse.equinox.bidi.advanced.STextExpertFactory; + +/** + * This class defines the segment listener in order to enforce Structured Text (STT) support + * + * @since 3.9 + */ +public final class StructuredTextSegmentListener implements SegmentListener { + + private String textType; + + /** + * Creates a new segment listener instance in order to enforce Structured Text (STT) support. + * + * @param sttType the type for the structured Text + * Possible values are: + *

+ */ + protected StructuredTextSegmentListener(String sttType) { + super(); + textType = sttType; + } + + public void getSegments(SegmentEvent event) { + int length = event.lineText.length(); + int segments[]; + if (length > 0) { + try { + ISTextExpert expert = STextExpertFactory.getExpert(textType); + segments = expert.leanBidiCharOffsets(event.lineText); + event.segments = new int[segments.length + 2]; + event.segments[0] = 0; + System.arraycopy(segments, 0, event.segments, 1, + segments.length); + event.segments[segments.length + 1] = length; + event.segmentsChars = new char[event.segments.length]; + event.segmentsChars[0] = BidiUtils.LRE; + for (int i = 1; i < event.segments.length - 1; i++) + event.segmentsChars[i] = BidiUtils.LRM; + event.segmentsChars[event.segments.length - 1] = BidiUtils.PDF; + } catch (Exception ex) { + // Ignore for now + } + } + } +} \ No newline at end of file -- cgit v1.2.3