Filing a bug never hurts. We'll either fix it, or close it and explain why it's not a bug then.

--
best regards,
Anthony

On 12/13/2013 11:17 PM, Tomas Mikula wrote:
I guess my main question is: should I file a bug on ListView?

Tomas

On Fri, Dec 13, 2013 at 8:15 PM, Tomas Mikula <tomas.mik...@gmail.com> wrote:
I just came across a strange case when these two are not equivalent.
Maybe that is no surprise to you, but it was to me. The case I
stumbled upon most likely has to do with ListView internals.

Substitute
a := ListView.widthProperty()
b := ListCell.prefWidthProperty()

and the code that demonstrates the difference:


public class Test extends Application {

     private static class MyCell extends ListCell<String> {
         public MyCell(ListView<String> lv) {
             setMaxWidth(Region.USE_PREF_SIZE);

             // !!! comment out exactly one of the following
             // !!! two lines to demonstrate the difference
             prefWidthProperty().bind(lv.widthProperty());
             lv.widthProperty().addListener(o -> setPrefWidth(lv.getWidth()));
         }

         @Override
         protected void updateItem(String item, boolean empty) {
             super.updateItem(item, empty);
             setGraphic(empty ? null : new TextFlow(new Text(item)));
         }
     }

     @Override
     public void start(Stage stage) {
         ListView<String> listView = new ListView<>();
         listView.setCellFactory(lv -> new MyCell(lv));
         listView.getItems().add("This is a very long line that needs
to be wrapped");

         StackPane stack = new StackPane();
         stack.getChildren().add(listView);
         Scene scene = new Scene(stack, 200, 100);
         stage.setScene(scene);
         stage.show();
     }

     public static void main(String[] args) {
         launch(args);
     }
}


When I run the "bind" version, the text shows up wrapped.
When I run the "addListener" version, the text shows up in one long line.

Do you think this is a bug in ListView, or is there a reasonable explanation?

Just for the record, I consider the "wrapping" behavior to be the correct one.


My *speculation* about the possible cause follows:

The only case I could come up with when
A) b.bind(a)
and
B) a.addListener(o -> b.set(a.get()))
are effectively different is when both of these conditions hold:
1) there is an invalidation listener set on b that causes b to become
valid (e.g. calls b.get()); and
2) a is invalidated twice in a row, but recomputes to the same value each time.

Now the scenarios for A) and B) differ:

Scenario A (b.bind(a)):
  - a is invalidated for the first time
  - b's invalidation listener is called for the first time
  - b is now valid
  - a is invalidated for the second time
  - b's invalidation listener is called for the *SECOND* time

Scenario B (a.addListener(o -> b.set(a.get()))):
  - a is invalidated for the first time
  - b is set to a.get() = x and b's invalidation listener is called for
the first time
  - b is now valid
  - a is invalidated for the second time
  - b is set to a.get() = x and b's invalidation listener is *NOT*
called for the second time, because b's value did not change

In scenario A, b's invalidation listener is called twice, while in
scenario B just once. If "weird things" are happening in this
invalidation listener, this can result in different behavior.

Now, if b is ListCell.prefWidthProperty(), scenario A and scenario B
cause it to be invalidated different number of times, which, my
*speculation*, could yield different behavior.
This is how far I got.

Cheers,
Tomas

Reply via email to