API REVIEW REQUEST: Public API for Node Orientation

Pavel Safrata pavel.safrata at oracle.com
Tue Oct 30 03:41:31 PDT 2012

Hi Steve,

On 29.10.2012 16:17, steve.x.northover at oracle.com wrote:
> On 29/10/2012 7:49 AM, Pavel Safrata wrote:
>> Hi Steve,
>> On 26.10.2012 18:41, steve.x.northover at oracle.com wrote:
>>>  Hi Pavel!
>>> > the inheritance ignoring reparenting.
>>> I don't think this was explained well in the documentation. There 
>>> should be no difference in visual behavior for the final result with 
>>> respect to the ordering of "orientate" and "insert" operations.
>> It seems to be explained well. This is how I understand it, please 
>> tell me which of the two statements is incorrect and why:
>> I have a left-to-right parent with an inheriting child. I create new 
>> parent, "orientate" it to right-to-left and "insert" it between the 
>> original parent and the child. Based on "If an application explicitly 
>> sets the root of a hierarchy to left-to-right and then reparents the 
>> hierarchy into a parent that is right-to-left, the hierarchy will 
>> remain left-to-right" I understand that the child will remain 
>> left-to-right.
>> Again, I have a left-to-right parent with an inheriting child. I 
>> create a new parent and "insert" it between the original parent and 
>> the child. Then I "orientate" it to right-to-left. Based on 
>> "Inheritance of node orientation allows application developers to 
>> specify the orientation of a root node and have it apply to all 
>> children" I understand that the new orientation will be applied to 
>> the child, so it will become right-to-left.
> The second statement is true.  The behavior can be summarized as: 
> "When not explicitly set, orientation is inherited".  I'm not sure 
> about the confusion in the first statement.  The sentence is meant to 
> mean that a hierarchy of nodes with an explicitly set root will always 
> have the explicitly set orientation of the root no matter where the 
> root is reparented.  Perhaps I should delete the sentence and replace 
> it with something like what I just said.

Got it. The confusion is that you mean reparenting the hierarchy 
including the root, I thought you meant leaving the root on place and 
reparenting its children to a different root. So I think it is ok (but 
yes, rewording the sentence may be useful, I'm not the only one to 
understand it that way).

>>> > How will mirroring cooperate with transformations?
>>> The mirroring transformation is transparent to the application and 
>>> is included automatically in local-to-scene (it's a bug if it is 
>>> not).  A public Mirror (or rather Flip) transformation would provide 
>>> API for this transformation, but I'm not sure why we would need to 
>>> do this.
>> Ah, that sounds quite good. The only thing that slightly bothers me 
>> is the state where there are no transformations anywhere and 
>> local-to-scene transform still reports it is not an identity 
>> transform, which seems confusing. But perhaps I'm too picky.
>>> > Shouldn't effectiveNodeOrientation be a property?
>>> That's a possibility.  It would be a properly that changed when 
>>> inherited orientation up the ancestor tree changed.  Do we have any 
>>> other properties like this in FX?
>> localToSceneTransform :-) But I admit there is some extra logic 
>> needed for such properties that we don't want to add blindly for 
>> performance reasons. So it may be better to just rename the getter to 
>> simply effectiveNodeOrientation().
> It might be that this needs to be a property after all.  The issue is 
> that a child may have state that is sets based on effective 
> orientation (say alignment of a text node) and this state needs to be 
> kept up to date with effective orientation.  However, providing the 
> method is defined correctly, there is nothing stopping it from 
> becoming a property in future.  I understand the performance issue.  I 
> will investigate further.

For a property we'd have effectiveNodeOrientationProperty() and 
getEffectiveNodeOrientation(). For a non-property we'd have something 
like effectiveNodeOrientation(). So I think we need to decide in the 

>>> > The same applies to isAutomaticallyMirrored.
>>> This is a mechanism that allows controls to opt out of mirroring. 
>>> Conceptually, it should be "... set once in the constructor and 
>>> never changed...".  I am not particularly happy with this method. Do 
>>> you have a better suggestion?
>> I've just discussed it locally, there are other options but not 
>> particularly nice as well. Guys here also prefer your solution 
>> because there is no need to store the value. So I'm withdrawing my 
>> objections, however, we believe that the method
>> - needs a better documentation that will state explicitly that it's 
>> supposed to return a constant
>> - should be protected (is there any reason for it to be public?)
>> - needs a name that doesn't start with "get" or "is"
> I will update the documentation to be better.  Can you show me other 
> examples where the "get" and "is" are not used in FX where they might 
> normally be used? 

