xref: /AOO41X/main/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.mm (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir/*************************************************************************
2*cdf0e10cSrcweir *
3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir *
5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir *
7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir *
9*cdf0e10cSrcweir * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir *
11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir *
15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir *
21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir *
26*cdf0e10cSrcweir ************************************************************************/
27*cdf0e10cSrcweir
28*cdf0e10cSrcweir// MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir#include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir
31*cdf0e10cSrcweir#include "aqua/salinst.h"
32*cdf0e10cSrcweir
33*cdf0e10cSrcweir#include "aqua11ytextattributeswrapper.h"
34*cdf0e10cSrcweir
35*cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleTextType.hpp>
36*cdf0e10cSrcweir#include <com/sun/star/awt/FontUnderline.hpp>
37*cdf0e10cSrcweir#include <com/sun/star/awt/FontWeight.hpp>
38*cdf0e10cSrcweir#include <com/sun/star/awt/FontStrikeout.hpp>
39*cdf0e10cSrcweir
40*cdf0e10cSrcweirusing namespace ::com::sun::star::accessibility;
41*cdf0e10cSrcweirusing namespace ::com::sun::star::awt;
42*cdf0e10cSrcweirusing namespace ::com::sun::star::beans;
43*cdf0e10cSrcweirusing namespace ::com::sun::star::lang;
44*cdf0e10cSrcweirusing namespace ::com::sun::star::uno;
45*cdf0e10cSrcweirusing namespace ::rtl;
46*cdf0e10cSrcweir
47*cdf0e10cSrcweir@implementation AquaA11yTextAttributesWrapper : NSObject
48*cdf0e10cSrcweir
49*cdf0e10cSrcweir+(int)convertUnderlineStyle:(PropertyValue)property {
50*cdf0e10cSrcweir    int underlineStyle = NSNoUnderlineStyle;
51*cdf0e10cSrcweir    sal_Int16 value = 0;
52*cdf0e10cSrcweir    property.Value >>= value;
53*cdf0e10cSrcweir    if ( value != FontUnderline::NONE
54*cdf0e10cSrcweir      && value != FontUnderline::DONTKNOW) {
55*cdf0e10cSrcweir        underlineStyle = NSSingleUnderlineStyle;
56*cdf0e10cSrcweir    }
57*cdf0e10cSrcweir    return underlineStyle;
58*cdf0e10cSrcweir}
59*cdf0e10cSrcweir
60*cdf0e10cSrcweir+(int)convertBoldStyle:(PropertyValue)property {
61*cdf0e10cSrcweir    int boldStyle = 0;
62*cdf0e10cSrcweir    float value = 0;
63*cdf0e10cSrcweir    property.Value >>= value;
64*cdf0e10cSrcweir    if ( value == FontWeight::SEMIBOLD
65*cdf0e10cSrcweir      || value == FontWeight::BOLD
66*cdf0e10cSrcweir      || value == FontWeight::ULTRABOLD
67*cdf0e10cSrcweir      || value == FontWeight::BLACK ) {
68*cdf0e10cSrcweir        boldStyle = NSBoldFontMask;
69*cdf0e10cSrcweir    }
70*cdf0e10cSrcweir    return boldStyle;
71*cdf0e10cSrcweir}
72*cdf0e10cSrcweir
73*cdf0e10cSrcweir+(int)convertItalicStyle:(PropertyValue)property {
74*cdf0e10cSrcweir    int italicStyle = 0;
75*cdf0e10cSrcweir    sal_Int16 value = property.Value.get<FontSlant>();
76*cdf0e10cSrcweir    if ( value == FontSlant_ITALIC ) {
77*cdf0e10cSrcweir        italicStyle = NSItalicFontMask;
78*cdf0e10cSrcweir    }
79*cdf0e10cSrcweir    return italicStyle;
80*cdf0e10cSrcweir}
81*cdf0e10cSrcweir
82*cdf0e10cSrcweir+(BOOL)isStrikethrough:(PropertyValue)property {
83*cdf0e10cSrcweir    BOOL strikethrough = NO;
84*cdf0e10cSrcweir    sal_Int16 value = 0;
85*cdf0e10cSrcweir    property.Value >>= value;
86*cdf0e10cSrcweir    if ( value != FontStrikeout::NONE
87*cdf0e10cSrcweir      && value != FontStrikeout::DONTKNOW ) {
88*cdf0e10cSrcweir        strikethrough = YES;
89*cdf0e10cSrcweir    }
90*cdf0e10cSrcweir    return strikethrough;
91*cdf0e10cSrcweir}
92*cdf0e10cSrcweir
93*cdf0e10cSrcweir+(BOOL)convertBoolean:(PropertyValue)property {
94*cdf0e10cSrcweir    BOOL myBoolean = NO;
95*cdf0e10cSrcweir    bool value = sal_False;
96*cdf0e10cSrcweir    property.Value >>= value;
97*cdf0e10cSrcweir    if ( value ) {
98*cdf0e10cSrcweir        myBoolean = YES;
99*cdf0e10cSrcweir    }
100*cdf0e10cSrcweir    return myBoolean;
101*cdf0e10cSrcweir}
102*cdf0e10cSrcweir
103*cdf0e10cSrcweir+(NSNumber *)convertShort:(PropertyValue)property {
104*cdf0e10cSrcweir    sal_Int16 value = 0;
105*cdf0e10cSrcweir    property.Value >>= value;
106*cdf0e10cSrcweir    return [ NSNumber numberWithShort: value ];
107*cdf0e10cSrcweir}
108*cdf0e10cSrcweir
109*cdf0e10cSrcweir+(void)addColor:(sal_Int32)salColor forAttribute:(NSString *)attribute andRange:(NSRange)range toString:(NSMutableAttributedString *)string {
110*cdf0e10cSrcweir    if ( salColor != -1 ) {
111*cdf0e10cSrcweir        float elements[] = { salColor & 0x00ff0000, salColor & 0x0000ff00, salColor & 0x000000ff };
112*cdf0e10cSrcweir        CGColorRef color = CGColorCreate ( CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ), elements );
113*cdf0e10cSrcweir        [ string addAttribute: attribute value: (id) color range: range ];
114*cdf0e10cSrcweir        CGColorRelease ( color );
115*cdf0e10cSrcweir    }
116*cdf0e10cSrcweir}
117*cdf0e10cSrcweir
118*cdf0e10cSrcweir+(void)addFont:(NSFont *)font toString:(NSMutableAttributedString *)string forRange:(NSRange)range {
119*cdf0e10cSrcweir    if ( font != nil ) {
120*cdf0e10cSrcweir        NSDictionary * fontDictionary = [ NSDictionary dictionaryWithObjectsAndKeys:
121*cdf0e10cSrcweir            [ font fontName ], NSAccessibilityFontNameKey,
122*cdf0e10cSrcweir            [ font familyName ], NSAccessibilityFontFamilyKey,
123*cdf0e10cSrcweir            [ font displayName ], NSAccessibilityVisibleNameKey,
124*cdf0e10cSrcweir            [ NSNumber numberWithFloat: [ font pointSize ] ], NSAccessibilityFontSizeKey,
125*cdf0e10cSrcweir            nil
126*cdf0e10cSrcweir        ];
127*cdf0e10cSrcweir        [ string addAttribute: NSAccessibilityFontTextAttribute
128*cdf0e10cSrcweir                value: fontDictionary
129*cdf0e10cSrcweir                range: range
130*cdf0e10cSrcweir        ];
131*cdf0e10cSrcweir    }
132*cdf0e10cSrcweir}
133*cdf0e10cSrcweir
134*cdf0e10cSrcweir+(void)applyAttributesFrom:(Sequence < PropertyValue >)attributes toString:(NSMutableAttributedString *)string forRange:(NSRange)range storeDefaultsTo:(AquaA11yWrapper *)wrapperStore getDefaultsFrom:(AquaA11yWrapper *)wrapper {
135*cdf0e10cSrcweir    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
136*cdf0e10cSrcweir    // constants
137*cdf0e10cSrcweir    static const OUString attrUnderline = OUString::createFromAscii("CharUnderline");
138*cdf0e10cSrcweir    static const OUString attrBold = OUString::createFromAscii("CharWeight");
139*cdf0e10cSrcweir    static const OUString attrFontname = OUString::createFromAscii("CharFontName");
140*cdf0e10cSrcweir    static const OUString attrItalic = OUString::createFromAscii("CharPosture");
141*cdf0e10cSrcweir    static const OUString attrHeight = OUString::createFromAscii("CharHeight");
142*cdf0e10cSrcweir    static const OUString attrStrikethrough = OUString::createFromAscii("CharStrikeout");
143*cdf0e10cSrcweir    static const OUString attrShadow = OUString::createFromAscii("CharShadowed");
144*cdf0e10cSrcweir    static const OUString attrUnderlineColor = OUString::createFromAscii("CharUnderlineColor");
145*cdf0e10cSrcweir    static const OUString attrUnderlineHasColor = OUString::createFromAscii("CharUnderlineHasColor");
146*cdf0e10cSrcweir    static const OUString attrForegroundColor = OUString::createFromAscii("CharColor");
147*cdf0e10cSrcweir    static const OUString attrBackgroundColor = OUString::createFromAscii("CharBackColor");
148*cdf0e10cSrcweir    static const OUString attrSuperscript = OUString::createFromAscii("CharEscapement");
149*cdf0e10cSrcweir    // vars
150*cdf0e10cSrcweir    OUString fontname;
151*cdf0e10cSrcweir    int fonttraits = 0;
152*cdf0e10cSrcweir    float fontsize = 0.0;
153*cdf0e10cSrcweir    sal_Int32 underlineColor = 0;
154*cdf0e10cSrcweir    BOOL underlineHasColor = NO;
155*cdf0e10cSrcweir    // add attributes to string
156*cdf0e10cSrcweir    for ( int attrIndex = 0; attrIndex < attributes.getLength(); attrIndex++ ) {
157*cdf0e10cSrcweir        PropertyValue property = attributes [ attrIndex ];
158*cdf0e10cSrcweir        // TODO: NSAccessibilityMisspelledTextAttribute, NSAccessibilityAttachmentTextAttribute, NSAccessibilityLinkTextAttribute
159*cdf0e10cSrcweir        // NSAccessibilityStrikethroughColorTextAttribute is unsupported by UNP-API
160*cdf0e10cSrcweir        if ( property.Value.hasValue() ) {
161*cdf0e10cSrcweir            if ( property.Name.equals ( attrUnderline ) ) {
162*cdf0e10cSrcweir                int style = [ AquaA11yTextAttributesWrapper convertUnderlineStyle: property ];
163*cdf0e10cSrcweir                if ( style != NSNoUnderlineStyle ) {
164*cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityUnderlineTextAttribute value: [ NSNumber numberWithInt: style ] range: range ];
165*cdf0e10cSrcweir                }
166*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrFontname ) ) {
167*cdf0e10cSrcweir                property.Value >>= fontname;
168*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrBold ) ) {
169*cdf0e10cSrcweir                fonttraits |= [ AquaA11yTextAttributesWrapper convertBoldStyle: property ];
170*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrItalic ) ) {
171*cdf0e10cSrcweir                fonttraits |= [ AquaA11yTextAttributesWrapper convertItalicStyle: property ];
172*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrHeight ) ) {
173*cdf0e10cSrcweir                property.Value >>= fontsize;
174*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrStrikethrough ) ) {
175*cdf0e10cSrcweir                if ( [ AquaA11yTextAttributesWrapper isStrikethrough: property ] ) {
176*cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityStrikethroughTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ];
177*cdf0e10cSrcweir                }
178*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrShadow ) ) {
179*cdf0e10cSrcweir                if ( [ AquaA11yTextAttributesWrapper convertBoolean: property ] ) {
180*cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityShadowTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ];
181*cdf0e10cSrcweir                }
182*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrUnderlineColor ) ) {
183*cdf0e10cSrcweir                property.Value >>= underlineColor;
184*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrUnderlineHasColor ) ) {
185*cdf0e10cSrcweir                underlineHasColor = [ AquaA11yTextAttributesWrapper convertBoolean: property ];
186*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrForegroundColor ) ) {
187*cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityForegroundColorTextAttribute andRange: range toString: string ];
188*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrBackgroundColor ) ) {
189*cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityBackgroundColorTextAttribute andRange: range toString: string ];
190*cdf0e10cSrcweir            } else if ( property.Name.equals ( attrSuperscript ) ) {
191*cdf0e10cSrcweir                // values < zero mean subscript
192*cdf0e10cSrcweir                // values > zero mean superscript
193*cdf0e10cSrcweir                // this is true for both NSAccessibility-API and UNO-API
194*cdf0e10cSrcweir                NSNumber * number = [ AquaA11yTextAttributesWrapper convertShort: property ];
195*cdf0e10cSrcweir                if ( [ number shortValue ] != 0 ) {
196*cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilitySuperscriptTextAttribute value: number range: range ];
197*cdf0e10cSrcweir                }
198*cdf0e10cSrcweir            }
199*cdf0e10cSrcweir        }
200*cdf0e10cSrcweir    }
201*cdf0e10cSrcweir    // add underline information
202*cdf0e10cSrcweir    if ( underlineHasColor ) {
203*cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addColor: underlineColor forAttribute: NSAccessibilityUnderlineColorTextAttribute andRange: range toString: string ];
204*cdf0e10cSrcweir    }
205*cdf0e10cSrcweir    // add font information
206*cdf0e10cSrcweir    if ( wrapperStore != nil ) { // default
207*cdf0e10cSrcweir        [ wrapperStore setDefaultFontname: CreateNSString ( fontname ) ];
208*cdf0e10cSrcweir        [ wrapperStore setDefaultFontsize: fontsize ];
209*cdf0e10cSrcweir        NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: CreateNSString ( fontname ) traits: fonttraits weight: 0 size: fontsize ];
210*cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ];
211*cdf0e10cSrcweir    } else if ( wrapper != nil && fonttraits != 0 ) { // attribute run and bold and/or italic was found
212*cdf0e10cSrcweir        NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: [ wrapper defaultFontname ] traits: fonttraits weight: 0 size: [ wrapper defaultFontsize ] ];
213*cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ];
214*cdf0e10cSrcweir    }
215*cdf0e10cSrcweir    [ pool release ];
216*cdf0e10cSrcweir}
217*cdf0e10cSrcweir
218*cdf0e10cSrcweir+(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange {
219*cdf0e10cSrcweir    static const Sequence < OUString > emptySequence;
220*cdf0e10cSrcweir    // vars
221*cdf0e10cSrcweir    NSMutableAttributedString * string = nil;
222*cdf0e10cSrcweir    int loc = [ origRange rangeValue ].location;
223*cdf0e10cSrcweir    int len = [ origRange rangeValue ].length;
224*cdf0e10cSrcweir    int endIndex = loc + len;
225*cdf0e10cSrcweir    int currentIndex = loc;
226*cdf0e10cSrcweir    try {
227*cdf0e10cSrcweir        NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817
228*cdf0e10cSrcweir        string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ];
229*cdf0e10cSrcweir        if ( [ wrapper accessibleTextAttributes ] != nil && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817
230*cdf0e10cSrcweir            [ string beginEditing ];
231*cdf0e10cSrcweir            // add default attributes for whole string
232*cdf0e10cSrcweir            Sequence < PropertyValue > defaultAttributes = [ wrapper accessibleTextAttributes ] -> getDefaultAttributes ( emptySequence );
233*cdf0e10cSrcweir            [ AquaA11yTextAttributesWrapper applyAttributesFrom: defaultAttributes toString: string forRange: [ origRange rangeValue ] storeDefaultsTo: wrapper getDefaultsFrom: nil ];
234*cdf0e10cSrcweir            // add attributes for attribute run(s)
235*cdf0e10cSrcweir            while ( currentIndex < endIndex ) {
236*cdf0e10cSrcweir                TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( currentIndex, AccessibleTextType::ATTRIBUTE_RUN );
237*cdf0e10cSrcweir                int endOfRange = endIndex > textSegment.SegmentEnd ? textSegment.SegmentEnd : endIndex;
238*cdf0e10cSrcweir                NSRange rangeForAttributeRun = NSMakeRange ( currentIndex, endOfRange - currentIndex );
239*cdf0e10cSrcweir                // add run attributes
240*cdf0e10cSrcweir                Sequence < PropertyValue > attributes = [ wrapper accessibleTextAttributes ] -> getRunAttributes ( currentIndex, emptySequence );
241*cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper applyAttributesFrom: attributes toString: string forRange: rangeForAttributeRun storeDefaultsTo: nil getDefaultsFrom: wrapper ];
242*cdf0e10cSrcweir                currentIndex = textSegment.SegmentEnd;
243*cdf0e10cSrcweir            }
244*cdf0e10cSrcweir            [ string endEditing ];
245*cdf0e10cSrcweir        }
246*cdf0e10cSrcweir    } catch ( IllegalArgumentException & e ) {
247*cdf0e10cSrcweir        // empty
248*cdf0e10cSrcweir    } catch ( IndexOutOfBoundsException & e ) {
249*cdf0e10cSrcweir        // empty
250*cdf0e10cSrcweir    } catch ( RuntimeException& ) {
251*cdf0e10cSrcweir        // at least don't crash
252*cdf0e10cSrcweir    }
253*cdf0e10cSrcweir    return string;
254*cdf0e10cSrcweir}
255*cdf0e10cSrcweir
256*cdf0e10cSrcweir@end
257