From the Grid context menu I am getting an Object (Book) which I need to open in the editing form. However, some books are multi-volume series and I need to choose one volume. For this purpose I have written another class extending com.vaadin.flow.component.dialog.Dialog
public class VolumeSelector extends Dialog {
private final Series series;
private final Button done;
private final ListBox<Book> selection;
private Book selectedBook;
public VolumeSelector(Series series) {
this.series = series;
this.setModal(true);
selection = new ListBox<>();
List<Book> books = new ArrayList<>();
books.add(series);
books.addAll(series.getVolumes());
selection.setItems(books);
selection.addComponents(series, new Hr());
selection.setRenderer(new ComponentRenderer<>(
book -> new Text(book.getTitle())));
selection.setValue(series);
this.add(selection);
done = new Button("Done",
(e) -> {
this.selectedBook = selection.getValue();
this.close();
});
this.getFooter().add(done);
this.setModal(true);
this.setCloseOnOutsideClick(false);
this.setCloseOnEsc(true);
Button closeButton = new Button(new Icon("lumo", "cross"),
(e) -> {
this.selectedBook = null;
this.close();
});
closeButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
closeButton.onEnabledStateChanged(true);
this.getHeader().add(closeButton);
}
/**
* @return the selectedBook
*/
public Book getSelectedBook() {
return selectedBook;
}
}
Now from the context menu I am calling the following function:
@SuppressWarnings("SleepWhileInLoop")
private Book selectVolume(Series series) {
VolumeSelector vs = new VolumeSelector(series);
this.doneWithBookSelection = false;
vs.addOpenedChangeListener(
event -> {
if(!event.isOpened()) {
this.doneWithBookSelection = true;
}
}
);
vs.open();
while(!doneWithBookSelection) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
}
return vs.getSelectedBook();
}
The dialog won't show up in this case. If I remove (comment out) while loop, dialog does shows up, but only after function returns null from the function. Therefore, I can't get the value. Can anyone please tell me what I am doing wrong and how to fix it.
I did resolve this problem by adding PropertyChangeSupport to the class.
private final transient PropertyChangeSupport propertyChangeSupport = new java.beans.PropertyChangeSupport(this);
And in the the context menu I put this code:
propertyChangeSupport.addPropertyChangeListener("selectedBook", new BookEditor());
this.editBookMenuItem = addItem("Edit book info",
event -> event.getItem().ifPresent((Book book) -> {
if (book instanceof Series) {
selectVolume((Series) book);
}
else {
this.setSelectedBook(book);
}
}));
And farther down in the code I added the following:
public void setSelectedBook(Book selectedBook) {
org.garik.encyclopedia.model.Book oldSelectedBook = this.selectedBook;
this.selectedBook = selectedBook;
propertyChangeSupport.firePropertyChange("selectedBook", oldSelectedBook, selectedBook);
}
private void selectVolume(Series series) {
VolumeSelector vs = new VolumeSelector(series);
vs.addOpenedChangeListener(
event -> {
if (!event.isOpened()) {
setSelectedBook(vs.getSelectedBook());
}
}
);
vs.open();
}
private class BookEditor implements PropertyChangeListener {
public BookEditor() {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
Book book = (Book) evt.getNewValue();
if (book != null) {
BookPanel bookPanel = config.getBookPanel();
bookPanel.setBook(book);
bookPanel.open();
}
}
}
Everything is working as expected now. Dialog is opened and it does return the value I am looking for.