For instance Point2D.magnitude() or Transform.determinant().

This is for the compatibility with tools and IDEs that use the naming to 
determine if it is a property or not.

> I am not a fan of protected.  Other than indicating explicitly that 
> subclasses are supposed to override this method, are there any other 
> benefits?

I believe it is a good approach not to publish things that don't need to 
be public. It is a node implementation thing, it should not confuse 
users in the list of publicly accessible methods. Other than you not 
being a fan, are there any concrete reasons for it to be public? (the 
fan thing doesn't leave much room for discussion)

>>> > Could you please elaborate on "the application will need to 
>>> configure parameters that are appropriate for the effect in both 
>>> orientations"?
>>> For example, if you want a light source effect to come from the 
>>> upper left corner when a control is RTL, you will need to create an 
>>> effect where the light source comes from the upper right corner so 
>>> that when the control is mirrored, it will come from the left.
>> Hmm, I would prefer to do that automatically, I don't think anybody 
>> wants the reversed shadow just because the reading direction is 
>> different. But it looks like it would require serious rework of 
>> effects which is probably not feasible..
> This issue is this:  You can't know what the application wants. In 
> some cases, it is using an effect as part of a control theme and it 
> makes sense for the effect to go from right-to-left when the 
> orientation changes.  In other cases, there is directionality involved 
> that should remain constant (like the car example in the documentation).

I think that effects are quite independent of what the application 
wants. The reflection always has to reflect the rendered node (having a 
right-to-left node with left-to-right reflection doesn't make any 
sense), and I think shadow is always dropped the same way based on the 
light source, regardless of it being right-to-left text or a car door. 
But again, I don't see any reasonable way to implement this right now.


>> Pavel
>>> Steve
>>> On 26/10/2012 9:16 AM, Pavel Safrata wrote:
>>>> Hi Steve,
>>>> I have a few comments/questions.
>>>> I'm not sure about the inheritance ignoring reparenting. I think 
>>>> that if an application will use orientation extensively it will 
>>>> reach a hard-to-trace "mess state" where most of the nodes 
>>>> "inherit" but they don't actually have the parent's value. Also it 
>>>> means that peforming "orientate parent" - "insert it into scene" 
>>>> will result in a different behavior than "insert" first and then 
>>>> "orientate", which seems confusing. What if I create a new node and 
>>>> insert it into scene, will it inherit form its new parent? In 
>>>> summary, I find this behavior hard to track and I think that when 
>>>> the value is Inherit it should always match the parent's orientation.
>>>> How will mirroring cooperate with transformations? For instance 
>>>> user can obtain local-to-scene transformation and if the mirrorring 
>>>> is not contained there, the computations with the transform (such 
>>>> as transforming points) will be wrong. Maybe we could just 
>>>> introduce a public Mirror (or rather Flip) transformation and use 
>>>> it publicly for the mirrorring?
>>>> How will it behave in 3D? Mirror nodes along X axis regardless of 
>>>> their z-direction volume?
>>>> Shouldn't effectiveNodeOrientation be a property? It seems it might 
>>>> make sense to observe the value. Also our naming convention is that 
>>>> you should not use getSomthing unless "something" is a property.
>>>> The same applies to isAutomaticallyMirrored. This method seems 
>>>> weird anyway. When and how often is it called? Can a node change 
>>>> the value dynamically? If yes, we should have a property, if not, 
>>>> we should make sure it doesn't - let the node call some init method 
>>>> in the constructor or something like that.
>>>> Could you please elaborate on "the application will need to 
>>>> configure parameters that are appropriate for the effect in both 
>>>> orientations"? How do I drop the shadow to the same direction for 
>>>> all nodes, specifically?
>>>> Thanks,
>>>> Pavel
>>>> On 23.10.2012 22:30, steve.x.northover at oracle.com wrote:
>>>>> Hi all,
>>>>> I have been looking into Node Orientation which is an API that 
>>>>> controls the directionality of a Node.  This is different from 
>>>>> BIDI or the BIDI algorithm which governs the direction of text. 
>>>>> Node orientation concerns the flow of visual data which is either 
>>>>> left-to-right or right-to-left.  The best example is a tree 
>>>>> control.  In tree control that is oriented right-to-left, the 
>>>>> expansion arrows point to the right and the branches of the tree 
>>>>> expand from the right to the left.
>>>>> https://wikis.oracle.com/display/OpenJDK/Node+Orientation+in+JavaFX
>>>>> Steve

More information about the openjfx-dev mailing list