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