[API Review] RT-17024: Region pickOnBounds default value

Pavel Safrata pavel.safrata at oracle.com
Thu Feb 28 06:34:17 PST 2013


Hello,
should the pickOnBounds property's default value be changed to false for 
regions? This issue has been discussed several times over the last two 
years and was closed a month ago as "Won't fix". Lately, new evidence 
was discovered, so we are reopening the discussion once more, hopefully 
for the last time.

Jira: http://javafx-jira.kenai.com/browse/RT-17024

The old public discussion can be found in the history of this alias 
under subject "Region PickOnBounds default setting":
http://mail.openjdk.java.net/pipermail/openjfx-dev/2012-June/thread.html#2538
http://mail.openjdk.java.net/pipermail/openjfx-dev/2012-July/thread.html#2692

I'll try to summarize. Short version: with the current behavior, layout 
containers "eat" mouse events, not rectangular panes and panes with 
displaced children "eat" mouse events outside of their visible area, all 
that is confusing. Recently we've discovered that the current behavior 
is practically unusable in 3D. In the other hand, fixing the above is a 
backward incompatible change, causing behavioral problems to existing 
application. And it would have negative performance impact. Long version 
follows.

*Introduction*

Region is a base class for all controls and panes. It is a Parent, but 
unlike Group, it can have its own visual appearance - borders, fills, 
shape. During picking, we check the children and the region itself. As 
usual, the picking of the region itself has two modes - exact picking 
that picks it only on places where it's physically present (there is 
something visual defined), and picking on bounds which picks it anywhere 
within the rectangular bounds enclosing the whole region (including all 
its children). In this discussion we need to resolve if the default 
value of the pickOnBounds property for regions should be switched from 
true to false.


*Old arguments for switching region pickOnBounds to false by default* 
(you can skip this if you remember the old discussions):

It would make region consistent with all the other nodes we have.

People often use panes only for layout purposes and they don't expect 
them to "eat" mouse events. For example, I have several buttons of 
different sizes and want them to be vertically aligned. So I put them to 
a VBox. Now, in the rectangular area containing all the buttons, I can 
see the background, but cannot click it, because the VBox is picked. I 
get confused. Often it's hard to understand what area is actually 
covered by the container - with children of different sizes, some layout 
stretches/paddings/insets taking place etc.

The pane's bounds contain all its children. If I create a small Pane in 
top-left corner of the scene with a child in bottom-right corner of the 
scene, the pane's bounds cover the entire scene and I'm not able to 
click on anything else than the pane and its child. I don't understand 
why, because both visually and in source code there is nothing in 
between the pane and the child. (This is demonstrated in the 
EvilPane.java attached to the Jira issue).

We've encountered a bunch of other problems with it. For instance, 
PieChart slices are implemented as regions and they have to have 
pickOnBounds set to false because their bounds obscure the neighboring 
slices. When writing table (which has rows implemented as regions), a 
single cell with rowSpan=2 made the enlarged bounds of the row obscure 
the entire row below. And so on, time to time a new confused user 
appears and needs to hear the trick: call setPickOnBounds(false).


*New arguments for switching region pickOnBounds to false by default*:

The new evidence was discovered during the work on 3D. The 
PickOnBounds=true is pretty unusable in 3D. If a region has any children 
that are 3D or transformed in 3D, the picking won't work well. There are 
two reasons for that:

In 3D (with active depth buffer), picking considers all nodes and finds 
the node under cursor which is closest to the camera. Unlike in 2D, in 
3D scene graph node's bounds can be closer to the camera than its 
content. For example, if I place a button in a pane and rotate the 
button 45 degrees along X axis, I'll be unable to click the button, 
because the pane's box bounds will always be closer to the camera than 
the diagonally placed button. In general, with pickOnBounds set to true 
by default on regions, anything placed in a region and rotated in 3D 
can't be picked (by default of course). The same applies to nodes with 
varying Z translations, 3D primitives etc.

The second problem here is that a child is translated to positive 
numbers along Z axis may be obscured by the region's fill. It may even 
be partially obscured with the 3D rotations or 3D primitives. So to pick 
the correct node visible under mouse cursor in 3D, it's just not 
sufficient to check the bounds. So 3D apps would probably end up calling 
setPickOnBounds(false) on all regions/panes.


*Arguments against switching region pickOnBounds to false by default*:

First of all, it is a backward incompatible change! This is a strong 
reason. It will cause some behavioral problems to existing controls and 
applications. Some of the existing control skins rely on the current 
behavior and may misbehave after the change, it looks like nobody is 
able to fully assess the potential impact. There are other things like 
small icons implemented as regions (the arrow in combo box) which would 
now be picked only exactly on the shape etc. Another serious issue is 
that some users use empty panes for the purpose of blocking mouse 
events, for example during data loading or showing in-scene dialogs. All 
those things will have to be fixed in controls and user apps.

Then there is performance. Obviously, checking all the possibly complex 
visuals of a region takes more time than just checking the rectangular 
bounds. So changing the default value will have negative performance 
impact.

Finally, if the current behavior doesn't fit, there is fairly simple 
workaround - just call setPickOnBounds(false). You need to be aware of 
this, and for some use-cases you'll have to do this often, but still it 
lowers the push for the change considerably.


Do you want us to keep the current behavior or to do the change?
Thanks,
Pavel


More information about the openjfx-dev mailing list