On Fri, 25 Jun 2021 23:17:10 GMT, Kevin Rushforth <k...@openjdk.org> wrote:

> 1. `FocusPropertyBase` overrides `set` (which is unusual). The current 
> implementation (of `FocusedProperty `) has some custom logic as well, but it 
> didn't try to use the set method of a writable property. Also, you use a 
> writable property and don't override `invalidated`. Can you say why you made 
> the changes you made?

Technically, it doesn't _override_ `set`.
`FocusPropertyBase` extends `ReadOnlyBooleanPropertyBase`, and also defines a 
_new_ `set` method. As implemented, setting the value is completely decoupled 
from notifying listeners, which leads me directly to your next question...

> 2. I'm curious about the approach for notifying listeners. It seems similar 
> to what is currently done for `focusedProperty`, but there are differences. 
> Also, I'm not sure that the two newly added properties need to handle 
> notifications in the same way as focused. I can think of at least one 
> potential issue. If focus shifts from one node to another in the same parent, 
> you might end up notifying a parent's listeners even though its `focusWithin` 
> is unchanged.

`FocusPropertyBase.set` just records the new value, and the decision of whether 
to notify listeners is deferred until after all focus-related properties have 
been set on the current node and any of its parents. In the scenario you 
describe, the recorded value of `focusWithin` is changed twice, but ends up 
being the same value as before. In this case, 
`FocusPropertyBase.notifyListeners` will _not_ fire a change notification.

There's a test for this scenario: 
`FocusTest.testFocusWithinListenerIsNotInvokedIfPropertyDidNotEffectivelyChange`.

> 3. I think the way you are propagating `focusWithin` might not work if nodes 
> are added or removed from the scene graph.

Good point, I'll try to come up with some test cases to see if there are any 
issues.

> 4. Normally a read-only property that needs to be settable by the 
> implementation would use `ReadOnlyBooleanWrapper`. And then the public 
> property method would call `getReadOnlyProperty` to return the read-only 
> property to the user. The implementation would access the wrapper and you 
> don't need to cast. You could consider having `FocusPropertyBase` extend 
> `ReadOnlyBooleanWrapper`.

That could certainly be an option, although it would increase the memory 
footprint of `Node`.
I'm thinking instead to eagerly instantiate all three focus-related properties. 
In this case, the property field could be referenced directly, which would also 
remove the need for most casts.

I think that having the same deferred-notification property implementation for 
all three focus-related properties is the best approach, since the 
implementation guarantees that listeners are only notified after all changes 
are committed. At least, I see no upside to _not_ guarantee this. Maybe the 
atomicity guarantee for `focused`, `focusVisible` and `focusWithin` should be 
included in the documentation.

-------------

PR: https://git.openjdk.java.net/jfx/pull/475

Reply via email to