1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24// MARKER(update_precomp.py): autogen include statement, do not remove 25#include "precompiled_vcl.hxx" 26 27#include "aqua/salinst.h" 28 29#include "aqua11ytextwrapper.h" 30#include "aqua11ytextattributeswrapper.h" 31#include "aqua11yutil.h" 32 33#include <com/sun/star/accessibility/AccessibleTextType.hpp> 34#include <com/sun/star/awt/Rectangle.hpp> 35 36using namespace ::com::sun::star::accessibility; 37using namespace ::com::sun::star::awt; 38using namespace ::com::sun::star::lang; 39using namespace ::com::sun::star::uno; 40using namespace ::rtl; 41 42// Wrapper for XAccessibleText, XAccessibleEditableText and XAccessibleMultiLineText 43 44@implementation AquaA11yTextWrapper : NSObject 45 46+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { 47 return CreateNSString ( [ wrapper accessibleText ] -> getText() ); 48} 49 50+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value 51{ 52 // TODO 53 (void)wrapper; 54 (void)value; 55} 56 57+(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper { 58 return [ NSNumber numberWithLong: [ wrapper accessibleText ] -> getCharacterCount() ]; 59} 60 61+(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper { 62 return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ); 63} 64 65+(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { 66 if ( [ wrapper accessibleEditableText ] != nil ) { 67 NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; 68 OUString newText = GetOUString ( (NSString *) value ); 69 NSRange selectedTextRange = [ [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: wrapper ] rangeValue ]; 70 try { 71 [ wrapper accessibleEditableText ] -> replaceText ( selectedTextRange.location, selectedTextRange.location + selectedTextRange.length, newText ); 72 } catch ( const Exception & e ) { 73 // empty 74 } 75 [ pool release ]; 76 } 77} 78 79+(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper { 80 sal_Int32 start = [ wrapper accessibleText ] -> getSelectionStart(); 81 sal_Int32 end = [ wrapper accessibleText ] -> getSelectionEnd(); 82 if ( start != end ) { 83 return [ NSValue valueWithRange: NSMakeRange ( start, end - start ) ]; // true selection 84 } else { 85 long caretPos = [ wrapper accessibleText ] -> getCaretPosition(); 86 if ( caretPos < 0 || caretPos > [ wrapper accessibleText ] -> getCharacterCount() ) { 87 return nil; 88 } 89 return [ NSValue valueWithRange: NSMakeRange ( caretPos, 0 ) ]; // insertion point 90 } 91} 92 93+(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { 94 NSRange range = [ value rangeValue ]; 95 try { 96 [ wrapper accessibleText ] -> setSelection ( range.location, range.location + range.length ); 97 } catch ( const Exception & e ) { 98 // empty 99 } 100} 101 102+(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper { 103 // the OOo a11y API returns only the visible portion... 104 return [ NSValue valueWithRange: NSMakeRange ( 0, [ wrapper accessibleText ] -> getCharacterCount() ) ]; 105} 106 107+(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value 108{ 109 // do nothing 110 (void)wrapper; 111 (void)value; 112} 113 114+(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper 115{ 116 (void)wrapper; 117 return [ [ NSArray alloc ] init ]; // unsupported 118} 119 120+(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper 121{ 122 (void)wrapper; 123 return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; // unsupported 124} 125 126+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { 127 [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; 128} 129 130+(NSArray *)specialAttributeNames { 131 return [ NSArray arrayWithObjects: 132 NSAccessibilityValueAttribute, 133 NSAccessibilityNumberOfCharactersAttribute, 134 NSAccessibilitySelectedTextAttribute, 135 NSAccessibilitySelectedTextRangeAttribute, 136 NSAccessibilityVisibleCharacterRangeAttribute, 137 NSAccessibilitySharedTextUIElementsAttribute, 138 NSAccessibilitySharedCharacterRangeAttribute, 139 nil ]; 140} 141 142+(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames { 143 [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialParameterizedAttributeNames ] ]; 144} 145 146+(NSArray *)specialParameterizedAttributeNames { 147 return [ NSArray arrayWithObjects: 148 NSAccessibilityStringForRangeParameterizedAttribute, 149 NSAccessibilityAttributedStringForRangeParameterizedAttribute, 150 NSAccessibilityRangeForIndexParameterizedAttribute, 151 NSAccessibilityRangeForPositionParameterizedAttribute, 152 NSAccessibilityBoundsForRangeParameterizedAttribute, 153 NSAccessibilityStyleRangeForIndexParameterizedAttribute, 154 NSAccessibilityRTFForRangeParameterizedAttribute, 155 NSAccessibilityLineForIndexParameterizedAttribute, 156 NSAccessibilityRangeForLineParameterizedAttribute, 157 nil ]; 158} 159 160+(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { 161 NSNumber * lineNumber = nil; 162 try { 163 sal_Int32 line = [ wrapper accessibleMultiLineText ] -> getLineNumberAtIndex ( (sal_Int32) [ index intValue ] ); 164 lineNumber = [ NSNumber numberWithInt: line ]; 165 } catch ( IndexOutOfBoundsException & e ) { 166 // empty 167 } 168 return lineNumber; 169} 170 171+(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line { 172 NSValue * range = nil; 173 try { 174 TextSegment textSegment = [ wrapper accessibleMultiLineText ] -> getTextAtLineNumber ( [ line intValue ] ); 175 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; 176 } catch ( IndexOutOfBoundsException & e ) { 177 // empty 178 } 179 return range; 180} 181 182+(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { 183 int loc = [ range rangeValue ].location; 184 int len = [ range rangeValue ].length; 185 NSMutableString * textRange = [ [ NSMutableString alloc ] init ]; 186 try { 187 [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; 188 } catch ( IndexOutOfBoundsException & e ) { 189 // empty 190 } 191 return textRange; 192} 193 194+(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { 195 return [ AquaA11yTextAttributesWrapper createAttributedStringForElement: wrapper inOrigRange: range ]; 196} 197 198+(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { 199 NSValue * range = nil; 200 try { 201 TextSegment textSegment = [ wrapper accessibleText ] -> getTextBeforeIndex ( [ index intValue ], AccessibleTextType::GLYPH ); 202 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; 203 } catch ( IndexOutOfBoundsException & e ) { 204 // empty 205 } catch ( IllegalArgumentException & e ) { 206 // empty 207 } 208 return range; 209} 210 211+(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point { 212 NSValue * value = nil; 213 sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint ( [ AquaA11yUtil nsPointToVclPoint: point ] ); 214 if ( index > -1 ) { 215 value = [ AquaA11yTextWrapper rangeForIndexAttributeForElement: wrapper forParameter: [ NSNumber numberWithLong: index ] ]; 216 } 217 return value; 218} 219 220+(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { 221 NSValue * rect = nil; 222 try { 223 // TODO: this is ugly!!! 224 // the UNP-API can only return the bounds for a single character, not for a range 225 int loc = [ range rangeValue ].location; 226 int len = [ range rangeValue ].length; 227 int minx = 0x7fffffff, miny = 0x7fffffff, maxx = 0, maxy = 0; 228 for ( int i = 0; i < len; i++ ) { 229 Rectangle vclRect = [ wrapper accessibleText ] -> getCharacterBounds ( loc + i ); 230 if ( vclRect.X < minx ) { 231 minx = vclRect.X; 232 } 233 if ( vclRect.Y < miny ) { 234 miny = vclRect.Y; 235 } 236 if ( vclRect.Width + vclRect.X > maxx ) { 237 maxx = vclRect.Width + vclRect.X; 238 } 239 if ( vclRect.Height + vclRect.Y > maxy ) { 240 maxy = vclRect.Height + vclRect.Y; 241 } 242 } 243 if ( [ wrapper accessibleComponent ] != nil ) { 244 // get location on screen (must be added since get CharacterBounds returns values relative to parent) 245 Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen(); 246 Point pos ( minx + screenPos.X, miny + screenPos.Y ); 247 Point size ( maxx - minx, maxy - miny ); 248 NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ]; 249 rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ]; 250 //printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]); 251 } 252 } catch ( IndexOutOfBoundsException & e ) { 253 // empty 254 } 255 return rect; 256} 257 258+(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { 259 NSValue * range = nil; 260 try { 261 TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( [ index intValue ], AccessibleTextType::ATTRIBUTE_RUN ); 262 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; 263 } catch ( IndexOutOfBoundsException & e ) { 264 // empty 265 } catch ( IllegalArgumentException & e ) { 266 // empty 267 } 268 return range; 269} 270 271+(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { 272 NSData * rtfData = nil; 273 NSAttributedString * attrString = (NSAttributedString *) [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: wrapper forParameter: range ]; 274 if ( attrString != nil ) { 275 @try { 276 rtfData = [ attrString RTFFromRange: [ range rangeValue ] documentAttributes: nil ]; 277 } @catch ( NSException * e) { 278 // emtpy 279 } 280 } 281 return rtfData; 282} 283 284+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { 285 BOOL isSettable = NO; 286 if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] 287 || [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] 288 || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] 289 || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) { 290 if ( ! [ [ wrapper accessibilityAttributeValue: NSAccessibilityRoleAttribute ] isEqualToString: NSAccessibilityStaticTextRole ] ) { 291 isSettable = YES; 292 } 293 } 294 return isSettable; 295} 296 297@end 298