changeset 6844:f5d934a037a8

RT-36636: [Accessibility] Mac font support added - had to implement NSAttributedString and NSDictionary
author Felipe Heidrich <felipe.heidrich@oracle.com>
date Wed, 23 Apr 2014 15:54:37 -0700
parents e8ee46b11faf
children 5af944034d68
files modules/graphics/src/main/java/com/sun/glass/ui/mac/MacAccessible.java modules/graphics/src/main/java/com/sun/glass/ui/mac/MacVariant.java modules/graphics/src/main/native-glass/mac/GlassAccessible.h modules/graphics/src/main/native-glass/mac/GlassAccessible.m
diffstat 4 files changed, 126 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacAccessible.java	Wed Apr 23 10:39:20 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacAccessible.java	Wed Apr 23 15:54:37 2014 -0700
@@ -45,6 +45,7 @@
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyCombination;
+import javafx.scene.text.Font;
 import com.sun.glass.ui.PlatformAccessible;
 import com.sun.glass.ui.Screen;
 import com.sun.glass.ui.View;
@@ -78,6 +79,9 @@
         if (!_initEnum("MacOrientation")) {
             System.err.println("Fail linking MacOrientation");
         }
+        if (!_initEnum("MacText")) {
+            System.err.println("Fail linking MacText");
+        }
     }
 
     static enum MacAttribute {
@@ -573,6 +577,20 @@
         ;long ptr; /* Initialized natively - treat as final */
     }
 
+    static enum MacText {
+        NSAccessibilityBackgroundColorTextAttribute,
+        NSAccessibilityForegroundColorTextAttribute,
+        NSAccessibilityUnderlineTextAttribute,
+        NSAccessibilityStrikethroughTextAttribute,
+        NSAccessibilityMarkedMisspelledTextAttribute,
+        NSAccessibilityFontTextAttribute,
+        NSAccessibilityFontNameKey,
+        NSAccessibilityFontFamilyKey,
+        NSAccessibilityVisibleNameKey,
+        NSAccessibilityFontSizeKey,
+        ;long ptr; /* Initialized natively - treat as final */
+    }
+
     /* Do not access the following lists directly from the Mac enums.
      * It can cause the static initialization to happen in an unexpected order.
      */
