1010
1111#![ allow( non_upper_case_globals) ]
1212
13- use accesskit:: { Action , ActionData , ActionRequest , Orientation , Role , TextSelection , Toggled } ;
13+ use accesskit:: {
14+ Action , ActionData , ActionRequest , Orientation , Role , TextAlign , TextSelection , Toggled ,
15+ } ;
1416use accesskit_consumer:: { FilterResult , Node , NodeId , Tree } ;
1517use objc2:: {
1618 declare_class, msg_send_id,
@@ -21,8 +23,9 @@ use objc2::{
2123} ;
2224use objc2_app_kit:: * ;
2325use objc2_foundation:: {
24- ns_string, NSArray , NSCopying , NSInteger , NSNumber , NSObject , NSObjectProtocol , NSPoint ,
25- NSRange , NSRect , NSString , NSURL ,
26+ ns_string, NSArray , NSAttributedString , NSCopying , NSInteger , NSMutableAttributedString ,
27+ NSMutableDictionary , NSNumber , NSObject , NSObjectProtocol , NSPoint , NSRange , NSRect , NSString ,
28+ NSURL ,
2629} ;
2730use std:: rc:: { Rc , Weak } ;
2831
@@ -823,6 +826,112 @@ declare_class!(
823826 . flatten( )
824827 }
825828
829+ #[ method_id( accessibilityAttributedStringForRange: ) ]
830+ fn attributed_string_for_range( & self , range: NSRange ) -> Option <Id <NSAttributedString >> {
831+ self . resolve( |node| {
832+ if node. supports_text_ranges( ) {
833+ if let Some ( range) = from_ns_range( node, range) {
834+ let mut result = NSMutableAttributedString :: new( ) ;
835+ unsafe { result. beginEditing( ) } ;
836+ range. traverse_text:: <_, ( ) >( |node, text| {
837+ let ns_text = NSString :: from_str( text) ;
838+ let mut attrs = NSMutableDictionary :: new( ) ;
839+ if let Some ( color) = node. background_color( ) {
840+ attrs. insert_id(
841+ unsafe { NSAccessibilityBackgroundColorTextAttribute } ,
842+ to_color_attribute( color)
843+ ) ;
844+ }
845+ if let Some ( color) = node. foreground_color( ) {
846+ attrs. insert_id(
847+ unsafe { NSAccessibilityForegroundColorTextAttribute } ,
848+ to_color_attribute( color)
849+ ) ;
850+ }
851+ let mut font_attrs = NSMutableDictionary :: <NSAccessibilityFontAttributeKey , AnyObject >:: new( ) ;
852+ if let Some ( family) = node. font_family( ) {
853+ font_attrs. insert_id(
854+ unsafe { NSAccessibilityFontFamilyKey } ,
855+ Id :: into_super( Id :: into_super( NSString :: from_str( family) ) )
856+ ) ;
857+ }
858+ if let Some ( size) = node. font_size( ) {
859+ font_attrs. insert_id(
860+ unsafe { NSAccessibilityFontSizeKey } ,
861+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_f32( size) ) ) )
862+ ) ;
863+ }
864+ if let Some ( weight) = node. font_weight( ) {
865+ if weight >= 700.0 {
866+ font_attrs. insert_id(
867+ ns_string!( "AXFontBold" ) ,
868+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_bool( true ) ) ) )
869+ ) ;
870+ }
871+ }
872+ if node. is_italic( ) {
873+ font_attrs. insert_id(
874+ ns_string!( "AXFontItalic" ) ,
875+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_bool( true ) ) ) )
876+ ) ;
877+ }
878+ if !font_attrs. is_empty( ) {
879+ attrs. insert_id(
880+ unsafe { NSAccessibilityFontTextAttribute } ,
881+ Id :: into_super( Id :: into_super( Id :: into_super( font_attrs) ) )
882+ ) ;
883+ }
884+ if let Some ( deco) = node. underline( ) {
885+ attrs. insert_id(
886+ unsafe { NSAccessibilityUnderlineTextAttribute } ,
887+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_bool( true ) ) ) )
888+ ) ;
889+ attrs. insert_id(
890+ unsafe { NSAccessibilityUnderlineColorTextAttribute } ,
891+ to_color_attribute( deco. color)
892+ ) ;
893+ }
894+ if let Some ( deco) = node. strikethrough( ) {
895+ attrs. insert_id(
896+ unsafe { NSAccessibilityStrikethroughTextAttribute } ,
897+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_bool( true ) ) ) )
898+ ) ;
899+ attrs. insert_id(
900+ unsafe { NSAccessibilityStrikethroughColorTextAttribute } ,
901+ to_color_attribute( deco. color)
902+ ) ;
903+ }
904+ if let Some ( language) = node. language( ) {
905+ attrs. insert_id(
906+ unsafe { NSAccessibilityLanguageTextAttribute } ,
907+ Id :: into_super( Id :: into_super( NSString :: from_str( language) ) )
908+ ) ;
909+ }
910+ if let Some ( align) = node. text_align( ) {
911+ let ns_align = match align {
912+ TextAlign :: Left => NSTextAlignment :: Left ,
913+ TextAlign :: Center => NSTextAlignment :: Center ,
914+ TextAlign :: Right => NSTextAlignment :: Right ,
915+ TextAlign :: Justify => NSTextAlignment :: Justified ,
916+ } ;
917+ attrs. insert_id(
918+ unsafe { NSAccessibilityTextAlignmentAttribute } ,
919+ Id :: into_super( Id :: into_super( Id :: into_super( NSNumber :: new_isize( ns_align. 0 ) ) ) )
920+ ) ;
921+ }
922+ let part = unsafe { NSAttributedString :: new_with_attributes( & ns_text, & attrs) } ;
923+ unsafe { result. appendAttributedString( & part) } ;
924+ None
925+ } ) ;
926+ unsafe { result. endEditing( ) } ;
927+ return Some ( Id :: into_super( result) ) ;
928+ }
929+ }
930+ None
931+ } )
932+ . flatten( )
933+ }
934+
826935 #[ method( accessibilityFrameForRange: ) ]
827936 fn frame_for_range( & self , range: NSRange ) -> NSRect {
828937 self . resolve_with_context( |node, _, context| {
@@ -874,6 +983,26 @@ declare_class!(
874983 . unwrap_or_else( || NSRange :: new( 0 , 0 ) )
875984 }
876985
986+ #[ method( accessibilityStyleRangeForIndex: ) ]
987+ fn style_range_for_index( & self , index: NSInteger ) -> NSRange {
988+ self . resolve( |node| {
989+ if node. supports_text_ranges( ) && index >= 0 {
990+ if let Some ( pos) = node. text_position_from_global_utf16_index( index as _) {
991+ let start = if pos. is_format_start( ) {
992+ pos
993+ } else {
994+ pos. backward_to_format_start( )
995+ } ;
996+ let mut range = start. to_degenerate_range( ) ;
997+ range. set_end( pos. forward_to_format_end( ) ) ;
998+ return to_ns_range( & range) ;
999+ }
1000+ }
1001+ NSRange :: new( 0 , 0 )
1002+ } )
1003+ . unwrap_or_else( || NSRange :: new( 0 , 0 ) )
1004+ }
1005+
8771006 #[ method( setAccessibilitySelectedTextRange: ) ]
8781007 fn set_selected_text_range( & self , range: NSRange ) {
8791008 self . resolve_with_context( |node, tree, context| {
@@ -1097,9 +1226,11 @@ declare_class!(
10971226 || selector == sel!( accessibilityRangeForLine: )
10981227 || selector == sel!( accessibilityRangeForPosition: )
10991228 || selector == sel!( accessibilityStringForRange: )
1229+ || selector == sel!( accessibilityAttributedStringForRange: )
11001230 || selector == sel!( accessibilityFrameForRange: )
11011231 || selector == sel!( accessibilityLineForIndex: )
11021232 || selector == sel!( accessibilityRangeForIndex: )
1233+ || selector == sel!( accessibilityStyleRangeForIndex: )
11031234 || selector == sel!( setAccessibilitySelectedTextRange: )
11041235 {
11051236 return node. supports_text_ranges( ) ;
0 commit comments