Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8221722

ComboBox: uncontained value not shown in buttonCell

    Details

      Description

      Happens with an not-editable comboBox when setting a value that's not contained in the items "later" (than on startup) in its lifetime.

      To reproduce, compile and run the example below
      - click the button to set an uncontained value
      - expected and actual: uncontained value shown
      - open the dropdown and select a contained value
      - expected and actual: selected item shown
      - again click the button
      - expected: uncontained value shown
      - actual: buttonCell showing nothing

      The misbehavior turned up on SO https://stackoverflow.com/q/55378762/203657 and feels like a regression: the (very) old JDK-8127575 which exhibited the not-showing always, it was fixed some years ago.

      It might have been re-introduced by fixing JDK-8145588 (make sure that cell's selected property is updated in updateItem to allow for custom styles for that state) - at least removing that fix resulted in correct showing.

      The flow of control for updating a uncontained value in the skins is:

      1. listener to valueProperty calls - implicitely - comboBoxListViewSkin.updateDisplayNode

      2. if uncontained it reaches the snippet:

         // RT-21336 Show the ComboBox value even though it doesn't
         // exist in the ComboBox items list (part two of fix)
         buttonCell.updateIndex(-1);
         boolean empty = updateDisplayText(buttonCell, value, false);

      3. the updateIndex(-1) leads to marking the cell as dirty (bug fix JDK-8145588, done in cell.updateSelected)

              if (wasSelected != selected) {
                  markCellDirty();
              }

          // itemDirty and markCellDirty introduced as a solution for JDK-8145588.
          // In the fullness of time, a more fully developed solution can be developed
          // that offers a public API around this lazy-dirty impl.
          private boolean itemDirty = false;
          private final void markCellDirty() {
              itemDirty = true;
              requestLayout();
          }


      4. updateDisplayText changes the cell's text/empty properties under its feet, that is after doing this, cell.item != cell.text:

          cell.setText(s);
          cell.setGraphic(null);

      5. (last act ;) at layout time of the cell, the dirty marker triggers an updateItem with the cell's item (which at this time is != cell.text, see 4)

          if (itemDirty) {
              updateItem(getItem(), isEmpty());
              itemDirty = false;
          }

      On the whole there are two fishy parts:

      - changing cell properties under its feet
      - the dirty hot fix to guarantee valid selected in updateItem

      Not entirely certain how this can be fixed: the former might require a cell that can handle uncontained values on its own, the latter has deeper roots, see the discussion in the bug report

      Finally, the example to reproduce:

      public class ComboUncontainedBug extends Application {

          private Parent createContent() {
              ComboBox<String> combo = new ComboBox<>(
                      FXCollections.observableArrayList("Option 1", "Option 2", "Option 3")) ;
              Button uncontained = new Button("set value to uncontained");
              uncontained.setOnAction(e -> combo.setValue("uncontained value"));
              VBox content = new VBox(10, combo, uncontained);
              return content;
          }

          @Override
          public void start(Stage stage) throws Exception {
              stage.setScene(new Scene(createContent()));
              //stage.setTitle(FXUtils.version());
              stage.show();
          }

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

          @SuppressWarnings("unused")
          private static final Logger LOG = Logger
                  .getLogger(ComboUncontainedBug.class.getName());

      }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                aghaisas Ajit Ghaisas
                Reporter:
                fastegal Jeanette Winzenburg
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated: