merge the formfield patch from ooo-build
[ooovba.git] / vcl / aqua / source / a11y / aqua11ywrapper.mm
blob64e0e9ef030827186fca61c3a886fdfe7e57ba26
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  * 
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: aqua11ywrapper.mm,v $
10  *
11  * $Revision: 1.3 $
12  *
13  * This file is part of OpenOffice.org.
14  *
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.
18  *
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).
24  *
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.
29  *
30  ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_vcl.hxx"
35 #include "salinst.h"
36 #include "aqua11ywrapper.h"
37 #include "aqua11yactionwrapper.h"
38 #include "aqua11ycomponentwrapper.h"
39 #include "aqua11ylistener.hxx"
40 #include "aqua11yselectionwrapper.h"
41 #include "aqua11ytablewrapper.h"
42 #include "aqua11ytextwrapper.h"
43 #include "aqua11yvaluewrapper.h"
44 #include "aqua11yfactory.h"
45 #include "aqua11yfocuslistener.hxx"
46 #include "aqua11yfocustracker.hxx"
47 #include "aqua11yrolehelper.h"
48 #include <com/sun/star/accessibility/AccessibleRole.hpp>
49 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
50 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
51 #include <com/sun/star/awt/Size.hpp>
52 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
53 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
54 #include <com/sun/star/lang/DisposedException.hpp>
56 using namespace ::com::sun::star::accessibility;
57 using namespace ::com::sun::star::awt;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::uno;
61 @interface SalFrameWindow : NSWindow
64 -(Reference<XAccessibleContext>)accessibleContext;
65 @end
67 static MacOSBOOL isPopupMenuOpen = NO;
69 @implementation AquaA11yWrapper : NSView
71 #pragma mark -
72 #pragma mark Init and dealloc
74 -(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext {
75     self = [ super init ];
76     if ( self != nil ) {
77         [ self setDefaults: rxAccessibleContext ];
78     }
79     return self;
82 -(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext {
83     mDefaultFontsize = 0.0;
84     mpDefaultFontname = nil;
85     mpReferenceWrapper = new ReferenceWrapper;
86     mActsAsRadioGroup = NO;
87     mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext;
88     mIsTableCell = NO;
89     // Querying all supported interfaces
90     try {
91         // XAccessibleComponent
92         mpReferenceWrapper -> rAccessibleComponent = Reference < XAccessibleComponent > ( rxAccessibleContext, UNO_QUERY );
93         // XAccessibleExtendedComponent
94         mpReferenceWrapper -> rAccessibleExtendedComponent = Reference < XAccessibleExtendedComponent > ( rxAccessibleContext, UNO_QUERY );
95         // XAccessibleSelection
96         mpReferenceWrapper -> rAccessibleSelection = Reference< XAccessibleSelection > ( rxAccessibleContext, UNO_QUERY );
97         // XAccessibleTable
98         mpReferenceWrapper -> rAccessibleTable = Reference < XAccessibleTable > ( rxAccessibleContext, UNO_QUERY );
99         // XAccessibleText
100         mpReferenceWrapper -> rAccessibleText = Reference < XAccessibleText > ( rxAccessibleContext, UNO_QUERY );
101         // XAccessibleEditableText
102         mpReferenceWrapper -> rAccessibleEditableText = Reference < XAccessibleEditableText > ( rxAccessibleContext, UNO_QUERY );
103         // XAccessibleValue
104         mpReferenceWrapper -> rAccessibleValue = Reference < XAccessibleValue > ( rxAccessibleContext, UNO_QUERY );
105         // XAccessibleAction
106         mpReferenceWrapper -> rAccessibleAction = Reference < XAccessibleAction > ( rxAccessibleContext, UNO_QUERY );
107         // XAccessibleTextAttributes
108         mpReferenceWrapper -> rAccessibleTextAttributes = Reference < XAccessibleTextAttributes > ( rxAccessibleContext, UNO_QUERY );
109         // XAccessibleMultiLineText
110         mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY );
111         // XAccessibleEventBroadcaster
112         #if 0
113         /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children.
114            That means we need to cache this, else e.g. tree list boxes are not accessible (moreover
115            it crashes by notifying dead objects - which would seemt o be another bug)
116            
117            FIXME:
118            Unfortunately this can increase memory consumption drastically until the non transient parent
119            is destroyed an finally all the transients are released.
120         */
121         if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) )
122         #endif
123         {
124             Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY);
125             if( xBroadcaster.is() ) {
126                 /*
127                  * We intentionally do not hold a reference to the event listener in the wrapper object,
128                  * but let the listener control the life cycle of the wrapper instead ..
129                  */
130                 xBroadcaster->addEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) );
131             }
132         }
133         // TABLE_CELL
134         if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) {
135             mIsTableCell = YES;
136         }
137     } catch ( const Exception ) {
138     }
141 -(void)dealloc {
142     if ( mpReferenceWrapper != nil ) {
143         delete mpReferenceWrapper;
144     }
145     if ( mpDefaultFontname != nil ) {
146         [ mpDefaultFontname release ];
147     }
148     [ super dealloc ];
151 #pragma mark -
152 #pragma mark Utility Section
154 // generates selectors for attribute name AXAttributeNameHere
155 // (getter without parameter) attributeNameHereAttribute
156 // (getter with parameter)    attributeNameHereAttributeForParameter:
157 // (setter)                   setAttributeNameHereAttributeForElement:to:
158 -(SEL)selectorForAttribute:(NSString *)attribute asGetter:(MacOSBOOL)asGetter withGetterParameter:(MacOSBOOL)withGetterParameter {
159     SEL selector = nil;
160     NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
161     @try {
162         // step 1: create method name from attribute name
163         NSMutableString * methodName = [ NSMutableString string ];
164         if ( ! asGetter ) {
165             [ methodName appendString: @"set" ];
166         }
167         NSString * firstChar = [ attribute substringWithRange: NSMakeRange ( 2, 1 ) ]; // drop leading "AX" and get first char
168         if ( asGetter ) {
169             [ methodName appendString: [ firstChar lowercaseString ] ]; 
170         } else {
171             [ methodName appendString: firstChar ]; 
172         }
173         [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name
174         // append rest of method name
175         [ methodName appendString: @"Attribute" ];
176         if ( ! asGetter ) {
177             [ methodName appendString: @"ForElement:to:" ];
178         } else if ( asGetter && withGetterParameter ) {
179             [ methodName appendString: @"ForParameter:" ];
180         }
181         // step 2: create selector
182         selector = NSSelectorFromString ( methodName );
183     } @catch ( id exception ) {
184         selector = nil;
185     }
186     [ pool release ];
187     return selector;
190 -(Reference < XAccessible >)getFirstRadioButtonInGroup {
191     Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
192     if( rxAccessibleRelationSet.is() )
193     {
194         AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
195         if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() )
196             return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY );
197     }
198     return Reference < XAccessible > ();
201 -(MacOSBOOL)isFirstRadioButtonInGroup {
202     Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ];
203     if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) {
204         return YES;
205     }
206     return NO;
209 #pragma mark -
210 #pragma mark Attribute Value Getters
211 // ( called via Reflection by accessibilityAttributeValue )
214     Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their
215     RelationSet. In NSAccessibility the relationship is axpressed through the hierarchy. A AXRadioGroup contains two or more AXRadioButton 
216     objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all 
217     attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes. 
218     So in this five methods there is a special treatment for radio buttons and groups.
221 -(id)roleAttribute {
222     if ( mActsAsRadioGroup ) {
223         return NSAccessibilityRadioGroupRole;
224     } else {
225         return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ];
226     }
229 -(id)subroleAttribute {
230     if ( mActsAsRadioGroup ) {
231         return @"";
232     } else {
233         NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
234         if ( ! [ subRole isEqualToString: @"" ] ) {
235             return subRole;
236         } else {
237             [ subRole release ];
238             return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ];
239         }
240     }
243 -(id)titleAttribute {
244     return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() );
247 -(id)descriptionAttribute {
248     if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
249         return [ self titleAttribute ];
250     } else if ( [ self accessibleExtendedComponent ] != nil ) {
251         return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ];
252     } else {
253         return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
254     }
257 -(id)enabledAttribute {
258     if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
259         return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ];
260     } else {
261         return nil;
262     }
265 -(id)focusedAttribute {
266     if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
267         id isFocused = nil;
268         Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent();
269         if ( rxParent.is() ) {
270             Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext();
271             if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) {
272                 isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
273             }
274         }
275         return isFocused;
276     } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
277         return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
278     } else {
279         return nil;
280     }
283 -(id)parentAttribute {
284     if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) {
285         Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ];
286         if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
287             Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext();
288             id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ];
289             [ parent_wrapper autorelease ];
290             return NSAccessibilityUnignoredAncestor( parent_wrapper );
291         }
292         return nil;
293     }
294     try {
295         Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() );
296         if ( xParent.is() ) {
297             Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() );
298             if ( xContext.is() ) {
299                 id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ];
300                 [ parent_wrapper autorelease ];
301                 return NSAccessibilityUnignoredAncestor( parent_wrapper );
302             }
303         }
304     } catch (const Exception&) {
305     }
306     
307     OSL_ASSERT( 0 );
308     return nil;
311 -(id)childrenAttribute {
312     if ( mActsAsRadioGroup ) {
313         NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
314         Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
315         AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
316         if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) {
317             for ( int index = 0; index < relationMemberOf.TargetSet.getLength(); index++ ) {
318                 Reference < XAccessible > rMateAccessible = Reference < XAccessible > ( relationMemberOf.TargetSet[index], UNO_QUERY );
319                 if ( rMateAccessible.is() ) {
320                     Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() );
321                     if ( rMateAccessibleContext.is() ) {
322                         id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ];
323                         [ children addObject: wrapper ];
324                         [ wrapper release ];
325                     }
326                 }
327             }
328         }
329         return children;
330     } else if ( [ self accessibleTable ] != nil ) {
331         return [ AquaA11yTableWrapper childrenAttributeForElement: self ];
332     } else {
333         try {
334             NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
335             Reference< XAccessibleContext > xContext( [ self accessibleContext ] );
336             
337             sal_Int32 cnt = xContext -> getAccessibleChildCount();
338             for ( sal_Int32 i = 0; i < cnt; i++ ) {
339                 Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) );
340                 if( xChild.is() ) {
341                     Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() );
342                     // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here
343                     if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) {
344                         id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ];
345                         [ children addObject: wrapper ];
346                         [ wrapper release ];
347                     }
348                 }
349             }
350             
351             // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons
352             if ( ! mActsAsRadioGroup ) {
353                 NSEnumerator * enumerator = [ children objectEnumerator ];
354                 AquaA11yWrapper * element;
355                 while ( ( element = ( (AquaA11yWrapper *) [ enumerator nextObject ] ) ) ) {
356                     if ( [ element accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) {
357                         if ( [ element isFirstRadioButtonInGroup ] ) {
358                             id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ element accessibleContext ] createIfNotExists: YES asRadioGroup: YES ];
359                             [ children replaceObjectAtIndex: [ children indexOfObjectIdenticalTo: element ] withObject: wrapper ];
360                         }
361                         [ children removeObject: element ];
362                     }
363                 }
364             }
366             [ children autorelease ];
367             return NSAccessibilityUnignoredChildren( children );
368         } catch (const Exception &e) {
369             // TODO: Log
370             return nil;
371         }
372     }
375 -(id)windowAttribute {
376     // go upstairs until reaching the broken connection
377     AquaA11yWrapper * aWrapper = self;
378     while ( [ aWrapper accessibleContext ] -> getAccessibleParent().is() ) {
379         aWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ aWrapper accessibleContext ] -> getAccessibleParent() -> getAccessibleContext() ];
380         [ aWrapper autorelease ];
381     }
382     // get associated NSWindow
383     NSView * theView = [ aWrapper viewElementForParent ];
384     return theView;
387 -(id)topLevelUIElementAttribute {
388     return [ self windowAttribute ];
391 -(id)sizeAttribute {
392     if ( [ self accessibleComponent ] != nil ) {
393         return [ AquaA11yComponentWrapper sizeAttributeForElement: self ];
394     } else {
395         return nil;
396     }
399 -(id)positionAttribute {
400     if ( [ self accessibleComponent ] != nil ) {
401         return [ AquaA11yComponentWrapper positionAttributeForElement: self ];
402     } else {
403         return nil;
404     }
407 -(id)helpAttribute {
408     return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
411 -(id)roleDescriptionAttribute {
412     if ( mActsAsRadioGroup ) {
413         return [ AquaA11yRoleHelper getRoleDescriptionFrom: NSAccessibilityRadioGroupRole with: @"" ];
414         } else if( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) {
415                 // FIXME: VO should read this because of hierarchy, this is just a workaround
416                 // get parent and its children
417                 AquaA11yWrapper * parent = [ self parentAttribute ];
418                 NSArray * children = [ parent childrenAttribute ];
419                 // find index of self
420                 int index = 1;
421                 NSEnumerator * enumerator = [ children objectEnumerator ];
422                 AquaA11yWrapper * child = nil;
423                 while ( ( child = [ enumerator nextObject ] ) ) {
424                         if ( self == child ) {
425                                 break;
426                         }
427                         index++;
428                 }
429                 // build string
430                 NSNumber * nIndex = [ NSNumber numberWithInt: index ];
431                 NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ];
432                 NSMutableString * value = [ [ NSMutableString alloc ] init ];
433                 [ value appendString: @"radio button " ];
434                 [ value appendString: [ nIndex stringValue ] ];
435                 [ value appendString: @" of " ];
436                 [ value appendString: [ nGroupsize stringValue ] ];
437                 // clean up and return string
438                 [ nIndex release ];
439                 [ nGroupsize release ];
440                 [ children release ];
441                 return value;
442     } else {
443         return [ AquaA11yRoleHelper getRoleDescriptionFrom: 
444                 [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ] 
445                 with: [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ] ];
446     }
449 -(id)valueAttribute {
450     if ( [ [ self roleAttribute ] isEqualToString: NSAccessibilityMenuItemRole ] ) {
451         return nil;
452     } else if ( [ self accessibleText ] != nil ) {
453         return [ AquaA11yTextWrapper valueAttributeForElement: self ];
454     } else if ( [ self accessibleValue ] != nil ) {
455         return [ AquaA11yValueWrapper valueAttributeForElement: self ];
456     } else {
457         return nil;
458     }
461 -(id)minValueAttribute {
462     if ( [ self accessibleValue ] != nil ) {
463         return [ AquaA11yValueWrapper minValueAttributeForElement: self ];
464     } else {
465         return nil;
466     }
469 -(id)maxValueAttribute {
470     if ( [ self accessibleValue ] != nil ) {
471         return [ AquaA11yValueWrapper maxValueAttributeForElement: self ];
472     } else {
473         return nil;
474     }
477 -(id)contentsAttribute {
478     return [ self childrenAttribute ];
481 -(id)selectedChildrenAttribute {
482     return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ];
485 -(id)numberOfCharactersAttribute {
486     if ( [ self accessibleText ] != nil ) {
487         return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ];
488     } else {
489         return nil;
490     }
493 -(id)selectedTextAttribute {
494     if ( [ self accessibleText ] != nil ) {
495         return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ];
496     } else {
497         return nil;
498     }
501 -(id)selectedTextRangeAttribute {
502     if ( [ self accessibleText ] != nil ) {
503         return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ];
504     } else {
505         return nil;
506     }
509 -(id)visibleCharacterRangeAttribute {
510     if ( [ self accessibleText ] != nil ) {
511         return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ];
512     } else {
513         return nil;
514     }
517 -(id)tabsAttribute {
518     return self; // TODO ???
521 -(id)sharedTextUIElementsAttribute {
522     if ( [ self accessibleText ] != nil ) {
523         return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ];
524     } else {
525         return nil;
526     }
529 -(id)sharedCharacterRangeAttribute {
530     if ( [ self accessibleText ] != nil ) {
531         return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ];
532     } else {
533         return nil;
534     }
537 -(id)expandedAttribute {
538     return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ];
541 -(id)selectedAttribute {
542     return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ];
545 -(id)stringForRangeAttributeForParameter:(id)range {
546     if ( [ self accessibleText ] != nil ) {
547         return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ];
548     } else {
549         return nil;
550     }
553 -(id)attributedStringForRangeAttributeForParameter:(id)range {
554     if ( [ self accessibleText ] != nil ) {
555         return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ];
556     } else {
557         return nil;
558     }
561 -(id)rangeForIndexAttributeForParameter:(id)index {
562     if ( [ self accessibleText ] != nil ) {
563         return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ];
564     } else {
565         return nil;
566     }
569 -(id)rangeForPositionAttributeForParameter:(id)point {
570     if ( [ self accessibleText ] != nil ) {
571         return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ];
572     } else {
573         return nil;
574     }
577 -(id)boundsForRangeAttributeForParameter:(id)range {
578     if ( [ self accessibleText ] != nil ) {
579         return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ];
580     } else {
581         return nil;
582     }
585 -(id)styleRangeForIndexAttributeForParameter:(id)index {
586     if ( [ self accessibleText ] != nil ) {
587         return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ];
588     } else {
589         return nil;
590     }
593 -(id)rTFForRangeAttributeForParameter:(id)range {
594     if ( [ self accessibleText ] != nil ) {
595         return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ];
596     } else {
597         return nil;
598     }
601 -(id)orientationAttribute {
602     NSString * orientation = nil;
603     Reference < XAccessibleStateSet > stateSet = [ self accessibleContext ] -> getAccessibleStateSet();
604     if ( stateSet -> contains ( AccessibleStateType::HORIZONTAL ) ) {
605         orientation = NSAccessibilityHorizontalOrientationValue;
606     } else if ( stateSet -> contains ( AccessibleStateType::VERTICAL ) ) {
607         orientation = NSAccessibilityVerticalOrientationValue;
608     }
609     return orientation;
612 -(id)titleUIElementAttribute {
613     if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) {
614         NSString * title = [ self titleAttribute ];
615         id titleElement = nil;
616         if ( [ title length ] == 0 ) {
617             AccessibleRelation relationLabeledBy = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABELED_BY );
618             if ( relationLabeledBy.RelationType == AccessibleRelationType::LABELED_BY && relationLabeledBy.TargetSet.hasElements()  ) {
619                 Reference < XAccessible > rxAccessible ( relationLabeledBy.TargetSet[0], UNO_QUERY );
620                 titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ];
621             }
622         }
623         if ( title != nil ) {
624             [ title release ];
625         }
626         return titleElement;
627     } else {
628         return nil;
629     }
632 -(id)servesAsTitleForUIElementsAttribute {
633     if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) {
634         id titleForElement = nil;
635         AccessibleRelation relationLabelFor = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABEL_FOR );
636         if ( relationLabelFor.RelationType == AccessibleRelationType::LABEL_FOR && relationLabelFor.TargetSet.hasElements() ) {
637             Reference < XAccessible > rxAccessible ( relationLabelFor.TargetSet[0], UNO_QUERY );
638             titleForElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ];
639         }
640         return titleForElement;
641     } else {
642         return nil;
643     }
646 -(id)lineForIndexAttributeForParameter:(id)index {
647     if ( [ self accessibleMultiLineText ] != nil ) {
648         return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ];
649     } else {
650         return nil;
651     }
654 -(id)rangeForLineAttributeForParameter:(id)line {
655     if ( [ self accessibleMultiLineText ] != nil ) {
656         return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ];
657     } else {
658         return nil;
659     }
662 #pragma mark -
663 #pragma mark Accessibility Protocol
665 -(id)accessibilityAttributeValue:(NSString *)attribute {
666     // #i90575# guard NSAccessibility protocol against unwanted access
667     if ( isPopupMenuOpen ) {
668         return nil;
669     }
670     id value = nil;
671     // if we are no longer in the wrapper repository, we have been disposed
672     AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ];
673     if ( theWrapper != nil || mIsTableCell ) {
674         try {
675             SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ];
676             if ( [ self respondsToSelector: methodSelector ] ) {
677                 value = [ self performSelector: methodSelector ];
678             }
679         } catch ( const DisposedException & e ) {
680             mIsTableCell = NO; // just to be sure
681             [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
682             return nil;
683         } catch ( const Exception & e ) {
684             // empty
685         }
686     }
687     if ( theWrapper != nil ) {
688         [ theWrapper release ]; // the above called method calls retain on the returned Wrapper
689     }
690     return value;
693 -(MacOSBOOL)accessibilityIsIgnored {
694     // #i90575# guard NSAccessibility protocol against unwanted access
695     if ( isPopupMenuOpen ) {
696         return nil;
697     }
698     MacOSBOOL ignored = NO;
699     sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
700     switch ( nRole ) {
701         case AccessibleRole::PANEL:
702         case AccessibleRole::FRAME:
703         case AccessibleRole::ROOT_PANE:
704         case AccessibleRole::SEPARATOR:
705         case AccessibleRole::FILLER:
706         case AccessibleRole::DIALOG:
707             ignored = YES;
708             break;
709         default: 
710             ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) );
711             break;
712     }
713     return ignored; // TODO: to be completed
716 -(NSArray *)accessibilityAttributeNames {
717     // #i90575# guard NSAccessibility protocol against unwanted access
718     if ( isPopupMenuOpen ) {
719         return nil;
720     }
721     NSString * nativeSubrole = nil;
722     NSString * title = nil;
723     NSMutableArray * attributeNames = nil;
724     try {
725         // Default Attributes
726         attributeNames = [ NSMutableArray arrayWithObjects: 
727             NSAccessibilityRoleAttribute, 
728             NSAccessibilityDescriptionAttribute, 
729             NSAccessibilityParentAttribute, 
730             NSAccessibilityWindowAttribute, 
731             NSAccessibilityHelpAttribute, 
732             NSAccessibilityTopLevelUIElementAttribute, 
733             NSAccessibilityRoleDescriptionAttribute, 
734             nil ];
735         nativeSubrole = (NSString *) [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
736         title = (NSString *) [ self titleAttribute ];
737         Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
738         // Special Attributes depending on attribute values
739         if ( nativeSubrole != nil && ! [ nativeSubrole isEqualToString: @"" ] ) {
740             [ attributeNames addObject: NSAccessibilitySubroleAttribute ];
741         }
742         try
743         {
744         if ( [ self accessibleContext ] -> getAccessibleChildCount() > 0 ) {
745             [ attributeNames addObject: NSAccessibilityChildrenAttribute ];
746         }
747         }
748         catch( DisposedException& ) {}
749         catch( RuntimeException& ) {}
750         
751         if ( title != nil && ! [ title isEqualToString: @"" ] ) {
752             [ attributeNames addObject: NSAccessibilityTitleAttribute ];
753         }
754         if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) {
755             [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ];
756         }
757         if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) {
758             [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ];
759         }
760         // Special Attributes depending on interface
761         if ( [ self accessibleText ] != nil ) {
762             [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ];
763         }
764         if ( [ self accessibleComponent ] != nil ) {
765             [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ];
766         }
767         if ( [ self accessibleSelection ] != nil ) {
768             [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ];
769         }
770         if ( [ self accessibleValue ] != nil ) {
771             [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ];
772         }
773         [ nativeSubrole release ];
774         [ title release ];
775         return attributeNames;
776     } catch ( DisposedException & e ) { // Object is no longer available
777         if ( nativeSubrole != nil ) {
778             [ nativeSubrole release ];
779         }
780         if ( title != nil ) {
781             [ title release ];
782         }
783         if ( attributeNames != nil ) {
784             [ attributeNames release ];
785         }
786         [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
787         return [ [ NSArray alloc ] init ];
788     }
791 -(MacOSBOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
792     MacOSBOOL isSettable = NO;
793     if ( [ self accessibleText ] != nil ) {
794         isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ];
795     }
796     if ( ! isSettable && [ self accessibleComponent ] != nil ) {
797         isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ];
798     }
799     if ( ! isSettable && [ self accessibleSelection ] != nil ) {
800         isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ];
801     }
802     if ( ! isSettable && [ self accessibleValue ] != nil ) {
803         isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ];
804     }
805     return isSettable; // TODO: to be completed
808 -(NSArray *)accessibilityParameterizedAttributeNames {
809     NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ];
810     // Special Attributes depending on interface
811     if ( [ self accessibleText ] != nil ) {
812         [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ];
813     }
814     return attributeNames; // TODO: to be completed
817 -(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
818     SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ];
819     if ( [ self respondsToSelector: methodSelector ] ) {
820         return [ self performSelector: methodSelector withObject: parameter ];
821     }
822     return nil; // TODO: to be completed
825 -(MacOSBOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute {
826     return NO; // TODO
829 -(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
830     SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ];
831     if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) {
832         [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ];
833     }
834     if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) {
835         [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ];
836     }
837     if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) {
838         [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ];
839     }
840     if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) {
841         [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ];
842     }
845 -(id)accessibilityFocusedUIElement {
846     // #i90575# guard NSAccessibility protocol against unwanted access
847     if ( isPopupMenuOpen ) {
848         return nil;
849     }
851     // as this seems to be the first API call on a newly created SalFrameView object,
852     // make sure self gets registered in the repository ..
853     [ self accessibleContext ]; 
855     AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement();
856 //    AquaA11yWrapper * ancestor = focusedUIElement;
857             
858       // Make sure the focused object is a descendant of self
859 //    do  {
860 //       if( self == ancestor )
861              return focusedUIElement;
862         
863 //       ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ];
864 //    }  while( nil != ancestor );
865         
866     return self;
869 // TODO: hard-coded like the role descriptions. is there a better way?
870 -(NSString *)accessibilityActionDescription:(NSString *)action {
871     if ( [ action isEqualToString: NSAccessibilityConfirmAction ] ) {
872         return @"confirm";
873     } else if ( [ action isEqualToString: NSAccessibilityDecrementAction ] ) {
874         return @"decrement";
875     } else if ( [ action isEqualToString: NSAccessibilityDeleteAction ] ) {
876         return @"delete";
877     } else if ( [ action isEqualToString: NSAccessibilityIncrementAction ] ) {
878         return @"increment";
879     } else if ( [ action isEqualToString: NSAccessibilityPickAction ] ) {
880         return @"pick";
881     } else if ( [ action isEqualToString: NSAccessibilityPressAction ] ) {
882         return @"press";
883     } else if ( [ action isEqualToString: NSAccessibilityCancelAction ] ) {
884         return @"cancel";
885     } else if ( [ action isEqualToString: NSAccessibilityRaiseAction ] ) {
886         return @"raise";
887     } else if ( [ action isEqualToString: NSAccessibilityShowMenuAction ] ) {
888         return @"show menu";
889     } else {
890         return [ NSString string ];
891     }
894 -(AquaA11yWrapper *)actionResponder {
895     AquaA11yWrapper * wrapper = nil;
896     // get some information
897     NSString * role = (NSString *) [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
898     id enabledAttr = [ self enabledAttribute ];
899     MacOSBOOL enabled = [ enabledAttr boolValue ];
900     NSView * parent = (NSView *) [ self accessibilityAttributeValue: NSAccessibilityParentAttribute ];
901     AquaA11yWrapper * parentAsWrapper = nil;
902     if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) {
903         parentAsWrapper = (AquaA11yWrapper *) parent;
904     }
905     NSString * parentRole = (NSString *) [ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
906     // if we are a textarea inside a combobox, then the combobox is the action responder
907     if ( enabled 
908       && [ role isEqualToString: NSAccessibilityTextAreaRole ] 
909       && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ] 
910       && parentAsWrapper != nil ) {
911         wrapper = parentAsWrapper;
912     } else if ( enabled && [ self accessibleAction ] != nil ) {
913         wrapper = self ;
914     }
915     [ parentRole release ];
916     [ enabledAttr release ];
917     [ role release ];
918     return wrapper;
921 -(void)accessibilityPerformAction:(NSString *)action {
922     AquaA11yWrapper * actionResponder = [ self actionResponder ];
923     if ( actionResponder != nil ) {
924         [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ];
925     }
928 -(NSArray *)accessibilityActionNames {
929     NSArray * actionNames = nil;
930     AquaA11yWrapper * actionResponder = [ self actionResponder ];
931     if ( actionResponder != nil ) {
932         actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ];
933     } else {
934         actionNames = [ [ NSArray alloc ] init ];
935     }
936     return actionNames;
939 #pragma mark -
940 #pragma mark Hit Test
942 -(MacOSBOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point {
943     MacOSBOOL hit = NO;
944     NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
945     NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ];
946     NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ];
947     if ( position != nil && size != nil ) {
948         float minX = [ position pointValue ].x;
949         float minY = [ position pointValue ].y;
950         float maxX = minX + [ size sizeValue ].width;
951         float maxY = minY + [ size sizeValue ].height;
952         if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) {
953             hit = YES;
954         }
955     }
956     [ pool release ];
957     return hit;
960 Reference < XAccessibleContext > hitTestRunner ( Point point, Reference < XAccessibleContext > rxAccessibleContext ) {
961     Reference < XAccessibleContext > hitChild;
962     Reference < XAccessibleContext > emptyReference;
963     try {
964         Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY );
965         if ( rxAccessibleComponent.is() ) {
966             Point location = rxAccessibleComponent -> getLocationOnScreen();
967             Point hitPoint ( point.X - location.X , point.Y - location.Y); 
968             Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint );
969             if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
970                 if ( rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() > 0 ) {
971                     hitChild = hitTestRunner ( point, rxAccessible -> getAccessibleContext() );
972                     if ( ! hitChild.is() ) {
973                         hitChild = rxAccessible -> getAccessibleContext();
974                     }
975                 } else {
976                     hitChild = rxAccessible -> getAccessibleContext();
977                 }
978             }
979         } 
980         if ( !hitChild.is() && rxAccessibleContext -> getAccessibleChildCount() > 0 ) { // special treatment for e.g. comboboxes
981             for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) {
982                 Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i );
983                 if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) {
984                     Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() );
985                     if ( myHitChild.is() ) {
986                         hitChild = myHitChild;
987                         break;
988                     }
989                 }
990             }
991         }
992     } catch ( RuntimeException ) {
993         return emptyReference;
994     }
995     return hitChild;
998 -(id)accessibilityHitTest:(NSPoint)point {
999     static id wrapper = nil;
1000     if ( nil != wrapper ) {
1001         [ wrapper release ];
1002         wrapper = nil;
1003     }
1004     Reference < XAccessibleContext > hitChild;
1005     NSRect screenRect = [ [ NSScreen mainScreen ] frame ];
1006     Point hitPoint ( static_cast<long>(point.x) , static_cast<long>(screenRect.size.height - point.y) ); 
1007     // check child windows first
1008     NSWindow * window = (NSWindow *) [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ];
1009     NSArray * childWindows = [ window childWindows ];
1010     if ( [ childWindows count ] > 0 ) {
1011         NSWindow * element = nil;
1012         NSEnumerator * enumerator = [ childWindows objectEnumerator ];
1013         while ( ( element = [ enumerator nextObject ] ) && hitChild == nil ) {
1014             if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) {
1015                 // we have a child window that is hit
1016                 Reference < XAccessibleRelationSet > relationSet = [ ( ( SalFrameWindow * ) element ) accessibleContext ] -> getAccessibleRelationSet();
1017                 if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) {
1018                     // we have a valid relation to the parent element
1019                     AccessibleRelation relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF );
1020                     for ( int i = 0; i < relation.TargetSet.getLength() && !hitChild.is(); i++ ) {
1021                         Reference < XAccessible > rxAccessible ( relation.TargetSet [ i ], UNO_QUERY );
1022                         if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
1023                             // hit test for children of parent
1024                             hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() );
1025                         }
1026                     }
1027                 }
1028             }
1029         }
1030     }
1031     // nothing hit yet, so check ourself
1032     if ( ! hitChild.is() ) {
1033         if ( mpReferenceWrapper == nil ) {
1034             [ self setDefaults: [ self accessibleContext ] ];
1035         }
1036         hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext );
1037     }
1038     if ( hitChild.is() ) {
1039         wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ];
1040     }
1041     if ( wrapper != nil ) {
1042         [ wrapper retain ]; // TODO: retain only when transient ?
1043     }
1044     return wrapper;
1047 #pragma mark -
1048 #pragma mark Access Methods
1050 -(XAccessibleAction *)accessibleAction {
1051     return mpReferenceWrapper -> rAccessibleAction.get();
1054 -(XAccessibleContext *)accessibleContext {
1055     return mpReferenceWrapper -> rAccessibleContext.get();
1058 -(XAccessibleComponent *)accessibleComponent {
1059     return mpReferenceWrapper -> rAccessibleComponent.get();
1062 -(XAccessibleExtendedComponent *)accessibleExtendedComponent {
1063     return mpReferenceWrapper -> rAccessibleExtendedComponent.get();
1066 -(XAccessibleSelection *)accessibleSelection {
1067     return mpReferenceWrapper -> rAccessibleSelection.get();
1070 -(XAccessibleTable *)accessibleTable {
1071     return mpReferenceWrapper -> rAccessibleTable.get();
1074 -(XAccessibleText *)accessibleText {
1075     return mpReferenceWrapper -> rAccessibleText.get();
1078 -(XAccessibleEditableText *)accessibleEditableText {
1079     return mpReferenceWrapper -> rAccessibleEditableText.get();
1082 -(XAccessibleValue *)accessibleValue {
1083     return mpReferenceWrapper -> rAccessibleValue.get();
1086 -(XAccessibleTextAttributes *)accessibleTextAttributes {
1087     return mpReferenceWrapper -> rAccessibleTextAttributes.get();
1090 -(XAccessibleMultiLineText *)accessibleMultiLineText {
1091     return mpReferenceWrapper -> rAccessibleMultiLineText.get();
1094 -(NSView *)viewElementForParent {
1095     return self;
1098 // These four are for AXTextAreas only. They are needed, because bold and italic
1099 // attributes have to be bound to a font on the Mac. Our UNO-API instead handles
1100 // and reports them independently. When they occur we bundle them to a font with
1101 // this information here to create a according NSFont.
1102 -(void)setDefaultFontname:(NSString *)fontname {
1103     if ( mpDefaultFontname != nil ) {
1104         [ mpDefaultFontname release ];
1105     }
1106     mpDefaultFontname = fontname;
1109 -(NSString *)defaultFontname {
1110     return mpDefaultFontname;
1113 -(void)setDefaultFontsize:(float)fontsize {
1114     mDefaultFontsize = fontsize;
1117 -(float)defaultFontsize {
1118     return mDefaultFontsize;
1121 -(void)setActsAsRadioGroup:(MacOSBOOL)actsAsRadioGroup {
1122     mActsAsRadioGroup = actsAsRadioGroup;
1125 -(MacOSBOOL)actsAsRadioGroup {
1126     return mActsAsRadioGroup;
1129 +(void)setPopupMenuOpen:(MacOSBOOL)popupMenuOpen {
1130     isPopupMenuOpen = popupMenuOpen;
1133 @end