-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathEnrichedTextInputViewShadowNode.mm
More file actions
86 lines (72 loc) · 3.35 KB
/
Copy pathEnrichedTextInputViewShadowNode.mm
File metadata and controls
86 lines (72 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#import "EnrichedTextInputViewShadowNode.h"
#import <EnrichedTextInputView.h>
#import <react/utils/ManagedObjectWrapper.h>
#import <yoga/Yoga.h>
#import <React/RCTShadowView+Layout.h>
#import "CoreText/CoreText.h"
namespace facebook::react {
extern const char EnrichedTextInputViewComponentName[] = "EnrichedTextInputView";
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
const ShadowNodeFragment& fragment,
const ShadowNodeFamily::Shared& family,
ShadowNodeTraits traits
): ConcreteViewShadowNode(fragment, family, traits) {
localForceHeightRecalculationCounter_ = 0;
}
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
const ShadowNode& sourceShadowNode,
const ShadowNodeFragment& fragment
): ConcreteViewShadowNode(sourceShadowNode, fragment) {
dirtyLayoutIfNeeded();
}
void EnrichedTextInputViewShadowNode::dirtyLayoutIfNeeded() {
const auto state = this->getStateData();
const int receivedCounter = state.getForceHeightRecalculationCounter();
if(receivedCounter > localForceHeightRecalculationCounter_) {
localForceHeightRecalculationCounter_ = receivedCounter;
YGNodeMarkDirty(&yogaNode_);
}
}
Size EnrichedTextInputViewShadowNode::measureContent(const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const {
const auto state = this->getStateData();
const auto componentRef = state.getComponentViewRef();
RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(componentRef);
if(weakWrapper != nullptr) {
id componentObject = weakWrapper.object;
EnrichedTextInputView *typedComponentObject = (EnrichedTextInputView *) componentObject;
if(typedComponentObject != nullptr) {
__block CGSize estimatedSize;
// synchronously dispatch to main thread if needed
if([NSThread isMainThread]) {
estimatedSize = [typedComponentObject measureSize:layoutConstraints.maximumSize.width];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
estimatedSize = [typedComponentObject measureSize:layoutConstraints.maximumSize.width];
});
}
return {
estimatedSize.width,
MIN(estimatedSize.height, layoutConstraints.maximumSize.height)
};
}
} else {
// on the very first call there is no componentView that we can query for the component height
// thus, a little heuristic: just put a height that is exactly height of letter "I" with default apple font and size from props
// in a lot of cases it will be the desired height
// in others, the jump on the second call will at least be smaller
const auto props = this->getProps();
const auto &typedProps = *std::static_pointer_cast<EnrichedTextInputViewProps const>(props);
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"I" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:typedProps.fontSize]}];
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStr);
const CGSize &suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(
framesetter,
CFRangeMake(0, 1),
nullptr,
CGSizeMake(layoutConstraints.maximumSize.width, DBL_MAX),
nullptr
);
return {suggestedSize.width, suggestedSize.height};
}
return Size();
}
} // namespace facebook::react