@@ -1595,7 +1613,36 @@
         }
         if (result == null) return null;
         switch (attr) {
-            case NSAccessibilityAttributedStringForRangeParameterizedAttribute:
+            case NSAccessibilityAttributedStringForRangeParameterizedAttribute: {
+                String text = (String)result;
+                text = text.substring(variant.int1, variant.int1 + variant.int2);
+                List<MacVariant> styles = new ArrayList<>();
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    MacVariant fontDict = new MacVariant();
+                    fontDict.type = MacVariant.NSDictionary;
+                    fontDict.longArray = new long[] {
+                        MacText.NSAccessibilityFontNameKey.ptr,
+                        MacText.NSAccessibilityFontFamilyKey.ptr,
+                        MacText.NSAccessibilityVisibleNameKey.ptr,
+                        MacText.NSAccessibilityFontSizeKey.ptr,
+                    };
+                    fontDict.variantArray = new MacVariant[] {
+                        MacVariant.createNSString(font.getName()),
+                        MacVariant.createNSString(font.getFamily()),
+                        MacVariant.createNSString(font.getName()),
+                        MacVariant.createNSNumberForDouble(font.getSize()),
+                    };
+
+                    fontDict.key = MacText.NSAccessibilityFontTextAttribute.ptr;
+                    fontDict.location = 0;
+                    fontDict.length = text.length();
+                    styles.add(fontDict);
+                }
+                MacVariant attrString = attr.map.apply(text);
+                attrString.variantArray = styles.toArray(new MacVariant[0]);
+                return attrString;
+            }
             case NSAccessibilityStringForRangeParameterizedAttribute: {
                 String text = (String)result;
                 result = text.substring(variant.int1, variant.int1 + variant.int2);
--- a/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacVariant.java	Wed Apr 23 10:39:20 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacVariant.java	Wed Apr 23 15:54:37 2014 -0700
@@ -35,10 +35,10 @@
     final static int NSArray_NSString = 2;
     final static int NSArray_int = 3;
     final static int NSArray_range = 4;
-    final static int NSAttributedString = 5;
+    final static int NSAttributedString = 5; /* Uses string for the text and variantArray for the styles */
     final static int NSData = 6;
     final static int NSDate = 7;
-    final static int NSDictionary = 8;
+    final static int NSDictionary = 8; /* Uses longArray for keys (NSString) and variantArray for values */
     final static int NSNumber_Boolean = 9;
     final static int NSNumber_Int = 10;
     final static int NSNumber_Float = 11;
@@ -55,6 +55,7 @@
     long[] longArray;
     int[] intArray;
     String[] stringArray;
+    MacVariant[] variantArray; /* Used by NSAttributedString and NSDictionary */
     float float1;
     float float2;
     float float3;
@@ -65,6 +66,11 @@
     long long1;
     double double1;
 
+    /* Used when the Variant represents an attribute within a NSAttributedString */
+    int location;
+    int length;
+    long key;
+
     static MacVariant createNSArray(Object result) {
         MacVariant variant = new MacVariant();
         variant.type = NSArray_id;
@@ -174,6 +180,8 @@
             case NSValue_point: return new float[] {float1, float2};
             case NSValue_size: return new float[] {float1, float2};
             case NSValue_rectangle: return new float[] {float1, float2, float3, float4};
+            case NSString: return string;
+            case NSAttributedString: return string;
             //TODO REST
         }
         return null;
@@ -186,6 +194,8 @@
             case NSArray_id: v = Arrays.toString((long[])v); break;
             case NSArray_int: v = Arrays.toString((int[])v); break;
             case NSValue_range: v = Arrays.toString((int[])v); break;
+            case NSAttributedString: v += Arrays.toString(variantArray); break;
+            case NSDictionary: v = "keys: " + Arrays.toString(longArray) + " values: " + Arrays.toString(variantArray);
         }
         return "MacVariant type: " + type + " value " + v;
     }
--- a/modules/graphics/src/main/native-glass/mac/GlassAccessible.h	Wed Apr 23 10:39:20 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassAccessible.h	Wed Apr 23 15:54:37 2014 -0700
@@ -34,11 +34,17 @@
 - (jobject)getJAccessible;
 @end
 
-id (^jLongToID)(void*, CFIndex);
-id (^jIntToNSNumber)(void*, CFIndex);
+/* The following blocks are used by jArrayToNSArray() to convert java types
+ * within a java array to a native type to be stored in the resulting NSArray.
+ */
+typedef id (^jMapper)(void*, CFIndex);
+jMapper jLongToID;
+jMapper jIntToNSNumber;
+jMapper jVariantToID;
+
 id variantToID(JNIEnv *env, jobject variant);
 NSString* jStringToNSString(JNIEnv *env, jstring string);
-NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, id (^)(void*, CFIndex));
+NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, jMapper);
 
 /* Accessible class IDs for classes, methods, and fields (this could be in GlassStatics.h) */
 
@@ -76,4 +82,8 @@
 jfieldID jVariantFloat4;
 jfieldID jVariantDouble1;
 jfieldID jVariantString;
+jfieldID jVariantVariantArray;
+jfieldID jVariantLocation;
+jfieldID jVariantLength;
+jfieldID jVariantKey;
 
--- a/modules/graphics/src/main/native-glass/mac/GlassAccessible.m	Wed Apr 23 10:39:20 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassAccessible.m	Wed Apr 23 15:54:37 2014 -0700
@@ -224,7 +224,7 @@
 
 @end
 
-NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, id (^mapper)(void*, CFIndex)) {
+NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, jMapper mapper) {
     if (srcArray == NULL) return NULL;
     jsize size = (*env)->GetArrayLength(env, srcArray);
 
@@ -232,6 +232,16 @@
     NSMutableArray *array = [NSMutableArray arrayWithCapacity: size];
     if (size <= 0) return array;
 
+    /* Do not use GetPrimitiveArrayCritical, variantToID() can be used recursively */
+    if (mapper == jVariantToID) {
+        for (CFIndex index = 0; index < size; index++) {
+            jobject element = (*env)->GetObjectArrayElement(env, srcArray, index);
+            if ((*env)->ExceptionCheck(env)) return NULL;
+            [array addObject: variantToID(env, element)];
+        }
+        return array;
+    }
+
     void* ptr = (*env)->GetPrimitiveArrayCritical(env, srcArray, 0);
     if (ptr) {
         @try {
@@ -281,11 +291,41 @@
         jstring string = (*env)->GetObjectField(env, variant, jVariantString);
         return jStringToNSString(env, string);
     }
+    case com_sun_glass_ui_mac_MacVariant_NSDictionary: {
+        jlongArray longArray = (*env)->GetObjectField(env, variant, jVariantLongArray);
+        jobjectArray objectArray = (*env)->GetObjectField(env, variant, jVariantVariantArray);
+        NSArray* keys = jArrayToNSArray(env, longArray, jLongToID);
+        NSArray* values = jArrayToNSArray(env, objectArray, jVariantToID);
+        if (keys != NULL && values != NULL && [keys count] == [values count]) {
+            return [NSDictionary dictionaryWithObjects: values forKeys: keys]; 
+        }
+        return NULL;
+    }
     case com_sun_glass_ui_mac_MacVariant_NSAttributedString: {
         jstring string = (*env)->GetObjectField(env, variant, jVariantString);
         NSString* nsString = jStringToNSString(env, string);
         if (nsString == NULL) return NULL;
-        NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:nsString];
+        NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:nsString];
+        jobjectArray stylesArray = (*env)->GetObjectField(env, variant, jVariantVariantArray);
+        if (stylesArray) {
+            /* Do not use GetPrimitiveArrayCritical for stylesArray */
+            jsize stylesCount = (*env)->GetArrayLength(env, stylesArray);
+
+            for (jsize index = 0; index < stylesCount; index++) {
+                /* jStyle is a special MacVariant with key, location, and length */
+                jobject jStyle = (*env)->GetObjectArrayElement(env, stylesArray, index);
+                if ((*env)->ExceptionCheck(env)) return NULL;
+                id value = variantToID(env, jStyle);
+                if (value) {
+                    jint location = (*env)->GetIntField(env, jStyle, jVariantLocation);
+                    jint length = (*env)->GetIntField(env, jStyle, jVariantLength);
+                    jlong key = (*env)->GetLongField(env, jStyle, jVariantKey);
+                    if (key) {
+                        [attrString addAttribute: (NSString *)key value: value range: NSMakeRange(location, length)];
+                    }
+                }
+            }
+        }
         return [attrString autorelease];
     }
     case com_sun_glass_ui_mac_MacVariant_NSValue_point: {
@@ -455,6 +495,14 @@
         if ((*env)->ExceptionCheck(env)) return;
         jVariantString = (*env)->GetFieldID(env, jVariantClass, "string", "Ljava/lang/String;");
         if ((*env)->ExceptionCheck(env)) return;
+        jVariantVariantArray = (*env)->GetFieldID(env, jVariantClass, "variantArray", "[Lcom/sun/glass/ui/mac/MacVariant;");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantLocation = (*env)->GetFieldID(env, jVariantClass, "location", "I");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantLength = (*env)->GetFieldID(env, jVariantClass, "length", "I");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantKey = (*env)->GetFieldID(env, jVariantClass, "key", "J");
+        if ((*env)->ExceptionCheck(env)) return;
     }
 
     jLongToID = ^(void* data, CFIndex index) {
@@ -464,6 +512,9 @@
     jIntToNSNumber = ^(void* data, CFIndex index) {
         return (id)[NSNumber numberWithInt: ((jint*)data)[index]];
     };
+
+    /* Special case, handled internally in jArrayToNSArray() */
+    jVariantToID = NULL;
 }
 
 /*