33
33
// ParagraphTextView is an auxiliary view we set as contentView so the drawing
34
34
// can happen on top of the layers manipulated by RCTViewComponentView (the parent view)
35
35
@interface RCTParagraphTextView : RCTUIView // [macOS]
36
+ #else // [macOS
37
+ // On macOS, we also defer drawing to an NSTextView,
38
+ // in order to get more native behaviors like text selection.
39
+ @interface RCTParagraphTextView : NSTextView // [macOS]
40
+ #endif // macOS]
36
41
37
42
@property (nonatomic ) ParagraphShadowNode::ConcreteState::Shared state;
38
43
@property (nonatomic ) ParagraphAttributes paragraphAttributes;
39
44
@property (nonatomic ) LayoutMetrics layoutMetrics;
40
45
46
+ #if TARGET_OS_OSX // [macOS]
47
+ // / UIKit compatibility shim that simply calls `[self setNeedsDisplay:YES]`
48
+ - (void )setNeedsDisplay ;
49
+ #endif
50
+
41
51
@end
42
- #else // [macOS
43
- #if TARGET_OS_OSX // [macOS
44
- // On macOS, we defer drawing to an NSTextView rather than a plan NSView, in order
45
- // to get more native behaviors like text selection. We make sure this NSTextView
46
- // does not take focus.
47
- @interface RCTParagraphComponentUnfocusableTextView : NSTextView
48
- @end
49
- #endif // macOS]
50
52
51
53
#if !TARGET_OS_OSX // [macOS]
52
54
@interface RCTParagraphComponentView () <UIEditMenuInteractionDelegate>
@@ -62,10 +64,8 @@ @implementation RCTParagraphComponentView {
62
64
RCTParagraphComponentAccessibilityProvider *_accessibilityProvider;
63
65
#if !TARGET_OS_OSX // [macOS]
64
66
UILongPressGestureRecognizer *_longPressGestureRecognizer;
65
- RCTParagraphTextView *_textView;
66
- #else // [macOS
67
- RCTParagraphComponentUnfocusableTextView *_textView;
68
67
#endif // macOS]
68
+ RCTParagraphTextView *_textView;
69
69
}
70
70
71
71
- (instancetype )initWithFrame : (CGRect )frame
@@ -77,15 +77,14 @@ - (instancetype)initWithFrame:(CGRect)frame
77
77
self.opaque = NO ;
78
78
_textView = [RCTParagraphTextView new ];
79
79
_textView.backgroundColor = RCTUIColor.clearColor ; // [macOS]
80
- self.contentView = _textView;
81
80
#else // [macOS
82
81
// Make the RCTParagraphComponentView accessible and available in the a11y hierarchy.
83
82
self.accessibilityElement = YES ;
84
83
self.accessibilityRole = NSAccessibilityStaticTextRole ;
85
84
// Fix blurry text on non-retina displays.
86
85
self.canDrawSubviewsIntoLayer = YES ;
87
86
// The NSTextView is responsible for drawing text and managing selection.
88
- _textView = [[RCTParagraphComponentUnfocusableTextView alloc ] initWithFrame: self .bounds];
87
+ _textView = [[RCTParagraphTextView alloc ] initWithFrame: self .bounds];
89
88
// The RCTParagraphComponentUnfocusableTextView is only used for rendering and should not appear in the a11y hierarchy.
90
89
_textView.accessibilityElement = NO ;
91
90
_textView.usesFontPanel = NO ;
@@ -98,6 +97,7 @@ - (instancetype)initWithFrame:(CGRect)frame
98
97
self.contentView = _textView;
99
98
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
100
99
#endif // macOS]
100
+ self.contentView = _textView;
101
101
}
102
102
103
103
return self;
@@ -164,12 +164,9 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
164
164
- (void )updateState : (const State::Shared &)state oldState : (const State::Shared &)oldState
165
165
{
166
166
_state = std::static_pointer_cast<const ParagraphShadowNode::ConcreteState>(state);
167
- #if !TARGET_OS_OSX // [macOS]
168
167
_textView.state = _state;
169
168
[_textView setNeedsDisplay ];
170
169
[self setNeedsLayout ];
171
- [self _updateTextView ];
172
- #endif // macOS]
173
170
}
174
171
175
172
- (void )updateLayoutMetrics : (const LayoutMetrics &)layoutMetrics
@@ -178,53 +175,10 @@ - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
178
175
// Using stored `_layoutMetrics` as `oldLayoutMetrics` here to avoid
179
176
// re-applying individual sub-values which weren't changed.
180
177
[super updateLayoutMetrics: layoutMetrics oldLayoutMetrics: _layoutMetrics];
181
- #if !TARGET_OS_OSX // [macOS]
182
178
_textView.layoutMetrics = _layoutMetrics;
183
179
[_textView setNeedsDisplay ];
184
180
[self setNeedsLayout ];
185
- #else // [macOS
186
- [self _updateTextView ];
187
- #endif // macOS]
188
- }
189
-
190
- #if TARGET_OS_OSX // [macOS
191
- - (void )_updateTextView
192
- {
193
- if (!_state) {
194
- return ;
195
- }
196
-
197
- auto textLayoutManager = _state->getData ().paragraphLayoutManager .getTextLayoutManager ();
198
-
199
- if (!textLayoutManager) {
200
- return ;
201
- }
202
-
203
- RCTTextLayoutManager *nativeTextLayoutManager =
204
- (RCTTextLayoutManager *)unwrapManagedObject (textLayoutManager->getNativeTextLayoutManager ());
205
-
206
- CGRect frame = RCTCGRectFromRect (_layoutMetrics.getContentFrame ());
207
-
208
- NSTextStorage *textStorage = [nativeTextLayoutManager getTextStorageForAttributedString: _state->getData ().attributedString paragraphAttributes: _paragraphAttributes frame: frame];
209
-
210
- NSLayoutManager *layoutManager = textStorage.layoutManagers .firstObject ;
211
- NSTextContainer *textContainer = layoutManager.textContainers .firstObject ;
212
-
213
- [_textView replaceTextContainer: textContainer];
214
-
215
- NSArray <NSLayoutManager *> *managers = [[textStorage layoutManagers ] copy ];
216
- for (NSLayoutManager *manager in managers) {
217
- [textStorage removeLayoutManager: manager];
218
- }
219
-
220
- _textView.minSize = frame.size ;
221
- _textView.maxSize = frame.size ;
222
- _textView.frame = frame;
223
- _textView.textStorage .attributedString = textStorage;
224
-
225
- [self setNeedsDisplay ];
226
181
}
227
- #endif // macOS]
228
182
229
183
- (void )prepareForRecycle
230
184
{
@@ -427,11 +381,13 @@ - (void)copy:(id)sender
427
381
return RCTParagraphComponentView.class ;
428
382
}
429
383
430
- #if !TARGET_OS_OSX // [macOS]
431
384
@implementation RCTParagraphTextView {
385
+ #if !TARGET_OS_OSX // [macOS]
432
386
CAShapeLayer *_highlightLayer;
387
+ #endif // macOS]
433
388
}
434
389
390
+
435
391
- (void )drawRect : (CGRect )rect
436
392
{
437
393
if (!_state) {
@@ -449,6 +405,7 @@ - (void)drawRect:(CGRect)rect
449
405
450
406
CGRect frame = RCTCGRectFromRect (_layoutMetrics.getContentFrame ());
451
407
408
+ #if !TARGET_OS_OSX // [macOS]
452
409
[nativeTextLayoutManager drawAttributedString: _state->getData ().attributedString
453
410
paragraphAttributes: _paragraphAttributes
454
411
frame: frame
@@ -466,12 +423,33 @@ - (void)drawRect:(CGRect)rect
466
423
self->_highlightLayer = nil ;
467
424
}
468
425
}];
426
+ #else // [macOS
427
+ NSTextStorage *textStorage = [nativeTextLayoutManager getTextStorageForAttributedString: _state->getData ().attributedString paragraphAttributes: _paragraphAttributes size: frame.size];
428
+
429
+ NSLayoutManager *layoutManager = textStorage.layoutManagers .firstObject ;
430
+ NSTextContainer *textContainer = layoutManager.textContainers .firstObject ;
431
+
432
+ [self replaceTextContainer: textContainer];
433
+
434
+ NSArray <NSLayoutManager *> *managers = [[textStorage layoutManagers ] copy ];
435
+ for (NSLayoutManager *manager in managers) {
436
+ [textStorage removeLayoutManager: manager];
437
+ }
438
+
439
+ self.minSize = frame.size ;
440
+ self.maxSize = frame.size ;
441
+ self.frame = frame;
442
+ [[self textStorage ] setAttributedString: textStorage];
443
+
444
+ [super drawRect: rect];
445
+ #endif
469
446
}
470
447
471
- @end
472
- #else // [macOS
473
448
#if TARGET_OS_OSX // [macOS
474
- @implementation RCTParagraphComponentUnfocusableTextView
449
+ - (void )setNeedsDisplay
450
+ {
451
+ [self setNeedsDisplay: YES ];
452
+ }
475
453
476
454
- (BOOL )canBecomeKeyView
477
455
{
@@ -487,6 +465,6 @@ - (BOOL)resignFirstResponder
487
465
488
466
return [super resignFirstResponder ];
489
467
}
468
+ #endif // macOS]
490
469
491
470
@end
492
- #endif // macOS]
0 commit comments