1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: aqua11ytextwrapper.mm,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_vcl.hxx"
36 #include "aqua11ytextwrapper.h"
37 #include "aqua11ytextattributeswrapper.h"
38 #include "aqua11yutil.h"
39 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
40 #include <com/sun/star/awt/Rectangle.hpp>
42 using namespace ::com::sun::star::accessibility;
43 using namespace ::com::sun::star::awt;
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::uno;
46 using namespace ::rtl;
48 // Wrapper for XAccessibleText, XAccessibleEditableText and XAccessibleMultiLineText
50 @implementation AquaA11yTextWrapper : NSObject
52 +(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper {
53 return CreateNSString ( [ wrapper accessibleText ] -> getText() );
56 +(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value {
60 +(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper {
61 return [ NSNumber numberWithLong: [ wrapper accessibleText ] -> getCharacterCount() ];
64 +(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper {
65 return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() );
68 +(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value {
69 if ( [ wrapper accessibleEditableText ] != nil ) {
70 NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
71 OUString newText = GetOUString ( (NSString *) value );
72 NSRange selectedTextRange = [ [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: wrapper ] rangeValue ];
74 [ wrapper accessibleEditableText ] -> replaceText ( selectedTextRange.location, selectedTextRange.location + selectedTextRange.length, newText );
75 } catch ( const Exception & e ) {
82 +(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper {
83 sal_Int32 start = [ wrapper accessibleText ] -> getSelectionStart();
84 sal_Int32 end = [ wrapper accessibleText ] -> getSelectionEnd();
86 return [ NSValue valueWithRange: NSMakeRange ( start, end - start ) ]; // true selection
88 long caretPos = [ wrapper accessibleText ] -> getCaretPosition();
89 if ( caretPos < 0 || caretPos > [ wrapper accessibleText ] -> getCharacterCount() ) {
92 return [ NSValue valueWithRange: NSMakeRange ( caretPos, 0 ) ]; // insertion point
96 +(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value {
97 NSRange range = [ value rangeValue ];
99 [ wrapper accessibleText ] -> setSelection ( range.location, range.location + range.length );
100 } catch ( const Exception & e ) {
105 +(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper {
106 // the OOo a11y API returns only the visible portion...
107 return [ NSValue valueWithRange: NSMakeRange ( 0, [ wrapper accessibleText ] -> getCharacterCount() ) ];
110 +(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value {
114 +(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper {
115 return [ [ NSArray alloc ] init ]; // unsupported
118 +(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper {
119 return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; // unsupported
122 +(void)addAttributeNamesTo:(NSMutableArray *)attributeNames {
123 [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialAttributeNames ] ];
126 +(NSArray *)specialAttributeNames {
127 return [ NSArray arrayWithObjects:
128 NSAccessibilityValueAttribute,
129 NSAccessibilityNumberOfCharactersAttribute,
130 NSAccessibilitySelectedTextAttribute,
131 NSAccessibilitySelectedTextRangeAttribute,
132 NSAccessibilityVisibleCharacterRangeAttribute,
133 NSAccessibilitySharedTextUIElementsAttribute,
134 NSAccessibilitySharedCharacterRangeAttribute,
138 +(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames {
139 [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialParameterizedAttributeNames ] ];
142 +(NSArray *)specialParameterizedAttributeNames {
143 return [ NSArray arrayWithObjects:
144 NSAccessibilityStringForRangeParameterizedAttribute,
145 NSAccessibilityAttributedStringForRangeParameterizedAttribute,
146 NSAccessibilityRangeForIndexParameterizedAttribute,
147 NSAccessibilityRangeForPositionParameterizedAttribute,
148 NSAccessibilityBoundsForRangeParameterizedAttribute,
149 NSAccessibilityStyleRangeForIndexParameterizedAttribute,
150 NSAccessibilityRTFForRangeParameterizedAttribute,
151 NSAccessibilityLineForIndexParameterizedAttribute,
152 NSAccessibilityRangeForLineParameterizedAttribute,
156 +(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index {
157 NSNumber * lineNumber = nil;
159 sal_Int32 line = [ wrapper accessibleMultiLineText ] -> getLineNumberAtIndex ( (sal_Int32) [ index intValue ] );
160 lineNumber = [ NSNumber numberWithInt: line ];
161 } catch ( IndexOutOfBoundsException & e ) {
167 +(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line {
168 NSValue * range = nil;
170 TextSegment textSegment = [ wrapper accessibleMultiLineText ] -> getTextAtLineNumber ( [ line intValue ] );
171 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ];
172 } catch ( IndexOutOfBoundsException & e ) {
178 +(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range {
179 int loc = [ range rangeValue ].location;
180 int len = [ range rangeValue ].length;
181 NSMutableString * textRange = [ [ NSMutableString alloc ] init ];
183 [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ];
184 } catch ( IndexOutOfBoundsException & e ) {
190 +(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range {
191 return [ AquaA11yTextAttributesWrapper createAttributedStringForElement: wrapper inOrigRange: range ];
194 +(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index {
195 NSValue * range = nil;
197 TextSegment textSegment = [ wrapper accessibleText ] -> getTextBeforeIndex ( [ index intValue ], AccessibleTextType::GLYPH );
198 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ];
199 } catch ( IndexOutOfBoundsException & e ) {
201 } catch ( IllegalArgumentException & e ) {
207 +(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point {
208 NSValue * value = nil;
209 sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint ( [ AquaA11yUtil nsPointToVclPoint: point ] );
211 value = [ AquaA11yTextWrapper rangeForIndexAttributeForElement: wrapper forParameter: [ NSNumber numberWithLong: index ] ];
216 +(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range {
217 NSValue * rect = nil;
219 // TODO: this is ugly!!!
220 // the UNP-API can only return the bounds for a single character, not for a range
221 int loc = [ range rangeValue ].location;
222 int len = [ range rangeValue ].length;
223 int minx = 0x7fffffff, miny = 0x7fffffff, maxx = 0, maxy = 0;
224 for ( int i = 0; i < len; i++ ) {
225 Rectangle vclRect = [ wrapper accessibleText ] -> getCharacterBounds ( loc + i );
226 if ( vclRect.X < minx ) {
229 if ( vclRect.Y < miny ) {
232 if ( vclRect.Width + vclRect.X > maxx ) {
233 maxx = vclRect.Width + vclRect.X;
235 if ( vclRect.Height + vclRect.Y > maxy ) {
236 maxy = vclRect.Height + vclRect.Y;
239 if ( [ wrapper accessibleComponent ] != nil ) {
240 // get location on screen (must be added since get CharacterBounds returns values relative to parent)
241 Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
242 Point pos ( minx + screenPos.X, miny + screenPos.Y );
243 Point size ( maxx - minx, maxy - miny );
244 NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ];
245 rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ];
246 //printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]);
248 } catch ( IndexOutOfBoundsException & e ) {
254 +(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index {
255 NSValue * range = nil;
257 TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( [ index intValue ], AccessibleTextType::ATTRIBUTE_RUN );
258 range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ];
259 } catch ( IndexOutOfBoundsException & e ) {
261 } catch ( IllegalArgumentException & e ) {
267 +(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range {
268 NSData * rtfData = nil;
269 NSAttributedString * attrString = (NSAttributedString *) [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: wrapper forParameter: range ];
270 if ( attrString != nil ) {
272 rtfData = [ attrString RTFFromRange: [ range rangeValue ] documentAttributes: nil ];
273 } @catch ( NSException * e) {
280 +(MacOSBOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper {
281 MacOSBOOL isSettable = NO;
282 if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ]
283 || [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ]
284 || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ]
285 || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) {
286 if ( ! [ [ wrapper accessibilityAttributeValue: NSAccessibilityRoleAttribute ] isEqualToString: NSAccessibilityStaticTextRole ] ) {