Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java: Expose extra functionality on CSSNode #202

Closed
wants to merge 491 commits into from

Conversation

rigdern
Copy link

@rigdern rigdern commented Jul 6, 2016

This change is needed to support inline views on React Native for Android.

daviskoh and others added 30 commits February 4, 2015 22:40
* add npm package
* add npm pretest script
Fix firefox iframe timing issue in test runners, fixes facebook#25
* add .jshintrc
* address semicolon errors
* ignore 'already defined' errors
Rework javascript api to match README
* modify .eslintrc w/ globals & rules
* use judgement in deciding bet proj style & eslint recommendation
* make
The JavaScript implementation of isDimDefined contains a check to ensure
that the dimension value is positive; the C and Java versions did not
have this check. As a result, a negative style value for 'width' (such
as that used by the "should layout node with negative width" test) would
have different layout under the C/Java implementation to the JavaScript
implementation.

This was hidden because the C/Java transpilers filtered out any negative
instantiation values from the test suite. In effect, the negative value
tests weren't running on the C/Java implementation.

This patch removes the negative value filter from the transpiler, and
makes the isDimDefined definition consistent between the three
implementations.
Normalized C and Java definition of isDimDefined.
Added support for min/max width and height constraints.
Chrome seems to always be ready on the first iteration, so this doesn't affect
Chrome, but on Firefox, the `iframe` is undefined in the recursive call.

This makes most of the test in `RunLayoutTests.html` pass in Firefox. The only
failing test is the one checking font sizes.
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 6, 2016
Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any
view can be nested within Text. One restriction of this feature is
that developers must give inline views a width and a height via
the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views
within Text, we create one special kind of span per inline view. This
span is called TextInlineViewPlaceholderSpan. It is the same size as
the inline view. It's job is just to occupy space -- it doesn't render
any visual. After the text is rendered, we query the Android Layout
associated with the TextView to find out where it has positioned each
TextInlineViewPlaceholderSpan. We then position the views to be at
those locations.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely
fit, the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 6, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 6, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
@emilsjolander
Copy link
Contributor

We typically just set the width/height/maxWidth/maxHeight of the root which layoutNode() is called on. Have you tried doing that? If so why does that not work for you

@rigdern
Copy link
Author

rigdern commented Jul 12, 2016

@emilsjolander That's a good point, I have not tried that. I will try that approach and get back to you. Note that the addition of getChildrenIterable will still be needed.

@ghost ghost added the CLA Signed label Jul 12, 2016
emilsjolander and others added 3 commits July 13, 2016 10:42
Revert "Correctly size cross axis when measuring flex basis"
This change is needed to support inline views on React Native
for Android.
@rigdern
Copy link
Author

rigdern commented Jul 20, 2016

@emilsjolander You were right. Changing the signature of calculateLayout was unnecessary. I updated the PR.

@ghost ghost added the CLA Signed label Jul 20, 2016
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 20, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
@ghost ghost added the CLA Signed label Jul 20, 2016
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 20, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
@ghost ghost added the CLA Signed label Jul 20, 2016
rigdern pushed a commit to rigdern/react-native that referenced this pull request Jul 20, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
@ghost ghost added the CLA Signed label Jul 20, 2016
@emilsjolander
Copy link
Contributor

@rigdern Due to large changes to the structure of the library syncing taking longer to turn on than expected master branch has been scrubbed of history. The old version is still available on the deprecated branch. I can add the getChildrenIterable method you needed if you don't want to add it yourself.

@emilsjolander
Copy link
Contributor

I got most if not all of the history back! rebasing might be enough

@rigdern
Copy link
Author

rigdern commented Jul 27, 2016

@emilsjolander Okay. I rebased and resubmitted the change as PR #212.

rigdern pushed a commit to rigdern/react-native that referenced this pull request Nov 3, 2016
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.
rigdern pushed a commit to rigdern/react-native that referenced this pull request Dec 20, 2018
Potential breaking change: The signature of ReactShadowNode's onBeforeLayout
method was changed
  - Before: public void onBeforeLayout()
  - After:  public void onBeforeLayout(NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer)

Depends on this css-layout PR:
facebook/yoga#202

Implements same feature as this iOS PR:
facebook#7304

Previously, only Text and Image could be nested within Text. Now, any view can
be nested within Text. One restriction of this feature is that developers must
give inline views a width and a height via the style prop.

Previously, inline Images were supported via
FrescoBasedReactTextInlineImageSpan. To get support for nesting views within
Text, we create one special kind of span per inline view. This span is called
TextInlineViewPlaceholderSpan. It is the same size as the inline view. Its job
is just to occupy space -- it doesn't render any visual. After the text is
rendered, we query the Android Layout object associated with the TextView to
find out where it has positioned each TextInlineViewPlaceholderSpan. We then
position the views to be at those locations.

One tricky aspect of the implementation is that the Text component needs to be
able to render native children (the inline views) but the Android TextView
cannot have children. This is solved by having the native parent of the
ReactTextView also host the inline views. Implementation-wise, this was
accomplished by extending the NativeViewHierarchyOptimizer to handle this case.
The optimizer now handles these cases:
  - Node is not in the native tree. An ancestor must host its children.
  - Node is in the native tree and it can host its own children.
  - (new) Node is in the native tree but it cannot host its own children. An
    ancestor must host both this node and its children.

Limitation: Clipping
====
If Text's height/width is small such that an inline view doesn't completely fit,
the inline view may still be fully visible due to hoisting (the inline view
isn't actually parented to the Text which has the limited size. It is parented
to an ancestor which may have a different clipping rectangle.). Prior to this
change, layout-only views had a similar limitation.

A number of commits were merged into this one:
  - 86cc9b4 # Fix some compiler errors and a runtime exception
  - 6a2ec85 # Emoticons can cause the Android app to hang
  - 4447065 # Fix inline view hang on Android 4.4.4
  - dbfe7be # Fix showing images inline with RTL text.
  - ea04463 # Yoga android fixes !!! incorporated into 92b13b64 Fix compilation errors

@MsSourceId: d08c770

fix of the bug in the first commit from the InlineViews
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.