Bug? Incorrect Top And Left values

keirS

Well-Known Member
Licensed User
Longtime User
A simple form with a button.


b1.png


The mouse clicked sub:
B4X:
Sub B1_MouseClicked(EventData As MouseEvent)
    Dim R As Reflector
    Log("Left Before Translate: " & Button1.Left)
   
    R.Target = Button1
    R.RunMethod2("setTranslateX","480","java.lang.double")
   
    Log("Left After Translate: " & Button1.Left)
   
   
End Sub

The buttons new position:


b2.png


The log output:

B4X:
Waiting for debugger to connect...
Program started.
Left Before Translate: 10
Left After Translate: 10

Looks to me like Left is using getLayoutX() (and possibly + getLayoutBounds().getMinX()) not getLayoutX() + getTranslateX() + getLayoutBounds().getMinX() for the Left property. The same applies to the Top property.

Changing the sub to:

B4X:
Sub B1_MouseClicked(EventData As MouseEvent)
    Dim R As Reflector
    Log("Left Before Translate: " & Button1.Left)
   
    R.Target = Button1
    R.RunMethod2("setTranslateX","480","java.lang.double")
   
    Log("Left After Translate: " & Button1.Left)

    Log("Layout X: " & R.RunMethod("getLayoutX"))
    Log("Translate X: " & R.RunMethod("getTranslateX"))
    R.Target = R.RunMethod("getLayoutBounds")
    Log("Bounds MinX: " & R.RunMethod("getMinX"))   
End Sub

gives me

B4X:
Left Before Translate: 10
Left After Translate: 10
Layout X: 10.0
Translate X: 480.0
Bounds MinX: 0.0
 

Informatix

Expert
Licensed User
Longtime User
A simple form with a button.


b1.png


The mouse clicked sub:
B4X:
Sub B1_MouseClicked(EventData As MouseEvent)
    Dim R As Reflector
    Log("Left Before Translate: " & Button1.Left)
  
    R.Target = Button1
    R.RunMethod2("setTranslateX","480","java.lang.double")
  
    Log("Left After Translate: " & Button1.Left)
  
  
End Sub

The buttons new position:


b2.png


The log output:

B4X:
Waiting for debugger to connect...
Program started.
Left Before Translate: 10
Left After Translate: 10

Looks to me like Left is using getLayoutX() (and possibly + getLayoutBounds().getMinX()) not getLayoutX() + getTranslateX() + getLayoutBounds().getMinX() for the Left property. The same applies to the Top property.

Changing the sub to:

B4X:
Sub B1_MouseClicked(EventData As MouseEvent)
    Dim R As Reflector
    Log("Left Before Translate: " & Button1.Left)
  
    R.Target = Button1
    R.RunMethod2("setTranslateX","480","java.lang.double")
  
    Log("Left After Translate: " & Button1.Left)

    Log("Layout X: " & R.RunMethod("getLayoutX"))
    Log("Translate X: " & R.RunMethod("getTranslateX"))
    R.Target = R.RunMethod("getLayoutBounds")
    Log("Bounds MinX: " & R.RunMethod("getMinX"))  
End Sub

gives me

B4X:
Left Before Translate: 10
Left After Translate: 10
Layout X: 10.0
Translate X: 480.0
Bounds MinX: 0.0
It may sound strange but it seems to me that what's expected. The left value is not supposed to change during the translation as the translation feature is a mean to shift the drawing of the node, not to change its coordinates. You have exactly the same thing under Android. The reason behind is to animate a node without really changing its position, or to compute within a given coordinate space while the drawing is made in a different coordinate space.
I implemented this feature in my SimpleGameEngine under the name DrawingOffset.
 

Informatix

Expert
Licensed User
Longtime User
From the Oracle documentation:
translateX
public final DoubleProperty translateXProperty
Defines the x coordinate of the translation that is added to this Node's transform.
The node's final translation will be computed as layoutX + translateX, where layoutX establishes the node's stable position and translateX optionally makes dynamic adjustments to that position.

This variable can be used to alter the location of a node without disturbing its layoutBounds, which makes it useful for animating a node's location.
 

keirS

Well-Known Member
Licensed User
Longtime User
It may sound strange but it seems to me that what's expected. The left value is not supposed to change during the translation as the translation feature is a mean to shift the drawing of the node, not to change its coordinates. You have exactly the same thing under Android. The reason behind is to animate a node without really changing its position, or to compute within a given coordinate space while the drawing is made in a different coordinate space.
I implemented this feature in my SimpleGameEngine under the name DrawingOffset.

The problem is B4J only has Left and Top which are meant to show the actual current position of the control and not the position just after LoadLayout.

The Java documentation also says:

The node's final translation will be computed as layoutX + translateX, where layoutX establishes the node's stable position and translateX optionally makes dynamic adjustments to that position.

Since B4J only has Left I would expect it to show the final translation value.
 

stevel05

Expert
Licensed User
Longtime User
It doesn't have translation either without the use of Reflection. If you use it, you will need to take that into account yourself.

You could always wrap the view and make the calculations in the wrapper.
 

keirS

Well-Known Member
Licensed User
Longtime User
And what other property the node has in Java? You have to compute the final position yourself. It's what the help text says.

Well I am sort of assuming the Left (and Top) are already computed fields consisting of region.getLayoutX() + region.getLayoutBounds().getMinX(). All I am asking is shouldn't it actually be region.getLayoutX() + region.translateX() + region.getLayoutBounds().getMinX().

To me it would seem logical to be:

LayoutX, LayoutY would be the position after LoadLayout() or the position when the control was added dynamically.
TranslateX, TanslateY would any changes to the X and Y after the control has been loaded / added.
 

keirS

Well-Known Member
Licensed User
Longtime User
It doesn't have translation either without the use of Reflection. If you use it, you will need to take that into account yourself.

You could always wrap the view and make the calculations in the wrapper.

I was actually playing with wrapping a library when I came across it. The B4J code is just a simple example of the problem.
 

keirS

Well-Known Member
Licensed User
Longtime User
Out of curiosity, why do you need to call "setTranslateX"? Why don't you update the Left property if you want to change the node location?

It's a library I am looking at wrapping. It's generic resize/move control library with features like bounds checking and collision detection It allows users to change the layout of a form and save it as a preference file and then reload it next time the app is run. It uses setTranslateX,Y values for all the user changes to layout. I need some of the features so I thought I would wrap it rather than start from scratch.
 
Top