All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.util.BidiUtils Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2012, 2014 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.equinox.bidi.StructuredTextTypeHandlerFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BidiSegmentEvent;
import org.eclipse.swt.custom.BidiSegmentListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SegmentListener;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
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 {
	
	private static final boolean DEBUG = false;

	/**
	 * Left-To-Right Base Text Direction.
	 * @see #getTextDirection()
	 */
	public static final String LEFT_TO_RIGHT = "ltr"; //$NON-NLS-1$
	
	/**
	 * Right-To-Left Base Text Direction.
	 * @see #getTextDirection()
	 */
	public static final String RIGHT_TO_LEFT = "rtl";//$NON-NLS-1$

	/**
	 * Auto (contextual) Base Text Direction.
	 * @see #getTextDirection()
	 */
	public static final String AUTO = "auto";//$NON-NLS-1$
	
	/**
	 * Base Text Direction defined in {@link BidiUtils#getTextDirection()}
	 * @see #getSegmentListener(String)
	 * @see #applyBidiProcessing(Text, String)
	 */
	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);
	
	/**
	 * Listener cache. Map from structured text type id ({@link String})
	 * to structured text segment listener ({@link SegmentListener}).
	 */
	private static final Map structuredTextSegmentListeners = new HashMap();
	
	/**
	 * The LRE char
	 */
	static final char LRE = 0x202A;
	
	/**
	 * The LRM char
	 */
	static final char LRM = 0x200E;
	
	/**
	 * The PDF char
	 */
	static final char PDF = 0x202C;
	
	/**
	 * The RLE char
	 */
	static final char RLE = 0x202B;
	
	private static boolean bidiSupport = false;
	private static String textDirection = "";//$NON-NLS-1$
	
	private BidiUtils() {
		// no instances
	}
	
	/**
	 * Returns the Base Text Direction. Possible values are:
	 * 
    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • null (no direction set)
  • *
* * @return the base text direction */ public static String getTextDirection() { return textDirection; } /** * Sets the Base Text Direction. Possible values are: *
    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • null (no default direction)
  • *
* * @param direction the text direction to set * @throws IllegalArgumentException if direction is not legal */ public static void setTextDirection(String direction) { if (direction == null || LEFT_TO_RIGHT.equals(direction) || RIGHT_TO_LEFT.equals(direction) || AUTO.equals(direction)) { textDirection = direction; } else { throw new IllegalArgumentException(direction); } } /** * Returns whether bidi support is enabled. * * @return true iff bidi support is enabled */ public static boolean getBidiSupport() { return bidiSupport; } /** * Enables or disables bidi support. * * @param bidi true to enable bidi support, false to disable */ public static void setBidiSupport(boolean bidi) { bidiSupport = bidi; } /** * Applies bidi processing to the given text field. * *

* Possible values for handlingType are: *

    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • {@link BidiUtils#BTD_DEFAULT}
  • *
  • the String constants in {@link StructuredTextTypeHandlerFactory}
  • *
  • if OSGi is running, the types that have been contributed to the * org.eclipse.equinox.bidi.bidiTypes extension point.
  • *
*

* The 3 values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT}, and {@link #AUTO} are * usable whether {@link #getBidiSupport() bidi support} is enabled or disabled. *

* The remaining values only have an effect if bidi support is enabled. *

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

* Note: * If this method is called on a text control, then {@link #applyTextDirection(Control, String)} must not be called on the same control. *

* Note: The Structured Text handling only works if the org.eclipse.equinox.bidi * bundle is on the classpath! *

* *

* Note: * {@link org.eclipse.swt.widgets.Text#addSegmentListener(SegmentListener)} * is currently only implemented on Windows and GTK, so this method won't have an effect on Cocoa. * * @param field the text field * @param handlingType the type of handling * @throws IllegalArgumentException * if handlingType is not a known type identifier */ public static void applyBidiProcessing(Text field, String handlingType) { SegmentListener listener = getSegmentListener(handlingType); if (listener != null) { field.addSegmentListener(listener); if (DEBUG) { int color = 0; if (LEFT_TO_RIGHT.equals(handlingType)) { color = SWT.COLOR_RED; } else if (RIGHT_TO_LEFT.equals(handlingType)) { color = SWT.COLOR_GREEN; } else if (BTD_DEFAULT.equals(handlingType)) { color = SWT.COLOR_YELLOW; } else if (AUTO.equals(handlingType)) { color = SWT.COLOR_MAGENTA; } else { color = SWT.COLOR_CYAN; } field.setBackground(field.getDisplay().getSystemColor(color)); if (field.getMessage().length() == 0) { field.setMessage('<' + handlingType + '>'); } if (field.getToolTipText() == null) { field.setToolTipText('<' + handlingType + '>'); } } } } /** * Applies bidi processing to the given styled text field. * *

* Possible values for handlingType are: *

    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • {@link BidiUtils#BTD_DEFAULT}
  • *
  • the String constants in {@link StructuredTextTypeHandlerFactory}
  • *
  • if OSGi is running, the types that have been contributed to the * org.eclipse.equinox.bidi.bidiTypes extension point.
  • *
*

* The 3 values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT}, and {@link #AUTO} are * usable whether {@link #getBidiSupport() bidi support} is enabled or disabled. *

* The remaining values only have an effect if bidi support is enabled. *

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

* Note: * If this method is called on a text control, then {@link #applyTextDirection(Control, String)} must not be called on the same control. *

* Note: The Structured Text handling only works if the org.eclipse.equinox.bidi * bundle is on the classpath! *

* * @param field the styled text field * @param handlingType the type of handling * @throws IllegalArgumentException * if handlingType is not a known type identifier */ public static void applyBidiProcessing(StyledText field, String handlingType) { final SegmentListener listener = getSegmentListener(handlingType); if (listener != null) { field.addBidiSegmentListener(new BidiSegmentListener() { @Override public void lineGetSegments(BidiSegmentEvent event) { listener.getSegments(event); } }); } } /** * Applies bidi processing to the given combo. * *

* Possible values for handlingType are: *

    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • {@link BidiUtils#BTD_DEFAULT}
  • *
  • the String constants in * {@link StructuredTextTypeHandlerFactory}
  • *
  • if OSGi is running, the types that have been contributed to the * org.eclipse.equinox.bidi.bidiTypes extension point.
  • *
*

* The 3 values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT}, and * {@link #AUTO} are usable whether {@link #getBidiSupport() bidi support} * is enabled or disabled. *

* The remaining values only have an effect if bidi support is enabled. *

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

* Note: If this method is called on a combo control, then * {@link #applyTextDirection(Control, String)} must not be called on the * same control. *

* Note: The Structured Text handling only works if the * org.eclipse.equinox.bidi bundle is on the classpath! *

* *

* Note: * {@link org.eclipse.swt.widgets.Combo#addSegmentListener(SegmentListener)} * is currently only implemented on Windows so this method won't have an * effect on Cocoa and GTK. * * @param combo * the combo field * @param handlingType * the type of handling * @throws IllegalArgumentException * if handlingType is not a known type identifier * @since 3.10 */ public static void applyBidiProcessing(Combo combo, String handlingType) { SegmentListener listener = getSegmentListener(handlingType); if (listener != null) { combo.addSegmentListener(listener); if (DEBUG) { int color = 0; if (LEFT_TO_RIGHT.equals(handlingType)) { color = SWT.COLOR_RED; } else if (RIGHT_TO_LEFT.equals(handlingType)) { color = SWT.COLOR_GREEN; } else if (BTD_DEFAULT.equals(handlingType)) { color = SWT.COLOR_YELLOW; } else if (AUTO.equals(handlingType)) { color = SWT.COLOR_MAGENTA; } else { color = SWT.COLOR_CYAN; } combo.setBackground(combo.getDisplay().getSystemColor(color)); if (combo.getToolTipText() == null) { combo.setToolTipText('<' + handlingType + '>'); } } } } /** * Returns a segment listener for the given handlingType that * can e.g. be passed to {@link Text#addSegmentListener(SegmentListener)}. * *

* Note: The Structured Text handling only works if the * org.eclipse.equinox.bidi bundle is on the classpath! *

* * @param handlingType * the handling type as specified in * {@link #applyBidiProcessing(Text, String)} * @return the segment listener, or null if no handling is * required * @throws IllegalArgumentException * if handlingType is not a known type identifier * @see #applyBidiProcessing(Text, String) */ public 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 (getBidiSupport()) { if (BTD_DEFAULT.equals(handlingType)) { if (LEFT_TO_RIGHT.equals(getTextDirection())) { listener = BASE_TEXT_DIRECTION_LTR; } else if (RIGHT_TO_LEFT.equals(getTextDirection())) { listener = BASE_TEXT_DIRECTION_RTL; } else if (AUTO.equals(getTextDirection())) { listener = BASE_TEXT_DIRECTION_AUTO; } } else { Object handler = structuredTextSegmentListeners.get(handlingType); if (handler != null) { listener = (SegmentListener) handler; } else { listener = new StructuredTextSegmentListener(handlingType); structuredTextSegmentListeners.put(handlingType, listener); } } } return listener; } /** * Applies a Base Text Direction to the given control (and its descendants, if it's a {@link Composite}). * *

* Possible values for textDirection are: *

    *
  • {@link BidiUtils#LEFT_TO_RIGHT}
  • *
  • {@link BidiUtils#RIGHT_TO_LEFT}
  • *
  • {@link BidiUtils#AUTO}
  • *
  • {@link BidiUtils#BTD_DEFAULT}
  • *
*

* The 3 values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT}, and {@link BidiUtils#AUTO} are * usable whether {@link #getBidiSupport() bidi support} is enabled or disabled. *

* {@link BidiUtils#AUTO} currently only works for {@link Text}, {@link StyledText}, and {@link Combo} controls. *

* The remaining value {@link BidiUtils#BTD_DEFAULT} only has an effect if bidi support is enabled. * *

* Note: * If this method is called on a control, then no applyBidiProcessing method must be called on the same control. *

* Note: * {@link org.eclipse.swt.widgets.Control#setTextDirection(int)} * is currently only implemented on Windows, so the direction won't be inherited by descendants on GTK and Cocoa. *

* Note: * {@link BidiUtils#BTD_DEFAULT} is currently not inherited by descendants of the control if * {@link BidiUtils#getTextDirection()} is {@link BidiUtils#AUTO}. * * @param control the control * @param textDirection the text direction */ public static void applyTextDirection(Control control, String textDirection) { int textDir = 0; boolean auto = false; if (LEFT_TO_RIGHT.equals(textDirection)) { textDir = SWT.LEFT_TO_RIGHT; } else if (RIGHT_TO_LEFT.equals(textDirection)) { textDir = SWT.RIGHT_TO_LEFT; } else if (AUTO.equals(textDirection)) { auto = true; } else if (getBidiSupport() && BTD_DEFAULT.equals(textDirection)) { if (LEFT_TO_RIGHT.equals(getTextDirection())) { textDir = SWT.LEFT_TO_RIGHT; } else if (RIGHT_TO_LEFT.equals(getTextDirection())) { textDir = SWT.RIGHT_TO_LEFT; } else if (AUTO.equals(getTextDirection())) { auto = true; } } if (control instanceof Text && (auto || textDir != 0)) { applyBidiProcessing((Text) control, textDirection); } else if (control instanceof StyledText && (auto || textDir != 0)) { applyBidiProcessing((StyledText) control, textDirection); } else if (control instanceof Combo && (auto || textDir != 0)) { applyBidiProcessing((Combo) control, textDirection); } else if (textDir != 0) { control.setTextDirection(textDir); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy