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#include "aqua/saldata.hxx"
29
30#include "aqua/aqua11ywrapper.h"
31#include "aqua/aqua11ylistener.hxx"
32#include "aqua/aqua11yfactory.h"
33#include "aqua/aqua11yfocustracker.hxx"
34
35#include "aqua11yfocuslistener.hxx"
36#include "aqua11yactionwrapper.h"
37#include "aqua11ycomponentwrapper.h"
38#include "aqua11yselectionwrapper.h"
39#include "aqua11ytablewrapper.h"
40#include "aqua11ytextwrapper.h"
41#include "aqua11yvaluewrapper.h"
42#include "aqua11yrolehelper.h"
43
44#include <com/sun/star/accessibility/AccessibleRole.hpp>
45#include <com/sun/star/accessibility/AccessibleStateType.hpp>
46#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
47#include <com/sun/star/awt/Size.hpp>
48#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
49#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
50#include <com/sun/star/lang/DisposedException.hpp>
51
52using namespace ::com::sun::star::accessibility;
53using namespace ::com::sun::star::awt;
54using namespace ::com::sun::star::lang;
55using namespace ::com::sun::star::uno;
56
57@interface SalFrameWindow : NSWindow
58{
59}
60-(Reference<XAccessibleContext>)accessibleContext;
61@end
62
63static BOOL isPopupMenuOpen = NO;
64
65@implementation AquaA11yWrapper : NSView
66
67#pragma mark -
68#pragma mark Init and dealloc
69
70-(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext {
71    self = [ super init ];
72    if ( self != nil ) {
73        [ self setDefaults: rxAccessibleContext ];
74    }
75    return self;
76}
77
78-(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext {
79    mDefaultFontsize = 0.0;
80    mpDefaultFontname = nil;
81    mpReferenceWrapper = new ReferenceWrapper;
82    mActsAsRadioGroup = NO;
83    mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext;
84    mIsTableCell = NO;
85    // Querying all supported interfaces
86    try {
87        // XAccessibleComponent
88        mpReferenceWrapper -> rAccessibleComponent = Reference < XAccessibleComponent > ( rxAccessibleContext, UNO_QUERY );
89        // XAccessibleExtendedComponent
90        mpReferenceWrapper -> rAccessibleExtendedComponent = Reference < XAccessibleExtendedComponent > ( rxAccessibleContext, UNO_QUERY );
91        // XAccessibleSelection
92        mpReferenceWrapper -> rAccessibleSelection = Reference< XAccessibleSelection > ( rxAccessibleContext, UNO_QUERY );
93        // XAccessibleTable
94        mpReferenceWrapper -> rAccessibleTable = Reference < XAccessibleTable > ( rxAccessibleContext, UNO_QUERY );
95        // XAccessibleText
96        mpReferenceWrapper -> rAccessibleText = Reference < XAccessibleText > ( rxAccessibleContext, UNO_QUERY );
97        // XAccessibleEditableText
98        mpReferenceWrapper -> rAccessibleEditableText = Reference < XAccessibleEditableText > ( rxAccessibleContext, UNO_QUERY );
99        // XAccessibleValue
100        mpReferenceWrapper -> rAccessibleValue = Reference < XAccessibleValue > ( rxAccessibleContext, UNO_QUERY );
101        // XAccessibleAction
102        mpReferenceWrapper -> rAccessibleAction = Reference < XAccessibleAction > ( rxAccessibleContext, UNO_QUERY );
103        // XAccessibleTextAttributes
104        mpReferenceWrapper -> rAccessibleTextAttributes = Reference < XAccessibleTextAttributes > ( rxAccessibleContext, UNO_QUERY );
105        // XAccessibleMultiLineText
106        mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY );
107        // XAccessibleEventBroadcaster
108        #if 0
109        /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children.
110           That means we need to cache this, else e.g. tree list boxes are not accessible (moreover
111           it crashes by notifying dead objects - which would seemt o be another bug)
112
113           FIXME:
114           Unfortunately this can increase memory consumption drastically until the non transient parent
115           is destroyed an finally all the transients are released.
116        */
117        if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) )
118        #endif
119        {
120            Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY);
121            if( xBroadcaster.is() ) {
122                /*
123                 * We intentionally do not hold a reference to the event listener in the wrapper object,
124                 * but let the listener control the life cycle of the wrapper instead ..
125                 */
126                xBroadcaster->addEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) );
127            }
128        }
129        // TABLE_CELL
130        if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) {
131            mIsTableCell = YES;
132        }
133    } catch ( const Exception ) {
134    }
135}
136
137-(void)dealloc {
138    if ( mpReferenceWrapper != nil ) {
139        delete mpReferenceWrapper;
140    }
141    if ( mpDefaultFontname != nil ) {
142        [ mpDefaultFontname release ];
143    }
144    [ super dealloc ];
145}
146
147#pragma mark -
148#pragma mark Utility Section
149
150// generates selectors for attribute name AXAttributeNameHere
151// (getter without parameter) attributeNameHereAttribute
152// (getter with parameter)    attributeNameHereAttributeForParameter:
153// (setter)                   setAttributeNameHereAttributeForElement:to:
154-(SEL)selectorForAttribute:(NSString *)attribute asGetter:(BOOL)asGetter withGetterParameter:(BOOL)withGetterParameter {
155    SEL selector = nil;
156    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
157    @try {
158        // step 1: create method name from attribute name
159        NSMutableString * methodName = [ NSMutableString string ];
160        if ( ! asGetter ) {
161            [ methodName appendString: @"set" ];
162        }
163        NSRange aRange = { 2, 1 };
164        NSString * firstChar = [ attribute substringWithRange: aRange ]; // drop leading "AX" and get first char
165        if ( asGetter ) {
166            [ methodName appendString: [ firstChar lowercaseString ] ];
167        } else {
168            [ methodName appendString: firstChar ];
169        }
170        [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name
171        // append rest of method name
172        [ methodName appendString: @"Attribute" ];
173        if ( ! asGetter ) {
174            [ methodName appendString: @"ForElement:to:" ];
175        } else if ( asGetter && withGetterParameter ) {
176            [ methodName appendString: @"ForParameter:" ];
177        }
178        // step 2: create selector
179        selector = NSSelectorFromString ( methodName );
180    } @catch ( id exception ) {
181        selector = nil;
182    }
183    [ pool release ];
184    return selector;
185}
186
187-(Reference < XAccessible >)getFirstRadioButtonInGroup {
188    Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
189    if( rxAccessibleRelationSet.is() )
190    {
191        AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
192        if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() )
193            return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY );
194    }
195    return Reference < XAccessible > ();
196}
197
198-(BOOL)isFirstRadioButtonInGroup {
199    Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ];
200    if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) {
201        return YES;
202    }
203    return NO;
204}
205
206#pragma mark -
207#pragma mark Attribute Value Getters
208// ( called via Reflection by accessibilityAttributeValue )
209
210/*
211    Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their
212    RelationSet. In NSAccessibility the relationship is axpressed through the hierarchy. A AXRadioGroup contains two or more AXRadioButton
213    objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all
214    attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes.
215    So in this five methods there is a special treatment for radio buttons and groups.
216*/
217
218-(id)roleAttribute {
219    if ( mActsAsRadioGroup ) {
220        return NSAccessibilityRadioGroupRole;
221    }
222    else {
223        return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ];
224    }
225}
226
227-(id)subroleAttribute {
228    if ( mActsAsRadioGroup ) {
229        return @"";
230    } else {
231        NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
232        if ( ! [ subRole isEqualToString: @"" ] ) {
233            return subRole;
234        } else {
235            [ subRole release ];
236            return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ];
237        }
238    }
239}
240
241-(id)titleAttribute {
242    return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() );
243}
244
245-(id)descriptionAttribute {
246    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
247        return [ self titleAttribute ];
248    } else if ( [ self accessibleExtendedComponent ] != nil ) {
249        return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ];
250    } else {
251        return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
252    }
253}
254
255-(id)enabledAttribute {
256    if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
257        return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ];
258    } else {
259        return nil;
260    }
261}
262
263-(id)focusedAttribute {
264    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
265        id isFocused = nil;
266        Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent();
267        if ( rxParent.is() ) {
268            Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext();
269            if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) {
270                isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
271            }
272        }
273        return isFocused;
274    } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
275        return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
276    } else {
277        return nil;
278    }
279}
280
281-(id)parentAttribute {
282    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) {
283        Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ];
284        if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
285            Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext();
286            id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ];
287            [ parent_wrapper autorelease ];
288            return NSAccessibilityUnignoredAncestor( parent_wrapper );
289        }
290        return nil;
291    }
292    try {
293        Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() );
294        if ( xParent.is() ) {
295            Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() );
296            if ( xContext.is() ) {
297                id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ];
298                [ parent_wrapper autorelease ];
299                return NSAccessibilityUnignoredAncestor( parent_wrapper );
300            }
301        }
302    } catch (const Exception&) {
303    }
304
305    OSL_ASSERT( 0 );
306    return nil;
307}
308
309-(id)childrenAttribute {
310    if ( mActsAsRadioGroup ) {
311        NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
312        Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
313        AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
314        if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) {
315            for ( int index = 0; index < relationMemberOf.TargetSet.getLength(); index++ ) {
316                Reference < XAccessible > rMateAccessible = Reference < XAccessible > ( relationMemberOf.TargetSet[index], UNO_QUERY );
317                if ( rMateAccessible.is() ) {
318                    Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() );
319                    if ( rMateAccessibleContext.is() ) {
320                        id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ];
321                        [ children addObject: wrapper ];
322                        [ wrapper release ];
323                    }
324                }
325            }
326        }
327        return children;
328    } else if ( [ self accessibleTable ] != nil )
329    {
330        AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? (AquaA11yTableWrapper*)self : nil;
331        return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ];
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            }
365
366            [ children autorelease ];
367            return NSAccessibilityUnignoredChildren( children );
368        } catch (const Exception &e) {
369            // TODO: Log
370            return nil;
371        }
372    }
373}
374
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    NSWindow* theWindow = [ aWrapper windowForParent ];
384    return theWindow;
385}
386
387-(id)topLevelUIElementAttribute {
388    return [ self windowAttribute ];
389}
390
391-(id)sizeAttribute {
392    if ( [ self accessibleComponent ] != nil ) {
393        return [ AquaA11yComponentWrapper sizeAttributeForElement: self ];
394    } else {
395        return nil;
396    }
397}
398
399-(id)positionAttribute {
400    if ( [ self accessibleComponent ] != nil ) {
401        return [ AquaA11yComponentWrapper positionAttributeForElement: self ];
402    } else {
403        return nil;
404    }
405}
406
407-(id)helpAttribute {
408    return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
409}
410
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    }
447}
448
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    }
459}
460
461-(id)minValueAttribute {
462    if ( [ self accessibleValue ] != nil ) {
463        return [ AquaA11yValueWrapper minValueAttributeForElement: self ];
464    } else {
465        return nil;
466    }
467}
468
469-(id)maxValueAttribute {
470    if ( [ self accessibleValue ] != nil ) {
471        return [ AquaA11yValueWrapper maxValueAttributeForElement: self ];
472    } else {
473        return nil;
474    }
475}
476
477-(id)contentsAttribute {
478    return [ self childrenAttribute ];
479}
480
481-(id)selectedChildrenAttribute {
482    return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ];
483}
484
485-(id)numberOfCharactersAttribute {
486    if ( [ self accessibleText ] != nil ) {
487        return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ];
488    } else {
489        return nil;
490    }
491}
492
493-(id)selectedTextAttribute {
494    if ( [ self accessibleText ] != nil ) {
495        return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ];
496    } else {
497        return nil;
498    }
499}
500
501-(id)selectedTextRangeAttribute {
502    if ( [ self accessibleText ] != nil ) {
503        return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ];
504    } else {
505        return nil;
506    }
507}
508
509-(id)visibleCharacterRangeAttribute {
510    if ( [ self accessibleText ] != nil ) {
511        return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ];
512    } else {
513        return nil;
514    }
515}
516
517-(id)tabsAttribute {
518    return self; // TODO ???
519}
520
521-(id)sharedTextUIElementsAttribute {
522    if ( [ self accessibleText ] != nil ) {
523        return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ];
524    } else {
525        return nil;
526    }
527}
528
529-(id)sharedCharacterRangeAttribute {
530    if ( [ self accessibleText ] != nil ) {
531        return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ];
532    } else {
533        return nil;
534    }
535}
536
537-(id)expandedAttribute {
538    return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ];
539}
540
541-(id)selectedAttribute {
542    return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ];
543}
544
545-(id)stringForRangeAttributeForParameter:(id)range {
546    if ( [ self accessibleText ] != nil ) {
547        return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ];
548    } else {
549        return nil;
550    }
551}
552
553-(id)attributedStringForRangeAttributeForParameter:(id)range {
554    if ( [ self accessibleText ] != nil ) {
555        return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ];
556    } else {
557        return nil;
558    }
559}
560
561-(id)rangeForIndexAttributeForParameter:(id)index {
562    if ( [ self accessibleText ] != nil ) {
563        return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ];
564    } else {
565        return nil;
566    }
567}
568
569-(id)rangeForPositionAttributeForParameter:(id)point {
570    if ( [ self accessibleText ] != nil ) {
571        return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ];
572    } else {
573        return nil;
574    }
575}
576
577-(id)boundsForRangeAttributeForParameter:(id)range {
578    if ( [ self accessibleText ] != nil ) {
579        return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ];
580    } else {
581        return nil;
582    }
583}
584
585-(id)styleRangeForIndexAttributeForParameter:(id)index {
586    if ( [ self accessibleText ] != nil ) {
587        return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ];
588    } else {
589        return nil;
590    }
591}
592
593-(id)rTFForRangeAttributeForParameter:(id)range {
594    if ( [ self accessibleText ] != nil ) {
595        return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ];
596    } else {
597        return nil;
598    }
599}
600
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;
610}
611
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    }
630}
631
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    }
644}
645
646-(id)lineForIndexAttributeForParameter:(id)index {
647    if ( [ self accessibleMultiLineText ] != nil ) {
648        return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ];
649    } else {
650        return nil;
651    }
652}
653
654-(id)rangeForLineAttributeForParameter:(id)line {
655    if ( [ self accessibleMultiLineText ] != nil ) {
656        return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ];
657    } else {
658        return nil;
659    }
660}
661
662#pragma mark -
663#pragma mark Accessibility Protocol
664
665-(id)accessibilityAttributeValue:(NSString *)attribute {
666    // #i90575# guard NSAccessibility protocol against unwanted access
667    if ( isPopupMenuOpen ) {
668        return nil;
669    }
670
671    id value = nil;
672    // if we are no longer in the wrapper repository, we have been disposed
673    AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ];
674    if ( theWrapper != nil || mIsTableCell ) {
675        try {
676            SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ];
677            if ( [ self respondsToSelector: methodSelector ] ) {
678                value = [ self performSelector: methodSelector ];
679            }
680        } catch ( const DisposedException & e ) {
681            mIsTableCell = NO; // just to be sure
682            [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
683            return nil;
684        } catch ( const Exception & e ) {
685            // empty
686        }
687    }
688    if ( theWrapper != nil ) {
689        [ theWrapper release ]; // the above called method calls retain on the returned Wrapper
690    }
691    return value;
692}
693
694-(BOOL)accessibilityIsIgnored {
695    // #i90575# guard NSAccessibility protocol against unwanted access
696    if ( isPopupMenuOpen ) {
697        return FALSE;
698    }
699    BOOL ignored = NO;
700    sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
701    switch ( nRole ) {
702        case AccessibleRole::PANEL:
703        case AccessibleRole::FRAME:
704        case AccessibleRole::ROOT_PANE:
705        case AccessibleRole::SEPARATOR:
706        case AccessibleRole::FILLER:
707        case AccessibleRole::DIALOG:
708            ignored = YES;
709            break;
710        default:
711            ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) );
712            break;
713    }
714    return ignored; // TODO: to be completed
715}
716
717-(NSArray *)accessibilityAttributeNames {
718    // #i90575# guard NSAccessibility protocol against unwanted access
719    if ( isPopupMenuOpen ) {
720        return nil;
721    }
722    NSString * nativeSubrole = nil;
723    NSString * title = nil;
724    NSMutableArray * attributeNames = nil;
725    sal_Int32 nAccessibleChildren = 0;
726    try {
727        // Default Attributes
728        attributeNames = [ NSMutableArray arrayWithObjects:
729            NSAccessibilityRoleAttribute,
730            NSAccessibilityDescriptionAttribute,
731            NSAccessibilityParentAttribute,
732            NSAccessibilityWindowAttribute,
733            NSAccessibilityHelpAttribute,
734            NSAccessibilityTopLevelUIElementAttribute,
735            NSAccessibilityRoleDescriptionAttribute,
736            nil ];
737        nativeSubrole = (NSString *) [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
738        title = (NSString *) [ self titleAttribute ];
739        Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
740        // Special Attributes depending on attribute values
741        if ( nativeSubrole != nil && ! [ nativeSubrole isEqualToString: @"" ] ) {
742            [ attributeNames addObject: NSAccessibilitySubroleAttribute ];
743        }
744        try
745        {
746            nAccessibleChildren = [ self accessibleContext ] -> getAccessibleChildCount();
747            if (  nAccessibleChildren > 0 ) {
748                [ attributeNames addObject: NSAccessibilityChildrenAttribute ];
749        }
750        }
751        catch( DisposedException& ) {}
752        catch( RuntimeException& ) {}
753
754        if ( title != nil && ! [ title isEqualToString: @"" ] ) {
755            [ attributeNames addObject: NSAccessibilityTitleAttribute ];
756        }
757        if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) {
758            [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ];
759        }
760        if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) {
761            [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ];
762        }
763        // Special Attributes depending on interface
764        if( [self accessibleContext ] -> getAccessibleRole() == AccessibleRole::TABLE )
765            [AquaA11yTableWrapper addAttributeNamesTo: attributeNames object: self];
766
767        if ( [ self accessibleText ] != nil ) {
768            [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ];
769        }
770        if ( [ self accessibleComponent ] != nil ) {
771            [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ];
772        }
773        if ( [ self accessibleSelection ] != nil ) {
774            [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ];
775        }
776        if ( [ self accessibleValue ] != nil ) {
777            [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ];
778        }
779        [ nativeSubrole release ];
780        [ title release ];
781        return attributeNames;
782    } catch ( DisposedException & e ) { // Object is no longer available
783        if ( nativeSubrole != nil ) {
784            [ nativeSubrole release ];
785        }
786        if ( title != nil ) {
787            [ title release ];
788        }
789        if ( attributeNames != nil ) {
790            [ attributeNames release ];
791        }
792        [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
793        return [ [ NSArray alloc ] init ];
794    }
795}
796
797-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
798    BOOL isSettable = NO;
799    if ( [ self accessibleText ] != nil ) {
800        isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ];
801    }
802    if ( ! isSettable && [ self accessibleComponent ] != nil ) {
803        isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ];
804    }
805    if ( ! isSettable && [ self accessibleSelection ] != nil ) {
806        isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ];
807    }
808    if ( ! isSettable && [ self accessibleValue ] != nil ) {
809        isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ];
810    }
811    return isSettable; // TODO: to be completed
812}
813
814-(NSArray *)accessibilityParameterizedAttributeNames {
815    NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ];
816    // Special Attributes depending on interface
817    if ( [ self accessibleText ] != nil ) {
818        [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ];
819    }
820    return attributeNames; // TODO: to be completed
821}
822
823-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
824    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ];
825    if ( [ self respondsToSelector: methodSelector ] ) {
826        return [ self performSelector: methodSelector withObject: parameter ];
827    }
828    return nil; // TODO: to be completed
829}
830
831-(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute
832{
833    (void)value;
834    (void)attribute;
835    return NO; // TODO
836}
837
838-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
839    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ];
840    if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) {
841        [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ];
842    }
843    if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) {
844        [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ];
845    }
846    if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) {
847        [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ];
848    }
849    if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) {
850        [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ];
851    }
852}
853
854-(id)accessibilityFocusedUIElement {
855    // #i90575# guard NSAccessibility protocol against unwanted access
856    if ( isPopupMenuOpen ) {
857        return nil;
858    }
859
860    // as this seems to be the first API call on a newly created SalFrameView object,
861    // make sure self gets registered in the repository ..
862    [ self accessibleContext ];
863
864    AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement();
865//    AquaA11yWrapper * ancestor = focusedUIElement;
866
867      // Make sure the focused object is a descendant of self
868//    do  {
869//       if( self == ancestor )
870             return focusedUIElement;
871
872//       ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ];
873//    }  while( nil != ancestor );
874
875    return self;
876}
877
878// TODO: hard-coded like the role descriptions. is there a better way?
879-(NSString *)accessibilityActionDescription:(NSString *)action {
880    if ( [ action isEqualToString: NSAccessibilityConfirmAction ] ) {
881        return @"confirm";
882    } else if ( [ action isEqualToString: NSAccessibilityDecrementAction ] ) {
883        return @"decrement";
884    } else if ( [ action isEqualToString: NSAccessibilityDeleteAction ] ) {
885        return @"delete";
886    } else if ( [ action isEqualToString: NSAccessibilityIncrementAction ] ) {
887        return @"increment";
888    } else if ( [ action isEqualToString: NSAccessibilityPickAction ] ) {
889        return @"pick";
890    } else if ( [ action isEqualToString: NSAccessibilityPressAction ] ) {
891        return @"press";
892    } else if ( [ action isEqualToString: NSAccessibilityCancelAction ] ) {
893        return @"cancel";
894    } else if ( [ action isEqualToString: NSAccessibilityRaiseAction ] ) {
895        return @"raise";
896    } else if ( [ action isEqualToString: NSAccessibilityShowMenuAction ] ) {
897        return @"show menu";
898    } else {
899        return [ NSString string ];
900    }
901}
902
903-(AquaA11yWrapper *)actionResponder {
904    AquaA11yWrapper * wrapper = nil;
905    // get some information
906    NSString * role = (NSString *) [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
907    id enabledAttr = [ self enabledAttribute ];
908    BOOL enabled = [ enabledAttr boolValue ];
909    NSView * parent = (NSView *) [ self accessibilityAttributeValue: NSAccessibilityParentAttribute ];
910    AquaA11yWrapper * parentAsWrapper = nil;
911    if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) {
912        parentAsWrapper = (AquaA11yWrapper *) parent;
913    }
914    NSString * parentRole = (NSString *) [ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
915    // if we are a textarea inside a combobox, then the combobox is the action responder
916    if ( enabled
917      && [ role isEqualToString: NSAccessibilityTextAreaRole ]
918      && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ]
919      && parentAsWrapper != nil ) {
920        wrapper = parentAsWrapper;
921    } else if ( enabled && [ self accessibleAction ] != nil ) {
922        wrapper = self ;
923    }
924    [ parentRole release ];
925    [ enabledAttr release ];
926    [ role release ];
927    return wrapper;
928}
929
930-(void)accessibilityPerformAction:(NSString *)action {
931    AquaA11yWrapper * actionResponder = [ self actionResponder ];
932    if ( actionResponder != nil ) {
933        [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ];
934    }
935}
936
937-(NSArray *)accessibilityActionNames {
938    NSArray * actionNames = nil;
939    AquaA11yWrapper * actionResponder = [ self actionResponder ];
940    if ( actionResponder != nil ) {
941        actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ];
942    } else {
943        actionNames = [ [ NSArray alloc ] init ];
944    }
945    return actionNames;
946}
947
948#pragma mark -
949#pragma mark Hit Test
950
951-(BOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point {
952    BOOL hit = NO;
953    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
954    NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ];
955    NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ];
956    if ( position != nil && size != nil ) {
957        float minX = [ position pointValue ].x;
958        float minY = [ position pointValue ].y;
959        float maxX = minX + [ size sizeValue ].width;
960        float maxY = minY + [ size sizeValue ].height;
961        if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) {
962            hit = YES;
963        }
964    }
965    [ pool release ];
966    return hit;
967}
968
969Reference < XAccessibleContext > hitTestRunner ( com::sun::star::awt::Point point,
970                                                 Reference < XAccessibleContext > rxAccessibleContext ) {
971    Reference < XAccessibleContext > hitChild;
972    Reference < XAccessibleContext > emptyReference;
973    try {
974        Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY );
975        if ( rxAccessibleComponent.is() ) {
976            com::sun::star::awt::Point location = rxAccessibleComponent -> getLocationOnScreen();
977            com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y);
978            Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint );
979            if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
980                if ( rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() > 0 ) {
981                    hitChild = hitTestRunner ( point, rxAccessible -> getAccessibleContext() );
982                    if ( ! hitChild.is() ) {
983                        hitChild = rxAccessible -> getAccessibleContext();
984                    }
985                } else {
986                    hitChild = rxAccessible -> getAccessibleContext();
987                }
988            }
989        }
990        if ( !hitChild.is() && rxAccessibleContext -> getAccessibleChildCount() > 0 ) { // special treatment for e.g. comboboxes
991            for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) {
992                Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i );
993                if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) {
994                    Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() );
995                    if ( myHitChild.is() ) {
996                        hitChild = myHitChild;
997                        break;
998                    }
999                }
1000            }
1001        }
1002    } catch ( RuntimeException ) {
1003        return emptyReference;
1004    }
1005    return hitChild;
1006}
1007
1008-(id)accessibilityHitTest:(NSPoint)point {
1009    static id wrapper = nil;
1010    if ( nil != wrapper ) {
1011        [ wrapper release ];
1012        wrapper = nil;
1013    }
1014    Reference < XAccessibleContext > hitChild;
1015    NSRect screenRect = [ [ NSScreen mainScreen ] frame ];
1016    com::sun::star::awt::Point hitPoint ( static_cast<long>(point.x) , static_cast<long>(screenRect.size.height - point.y) );
1017    // check child windows first
1018    NSWindow * window = (NSWindow *) [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ];
1019    NSArray * childWindows = [ window childWindows ];
1020    if ( [ childWindows count ] > 0 ) {
1021        NSWindow * element = nil;
1022        NSEnumerator * enumerator = [ childWindows objectEnumerator ];
1023        while ( ( element = [ enumerator nextObject ] ) && hitChild == nil ) {
1024            if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) {
1025                // we have a child window that is hit
1026                Reference < XAccessibleRelationSet > relationSet = [ ( ( SalFrameWindow * ) element ) accessibleContext ] -> getAccessibleRelationSet();
1027                if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) {
1028                    // we have a valid relation to the parent element
1029                    AccessibleRelation relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF );
1030                    for ( int i = 0; i < relation.TargetSet.getLength() && !hitChild.is(); i++ ) {
1031                        Reference < XAccessible > rxAccessible ( relation.TargetSet [ i ], UNO_QUERY );
1032                        if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
1033                            // hit test for children of parent
1034                            hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() );
1035                        }
1036                    }
1037                }
1038            }
1039        }
1040    }
1041    // nothing hit yet, so check ourself
1042    if ( ! hitChild.is() ) {
1043        if ( mpReferenceWrapper == nil ) {
1044            [ self setDefaults: [ self accessibleContext ] ];
1045        }
1046        hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext );
1047    }
1048    if ( hitChild.is() ) {
1049        wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ];
1050    }
1051    if ( wrapper != nil ) {
1052        [ wrapper retain ]; // TODO: retain only when transient ?
1053    }
1054    return wrapper;
1055}
1056
1057#pragma mark -
1058#pragma mark Access Methods
1059
1060-(XAccessibleAction *)accessibleAction {
1061    return mpReferenceWrapper -> rAccessibleAction.get();
1062}
1063
1064-(XAccessibleContext *)accessibleContext {
1065    return mpReferenceWrapper -> rAccessibleContext.get();
1066}
1067
1068-(XAccessibleComponent *)accessibleComponent {
1069    return mpReferenceWrapper -> rAccessibleComponent.get();
1070}
1071
1072-(XAccessibleExtendedComponent *)accessibleExtendedComponent {
1073    return mpReferenceWrapper -> rAccessibleExtendedComponent.get();
1074}
1075
1076-(XAccessibleSelection *)accessibleSelection {
1077    return mpReferenceWrapper -> rAccessibleSelection.get();
1078}
1079
1080-(XAccessibleTable *)accessibleTable {
1081    return mpReferenceWrapper -> rAccessibleTable.get();
1082}
1083
1084-(XAccessibleText *)accessibleText {
1085    return mpReferenceWrapper -> rAccessibleText.get();
1086}
1087
1088-(XAccessibleEditableText *)accessibleEditableText {
1089    return mpReferenceWrapper -> rAccessibleEditableText.get();
1090}
1091
1092-(XAccessibleValue *)accessibleValue {
1093    return mpReferenceWrapper -> rAccessibleValue.get();
1094}
1095
1096-(XAccessibleTextAttributes *)accessibleTextAttributes {
1097    return mpReferenceWrapper -> rAccessibleTextAttributes.get();
1098}
1099
1100-(XAccessibleMultiLineText *)accessibleMultiLineText {
1101    return mpReferenceWrapper -> rAccessibleMultiLineText.get();
1102}
1103
1104-(NSWindow*)windowForParent {
1105    return [self window];
1106}
1107
1108// These four are for AXTextAreas only. They are needed, because bold and italic
1109// attributes have to be bound to a font on the Mac. Our UNO-API instead handles
1110// and reports them independently. When they occur we bundle them to a font with
1111// this information here to create a according NSFont.
1112-(void)setDefaultFontname:(NSString *)fontname {
1113    if ( mpDefaultFontname != nil ) {
1114        [ mpDefaultFontname release ];
1115    }
1116    mpDefaultFontname = fontname;
1117}
1118
1119-(NSString *)defaultFontname {
1120    return mpDefaultFontname;
1121}
1122
1123-(void)setDefaultFontsize:(float)fontsize {
1124    mDefaultFontsize = fontsize;
1125}
1126
1127-(float)defaultFontsize {
1128    return mDefaultFontsize;
1129}
1130
1131-(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup {
1132    mActsAsRadioGroup = actsAsRadioGroup;
1133}
1134
1135-(BOOL)actsAsRadioGroup {
1136    return mActsAsRadioGroup;
1137}
1138
1139+(void)setPopupMenuOpen:(BOOL)popupMenuOpen {
1140    isPopupMenuOpen = popupMenuOpen;
1141}
1142
1143@end
1144