I have the following problem:
I have ListView<ViewsRecord>
where ViewsRecord
has property int favorites
.
If favorites > 0
it's in favorites, and if favorites == 0
it's a regular row (not favorite).
Now what I want to do is:
- When user selects cells (in multiple select mode) those cells will have default selected background (like:
-fx-background-color: -fx-selection-bar
) When cells aren't selected by the user:
2.1. if cell isn't in favorites it has regular bacground (ex. white)
2.2. if cell is in favorites it has green background
So far I came up with this solution, but it's ugly code, and I wonder if there's easiest way to do that.
Further more, I had to use setUserData()
to check if cell should be selected or not, otherwise during the list scroll, or select - cells had randomly changed their colors. (I assume it's because reusable objects are stored in memory and updateItem() isn't always fired).
Here's my code:
list.setCellFactory(new Callback<ListView<ViewsRecord>, ListCell<ViewsRecord>>(){
@Override
public ListCell<ViewsRecord> call(ListView<ViewsRecord> param) {
ListCell<ViewsRecord> cell = new ListCell<ViewsRecord>(){
@Override
protected void updateItem(ViewsRecord item, boolean empty) {
super.updateItem(item, empty);
if(!empty){
if(item.getFavorites() > 0){ //favorite view
if(!isSelected()){
setStyle("-fx-background-color: darkseagreen;");
}
setUserData(new Integer(1));
} else { //normal view
if(!isSelected()){
setStyle("-fx-background-color: white;");
}
setUserData(new Integer(0));
}
setText(item.toString());
} else { //empty view
setText(null);
setStyle("-fx-background-color: white;");
setUserData(new Integer(0));
}
}
};
//fix bacground color when cell is selected
cell.selectedProperty().addListener( (obsVal, oldVal, newVal) -> {
if(newVal){
cell.setStyle("-fx-background-color: -fx-selection-bar;");
} else {
if((Integer)cell.getUserData() == 1){ //favorite
cell.setStyle("-fx-background-color: darkseagreen;");
} else { //normal
cell.setStyle("-fx-background-color: white;");
}
}
});
return cell;
}
});
EDIT
Thanks to jns I've managed to simplify the code. Current version:
list.setCellFactory(new Callback<ListView<ViewsRecord>, ListCell<ViewsRecord>>(){
@Override
public ListCell<ViewsRecord> call(ListView<ViewsRecord> param) {
final PseudoClass FAVORITE_PSEUDO_CLASS = PseudoClass.getPseudoClass("favorite");
ListCell<ViewsRecord> cell = new ListCell<ViewsRecord>(){
@Override
protected void updateItem(ViewsRecord item, boolean empty) {
if(!empty){
//favorite or not, and not selected
pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, (item.getFavorites() > 0) && !isSelected());
setText(item.toString());
} else {
setText(null);
//empty
pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, false);
}
super.updateItem(item, empty);
}
};
cell.selectedProperty().addListener( (obsVal, oldVal, newVal) -> {
if(newVal){
//selected
cell.pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, false);
} else {
//favorite or not
cell.pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, cell.getItem().getFavorites() > 0);
}
});
return cell;
}
});